Jak se vyhnout frustraci s Java eventy?

Zelenac

Jak se vyhnout frustraci s Java eventy?
« kdy: 02. 02. 2016, 14:07:07 »
Zdravím,

 zajímalo by mně, jak by zdejší Java guru vyřešili tohle:

Dělám si client-server komunikační aplikaci, kterážto se později vyvine do P2P. To vyžaduje knihovnu, která obstarává naslouchání na portu (SocketServer) a dále obsluhu vzniklých Socketů (keepAlive, odesílání práv, příjem zpráv, rušení připojení, info o délce neaktivity socketů, atd.). Dále je třeba vytvořit další zaobalení těchto tříd a vytvořit třídu která v sobě sdružuje další funkcionality: typ odeslané zprávy (číže protokoly pro: chat, soubor, signalizace). A vzniknout další a další.

Je zřejmé, že takováto věc vyžaduje spoustu událostí, píše-li se správně objektově a to je prostě v Javě boží utrpení. Pořád dokolečka psát: listener kolekce, metody pro vyvolání událostí, foreache, interfacy. Obzvláště ty interfacy jsou velká lahůdka: co když třída má 20 událostí a já chci v jiné třídě reagovat pouze na 1? To musím buďto:

1. Napsat jednotný IListener interface kde budou všechny události k dané třídě. To vede k tomu, že pakliže v nějaké jiné třídě potřebuji jen události 2, stejně se mi jich tam bouchne dalších 18 které tam budou v souboru nevyužité strašit.
2. Napsat pro každou jednu událost jeden interface. No tak to tedy hodně štěstí při vývoji takovéto architektury, protože každý interface musí být v samostatném souboru, což je obrovská halda úkonů, která je k tomu nutná.

Prostě takové aplikace je plná událostí, nejde to elegantně řešit nijak jinak. Co s takovýmto hrozivým jazykem?

PS: Píšu to v Javě ze studijích důvodů, jinak bych to napsal hned v Qt.
« Poslední změna: 02. 02. 2016, 18:37:28 od Petr Krčmář »


Re:Java se vyhnout frustraci s Java eventy?
« Odpověď #1 kdy: 02. 02. 2016, 14:16:19 »
Trebas ve swingu se casto objevuje pattern, ze mas interface FooListener s dvaceti metodami a pro snazsi pouziti existuje abstraktni trida AbstractFooListener, kde maji vsechny ty metody defaultni (typicky prazdnou) implementaci. Pak dedis z AbstractFooListener. Kod uvnitr frameworku temer vsechno typuje na interface (FooListener).

kukacka

Re:Java se vyhnout frustraci s Java eventy?
« Odpověď #2 kdy: 02. 02. 2016, 14:21:58 »
Tvuj problem jsem prilis nepochopil, ale pouze strucne k jave, kterou jsi mozna jeste uplne neovladl. Neni pravda, ze kazdy intefarce musi byt v samostatnem souboru (BTW proc by to melo vadit?). Pokud je caste, ze se implementuje pouze cast interface, lze pouzit default implementace v interface nebo treba skeletalni implementace, coz umoznuje vice castecnych specializaci.

Re:Java se vyhnout frustraci s Java eventy?
« Odpověď #3 kdy: 02. 02. 2016, 14:25:39 »
Za prvé bych doporučil nevynalézat kolo a použít na to komunikaci hotovou knihovnu – doporučuju Netty. Dále píšete o správném objektovém programování, to nejde dohromady s tím, že třída reaguje na 20 událostí. Ve správném objektovém programování má třída jednu zodpovědnost, bude tudíž mít jen pár metod nebo reagovat jen na pár událostí.

Co s takovýmto hrozivým programátorem?
Buď se to programátor naučí, nebo bude lepší, když bude dělat něco jiného.

Turban Legend

Re:Java se vyhnout frustraci s Java eventy?
« Odpověď #4 kdy: 02. 02. 2016, 14:38:13 »
Nebudu řešit širší souvislosti, protože to by bylo na dlouho… tak jen stručně k těm implementačním detailům.

Když se ti nelíbí rozhraní/třída s mnoha metodami, máš i další možnosti:

a) Rozhraní bude mít hodně metod, ale uděláš k němu i výchozí implementaci (abstraktní třídu), která implementuje všechny metody, ale bude je mít prázdné. Ve své implementaci podědíš tuto abstraktní a překryješ jen metody (události), které tě zajímají.

b) Využiješ vhodně dědičnost nebo kompozici – rozhraní bude mít jednu nebo několik málo metod typu processEvent(Event e), přes kterou půjde všechny typy událostí, a implementace si z těch (komponovaných nebo poděděných objektů) vybere to, co ji zajímá.

c) Rozděl si události do logických skupin a pro ně vytvoř rozhraní listenerů – jednak je to vhodnější návrh a jako pozitivní vedlejší efekt tam nebudeš mít tolik metod. Tenhle přístup můžeš zároveň kombinovat s a)

Pro nízkoúrovňové věci (implementaci síťového protokolu) ti dobře poslouží Netty, jak píše Filip.


Kit

Re:Java se vyhnout frustraci s Java eventy?
« Odpověď #5 kdy: 02. 02. 2016, 14:44:29 »
Správně je odpověď č. 2. Vytvoření dvaceti rozhraní nevidím jako nějaký problém. Těch rozhraní však nemusí být 20, ale tolik, kolik je jich potřebných (některé události bývají vždy obsluhovány ve skupině). Výhodou takových rozhraní je, že se často dají používat napříč celou aplikací, tedy nejen určitou skupinou tříd z jednoho balíku.

O tom v podstatě hovoří Interface Segregation Principle ze SOLID.

Jak však již bylo uvedeno, obsluhovat 20 událostí v jedné třídě je přinejmenším podivné a těžko slučitelné s objektovým programováním - ukazuje to na závažné porušení Single Responsibility Principle, opět ze SOLID.

andy

Re:Java se vyhnout frustraci s Java eventy?
« Odpověď #6 kdy: 02. 02. 2016, 14:58:08 »
mozes si rozdne pomoct. java neni c++ a da sa vselico robit "za behu". mrkni napr na google eventbus

Zelenac

Re:Java se vyhnout frustraci s Java eventy?
« Odpověď #7 kdy: 02. 02. 2016, 15:21:52 »
Za prvé bych doporučil nevynalézat kolo a použít na to komunikaci hotovou knihovnu – doporučuju Netty. Dále píšete o správném objektovém programování, to nejde dohromady s tím, že třída reaguje na 20 událostí. Ve správném objektovém programování má třída jednu zodpovědnost, bude tudíž mít jen pár metod nebo reagovat jen na pár událostí.

Co s takovýmto hrozivým programátorem?
Buď se to programátor naučí, nebo bude lepší, když bude dělat něco jiného.

1. Ad Nevynálezat kolo - to v IT solo znamená nedělat vůbec nic, neb vše možné pro jednince proveditelné už existuje a ještě v několika variantách. Navíc píšu to, jak si můžete ráčit všimnou, ze studijních důvodů - jinak bych se neštval s Javou.
2. Ad Třída nemá mít 20 událostí a pokud ano, je něco blbě. Jsem lenivý a tak si značně ulehčím odpověď na tento žvást: Každé přinejmenším GUI je miriáda událostí.


Kukacka:
public interface musí být v samostatném souboru, vždy po jednom - alespoň dle Eclipse. Private interface by mi byl v mé situaci jaksi k ničemu.

Zatím nejlepší řešení je dle mého názoru použít tu abstraktní třídu, jak zmiňuje Turban Legend a Ondrej Satai Nekola. Tou mi ale odpoadne pouze nepříjemnost s interfacováním, zůstává mi pořád ještě:

1. Dokolečka psát addListener, removeListener, ArrayList<Listener> listeners, foreache, instrafacy a teď ještě i abstraktní třídy.
2. Ve třídách reagujících na událost tyto interfacy/abstraktní třídy následně implementovat.
3. S množstvím event přibývá chaos ten, že nevím, jaký inteface/abstraktClass patří ke které třídě, aniž bych použil funkci hledat a zjistil si to ručně. (v C# nebo v Qt stačí mrknout k eventě/signálu v našeptávači a napíše mi to popis eventy, stejně jako je to u popisů metod - je to kompfortní, je to rychlejší. V javě tato funkcionalita jaksi zcela odpadá.)

Filip

Re:Java se vyhnout frustraci s Java eventy?
« Odpověď #8 kdy: 02. 02. 2016, 15:27:16 »
dela se to pomoci aspektoveho programovani. Pokud pouzijes treba google eventbus (jak pise andy), tak nad metodu das @Subscribe a ta bude prijimat jen event ktery potrebujes.

Re:Java se vyhnout frustraci s Java eventy?
« Odpověď #9 kdy: 02. 02. 2016, 15:29:51 »
2. Ad Třída nemá mít 20 událostí a pokud ano, je něco blbě. Jsem lenivý a tak si značně ulehčím odpověď na tento žvást: Každé přinejmenším GUI je miriáda událostí.

Reagujes na neco jineho. V systemu muze byt udalosti docela dost, ale nemusis mit (pri slusnem navrhu) vsechno na jedne hromade v jedne tride.

Kukacka:
public interface musí být v samostatném souboru, vždy po jednom - alespoň dle Eclipse. Private interface by mi byl v mé situaci jaksi k ničemu.

Ja bych to nedelal, ale pokud chces workaround, tak staticke verejne interfacy uvnitr tridy, ktera ti slouzi jenom jako namespace. Ale ve skutecnosti to asi nechces a chces mit samostatne soubory (ostatne proc ne?)

1. Dokolečka psát addListener, removeListener, ArrayList<Listener> listeners, foreache, instrafacy a teď ještě i abstraktní třídy.

Vidim tam prostor pro refaktoring spolecne funkcionality? Interfacy musis psat tak jako tak. A abstraktni tridy ti udela zadarmo IntelliJ.

2. Ve třídách reagujících na událost tyto interfacy/abstraktní třídy následně implementovat.

Ten kod preci potrebujes tak jako tak.

3. S množstvím event přibývá chaos ten, že nevím, jaký inteface/abstraktClass patří ke které třídě, aniž bych použil funkci hledat a zjistil si to ručně. (v C# nebo v Qt stačí mrknout k eventě/signálu v našeptávači a napíše mi to popis eventy, stejně jako je to u popisů metod - je to kompfortní, je to rychlejší. V javě tato funkcionalita jaksi zcela odpadá.)

Pouzivas nejake slusne IDE? (cimz myslim IntelliJ, pochopitelne)

Re:Java se vyhnout frustraci s Java eventy?
« Odpověď #10 kdy: 02. 02. 2016, 15:34:59 »
Navíc píšu to, jak si můžete ráčit všimnou, ze studijních důvodů - jinak bych se neštval s Javou.

Pokud to píšete ze studijních důvodů, doporučoval bych naučit se v Javě programovat a naučit se používat IDE. Zatím to vypadá, že studujete to, zda se v Javě dá programovat, i když to neumíte a umět nechcete – ano, dá, a jako v kterémkoli jiném jazyce, výsledek bude stát za … vy víte co.

Lol Phirae

Re:Java se vyhnout frustraci s Java eventy?
« Odpověď #11 kdy: 02. 02. 2016, 15:43:50 »
zda se v Javě dá programovat, i když to neumíte a umět nechcete – ano, dá, a jako v kterémkoli jiném jazyce, výsledek bude stát za … vy víte co.

A oproti jiným jazykům to má navíc tu výhodu, že to bude pomalé a neskutečně rozežrané.  ;D  8)

none_

Re:Java se vyhnout frustraci s Java eventy?
« Odpověď #12 kdy: 02. 02. 2016, 15:52:09 »
1. Dokolečka psát addListener, removeListener, ArrayList<Listener> listeners, foreache, instrafacy a teď ještě i abstraktní třídy.
2. Ve třídách reagujících na událost tyto interfacy/abstraktní třídy následně implementovat.
3. S množstvím event přibývá chaos ten, že nevím, jaký inteface/abstraktClass patří ke které třídě, aniž bych použil funkci hledat a zjistil si to ručně. (v C# nebo v Qt stačí mrknout k eventě/signálu v našeptávači a napíše mi to popis eventy, stejně jako je to u popisů metod - je to kompfortní, je to rychlejší. V javě tato funkcionalita jaksi zcela odpadá.)

1. Proc? Tak snad budes mit jednu trida, ktera prijme vsechny eventy a nasledne je rozhazi vsem, kteri se do ni zaregistruji. A pokud je struktura listeneru staticka, tak ani nemusis mit addListener, ale proste ty hlavni tride posles vsechny potencialni listenery.
2. No tak pokud chces reagovat na nejakou event, tak vetsinou musis implementovat tu metodu, co to udela.:D
3. WTF? Co si predstavujes pod pojmem "popis eventy"? Event je proste POJO. Jestli to ma mit link na to, kdo ji vyhodil, musis si tam ten link dodat.

Podle tveho popisu, to co ma Qt je nejaky druh UI eventy, ktera uz je specializovana. Samozrejme to, co potrebuje UI event nepotrebuji nejaky udalosti mezi servery na backendu, takze je blbost pouzivat UI event.

Zacinam mit pocit, ze jsi bud nejakej Troll nebo mas vazne nedostatky ve znalostech a svadis to na jazyk.

none_

Re:Java se vyhnout frustraci s Java eventy?
« Odpověď #13 kdy: 02. 02. 2016, 15:53:19 »
A oproti jiným jazykům to má navíc tu výhodu, že to bude pomalé a neskutečně rozežrané.  ;D  8)
Tak jsem se spletl. Troll je nekdo jinej...

Re:Java se vyhnout frustraci s Java eventy?
« Odpověď #14 kdy: 02. 02. 2016, 15:56:56 »
zda se v Javě dá programovat, i když to neumíte a umět nechcete – ano, dá, a jako v kterémkoli jiném jazyce, výsledek bude stát za … vy víte co.

A oproti jiným jazykům to má navíc tu výhodu, že to bude pomalé a neskutečně rozežrané.  ;D  8)

Bullshit.