Jak se vyhnout frustraci s Java eventy?

Kit

Re:Java se vyhnout frustraci s Java eventy?
« Odpověď #15 kdy: 02. 02. 2016, 16:03:35 »
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í.

Není přece nutné všech 20 událostí obsluhovat v jedné obludné třídě. Ta třída si prostě zaslouží rozdělení do více menších tříd dle kompetencí.


perceptron

Re:Java se vyhnout frustraci s Java eventy?
« Odpověď #16 kdy: 02. 02. 2016, 16:10:04 »
si pozrite ako su eventy v swingu

mate objekt Event, ten nesie timestamp, kto ho odoslal. mate napr. mouseclick event, ktory nesie x y koordinaty, tlacidlo mysi atd

mate listener MouseListener s piatimi metodami (kliklo sa, stlacilo sa stlacidlo, pustilo sa, +2x fokus)

mate MouseAdapter ktory prekryje vsetky metody prazdnym spravanim takze nemusite potom implementovat 5 metod ale len tu ktoru vam treba

---
alternativne: publikujete do generickeho busu konkretne objekty typu event (pripojil sa klient event, odpojil sa klient event)
mate genericky interfejs void handle(Event) ktory sa rozhodne ci to obsluzi alebo nie

alternativne: java ee / spring styl: publikujete do generickeho busu lubovolne objekty, anotujete metodu ako posluchaca na event daneho typu, reflexiou zistite ci anotovana metoda posluchaca vie zozrat dany objekt, ak ano, zavolate ju dynamicky


perceptron

Re:Java se vyhnout frustraci s Java eventy?
« Odpověď #17 kdy: 02. 02. 2016, 16:25:28 »
Citace
. 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á.
obrovska halda ukonov? to buildujete z terminalu cez javac? za normalnych okolnosti je to File | New | Interface


andy

Re:Java se vyhnout frustraci s Java eventy?
« Odpověď #18 kdy: 02. 02. 2016, 16:39:59 »
Toto je taky ten klasicky problem - snaha aplikovat zlozvyky z ineho jazyka do druheho. Klasicky C++ pristup robit vsetko rucne, alebo mat cely program v jednom subore sa v jave velmi nenosi (nastastie). V eclipse je ta halda ukonov par klavesovych skratiek. Ale hlavne nie je nutne davat to do samotnych suborov. Co sa tyka nejakej absencie na eventy - .net bezi uz aj na linuxe, v c# mate delegatov, tak sa nemusite trapit s javou ked vas neoslovila...

Kit

Re:Java se vyhnout frustraci s Java eventy?
« Odpověď #19 kdy: 02. 02. 2016, 16:52:09 »
Toto je taky ten klasicky problem - snaha aplikovat zlozvyky z ineho jazyka do druheho. Klasicky C++ pristup robit vsetko rucne, alebo mat cely program v jednom subore sa v jave velmi nenosi (nastastie). V eclipse je ta halda ukonov par klavesovych skratiek.

Ani ve Vimu to není tolik úkonů, aby to stálo za řeč...

Zelenáč se zřejmě pokouší psát třídy, které jsou delší než 100 řádek. Pak mu z toho vznikají tyhle komplikace.


Zelenac

Re:Java se vyhnout frustraci s Java eventy?
« Odpověď #20 kdy: 02. 02. 2016, 17:17:38 »
Toto je taky ten klasicky problem - snaha aplikovat zlozvyky z ineho jazyka do druheho. Klasicky C++ pristup robit vsetko rucne, alebo mat cely program v jednom subore sa v jave velmi nenosi (nastastie). V eclipse je ta halda ukonov par klavesovych skratiek. Ale hlavne nie je nutne davat to do samotnych suborov. Co sa tyka nejakej absencie na eventy - .net bezi uz aj na linuxe, v c# mate delegatov, tak sa nemusite trapit s javou ked vas neoslovila...

Prý se v Javě příliš nenosí... už jsem si hezkých pár knihoven stáhnul a chytal mě amok, když jsem chtěl reagovat v nějaké na eventu v anonymně vytvořené instanci a vygenerovalo se mi 15 metod k implementaci.


Kit: ne právěže nepíšu víc než 100 řádků na třídu. To že někde vznikne 20 událostí neznaméná, že ta třída musí mít stovky řádků. Bude to třída, která zaobaluje celou hierarchii tříd a tvoří k ní takový finální handler.

Zelenac

Re:Java se vyhnout frustraci s Java eventy?
« Odpověď #21 kdy: 02. 02. 2016, 17:25:15 »
Takže dal jsem dokupy s vaší pomocí toto řešení:

Rozhraní k událostem vyvolaným v objektu vytvořím pomocí Interfacu, kterého bude implementovat Abstraktní třída. Čili udělám to tak, jak to dělá Swing. To je docela hezké řešení.

Teď ústavičné psaní AddLister a dalších: zde by se tedy mohlo dědit z nějaké třídy, která bude mít ty metody a atributy již napsány. Místo psaní vlastní mě napadá použít třídu Observable. Je to dobrý nápad?

koZel

Re:Java se vyhnout frustraci s Java eventy?
« Odpověď #22 kdy: 02. 02. 2016, 17:36:26 »
Není to dobrý nápad, chtělo by to nějakou generickou třídu Observable<E>

Ivan

Re:Java se vyhnout frustraci s Java eventy?
« Odpověď #23 kdy: 02. 02. 2016, 18:11:34 »
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í.

Není přece nutné všech 20 událostí obsluhovat v jedné obludné třídě. Ta třída si prostě zaslouží rozdělení do více menších tříd dle kompetencí.

Existuji i vyjimky. Napriklad parsery anebo cokoliv co ma v sobe nejaky stavovy automat. Samozrejme, ze muzete i DFA rozdelit do desitek trid, ale vysledek bude nejspis hure udrzovatelny. Podobne se to s implementaci nejakeho sitoveho protokolu.

Kit

Re:Java se vyhnout frustraci s Java eventy?
« Odpověď #24 kdy: 02. 02. 2016, 18:28:24 »
Není přece nutné všech 20 událostí obsluhovat v jedné obludné třídě. Ta třída si prostě zaslouží rozdělení do více menších tříd dle kompetencí.

Existuji i vyjimky. Napriklad parsery anebo cokoliv co ma v sobe nejaky stavovy automat. Samozrejme, ze muzete i DFA rozdelit do desitek trid, ale vysledek bude nejspis hure udrzovatelny. Podobne se to s implementaci nejakeho sitoveho protokolu.

I stavový automat se zpravidla dá napsat rozumně tak, aby obsluha stavu byla jedním příkazem a na jednom řádku. Pokud těch stavů je 200, tak metoda holt bude mít 200+něco řádek. Nebudu to řezat jen kvůli tomu, abych se přísně držel nějakého pravidla, které by v takovém případě neplnilo svůj účel - přehlednost kódu.

Takových metod je však minimum a proto se na ně dají uplatnit výjimky z jinak přísných pravidel.

Zelenac

Re:Jak se vyhnout frustraci s Java eventy?
« Odpověď #25 kdy: 02. 02. 2016, 20:02:42 »
Takže přidal jsem si:

Citace
package gld.util;

import java.util.ArrayList;
import java.util.Collection;

/** Simple observable with generics
 */
public class Observable<T> {

    protected Collection<T> observers = new ArrayList<>();

    public void addObserver(T observer) {
        synchronized (observers) {
            if (!observers.contains(observer)) {
                observers.add(observer);
            }
        }
    }

    public void removeObserver(T observer) {
        synchronized (observers) {
            observers.remove(observer);
        }
    }

    public void clearObservers() {
        synchronized (observers) {
            this.observers.clear();
        }
    }
}

Nicméně s tímto vyvstává další problém a to je multinásobné dědičnost. Tedy nevyvstává, protože v Javě tato možnost není, v C++ je. Já si totiž podědím tuto třídu, ale to mi znemožní, abych si kupříkladu udělal třídu, rozšiřující nějakou jinou knihovní třídu. Příklad: budu chtít rozšířit třídu Socket o události. Potom nemůžu už dědit tuto mou třídu. To je past vedle pasti ta Java.

Kit

Re:Jak se vyhnout frustraci s Java eventy?
« Odpověď #26 kdy: 02. 02. 2016, 20:23:33 »
Kód: [Vybrat]
protected Collection<T> observers = new ArrayList<>();

Proč tu kolekci observers nemáš synchronized?

Re:Jak se vyhnout frustraci s Java eventy?
« Odpověď #27 kdy: 02. 02. 2016, 20:26:08 »
Je účelem tohoto tématu, abyste předváděl, jak to opravdu neumíte a nechcete umět, nebo se chcete něco naučit? Zatím to vypadá na to první.

Zelenac

Re:Jak se vyhnout frustraci s Java eventy?
« Odpověď #28 kdy: 02. 02. 2016, 20:35:08 »
Kód: [Vybrat]
protected Collection<T> observers = new ArrayList<>();

Proč tu kolekci observers nemáš synchronized?

A jak ji mám mit synchronized? Vím že metody se dají dát jako synchronized, v tom případě se zamyká tuším celý objekt, ale atributy?

Re:Jak se vyhnout frustraci s Java eventy?
« Odpověď #29 kdy: 02. 02. 2016, 20:35:41 »
Kód: [Vybrat]
protected Collection<T> observers = new ArrayList<>();

Proč tu kolekci observers nemáš synchronized?

Ono je to celé špatně. Místo synchronized  kolekce by bylo lepší použít některou z kolekcí java.util.concurrent. Navíc tam nemá žádné čtení kolekce, takže je ta kolekce úplně zbytečná. Místo toho si stěžuje, že nemá vícenásobnou dědičnost, aby si v tom kódu udělal ještě větší guláš.

Řešením by byla třída, která bude obhospodařovat posluchače – bude je umět zaregistrovat a odregistrovat a bude umět všem registrovaným posluchačům poslat zprávu. Zároveň si ošetří konkurenční přístup. To je kód právě pro jednu třídu, není potřeba žádná vícenásobná dědičnost a ta třída se použije ve třídách, které potřebují posílat nějaké události registrovaným posluchačům. (Ano, v jiných jazycích by se to dalo řešit vícenásobnou dědičností místo kompozice, ale to by bylo porušení principu single responsibility.)