OOP jazyk - problém klasického stříhu

Kit

Re:OOP jazyk - problém klasického stříhu
« Odpověď #45 kdy: 06. 06. 2018, 23:46:09 »
Co kdyz budu mit v aplikaci dalsi tabulky? Customers, Officers, Managers...
A taky jim chci umet poslat email, ulozit do databaze, vypsat do logu...
Bude mit kazda svou tridu? Kazda metodu save, send, toString?
Budou implementovat stejne rozhrani?
Budou ty proxy umet pracovat se vsemi takovymi tridami? Nebo bude pro kazdy typ jina proxy?

Ano, ano, ano.

Nejsme však omezeni na jednu metodu send(). Ve třídách mívám 3-5 metod s poměrně unifikovanými názvy.

Pred casem jsi psal, ze kazdy takovy datovy bean delas immutable inicializovany konstruktorem, bez getteru a setteru.
K cemu je dobra u immutable beanu metoda save? Ze se to zkonstruuje, pak se to jednou ulozi pres save(), pri zmene se to cele zahodi a sestavi lautr znova?
Zajimave.

Metoda send(cíl) prostě odešle data do cíle - zavolá metodu cíl.send(data). Pokud nemám gettery, tak to vlastně ani jinak nejde.

Immutable objekty jsou běžné.


Re:OOP jazyk - problém klasického stříhu
« Odpověď #46 kdy: 06. 06. 2018, 23:51:05 »
...

Sice souhlasím s Tebou nastíněným kanonickým řešením, jenže debata je tu o tom, jaký je rozdíl mezi

  • User.save()
  • Lopata.priloz(Uhli)

Až budeš mít na tohle návod, dej vědět. Sémantický rozdíl tam v principu totiž není. A celá debata  je tu jen a pouze o tom, jak rozdělit kompetence. A k tomu DI ani Spring MVC nic neříká. Ten jenom poskytuje prostředky. A třeba Spring Roo, Ebeans a další umí Active Record jako alternativu k Data Mapperu. Výhoda je jasná - schová před uživatelem DAO, čímž schová i komplexitu, což patří IMHO k principu zapouzdření.

Čili odpověď k věci se bude spíš zabývat kategoriemi objektů (kolekce, entita, proces, manager, blabla...) a pravděpodobně i jazykem (podstatné jméno, přídavné jméno, sloveso) - s cílem formulovat správné programovací věty a najít vodítka a typické role objektů k rozdělení kompetencí. Tomuhle je nejblíž příspěvek BoneFlute https://forum.root.cz/index.php?topic=18704.msg268483#msg268483

(Bohužel tím pádem přijdou na přetřes i návrhové vzory a zde je riziko, že se budou míchat návrhové vzory týkající se věci samotné (kompetencí) s návrhovými vzory, které jenom maskují nedokonalost jazyka (typicky javy). To jen na okraj.)

Re:OOP jazyk - problém klasického stříhu
« Odpověď #47 kdy: 06. 06. 2018, 23:57:08 »
A třeba Spring Roo, Ebeans a další umí Active Record jako alternativu k Data Mapperu. Výhoda je jasná - schová před uživatelem DAO, čímž schová i komplexitu, což patří IMHO k principu zapouzdření.

Tím je současně vymezena i vhodnost Active Record - hodí se tam, kde nepotřebuju mluvit přímo s Data Mapperem. Například u transakcí podle mě už začíná koncept Active Record drhnout.

Onestone

Re:OOP jazyk - problém klasického stříhu
« Odpověď #48 kdy: 06. 06. 2018, 23:59:20 »
Immutable objekty jsou běžné.
Nejen to, dokonce i žádoucí.

Re:OOP jazyk - problém klasického stříhu
« Odpověď #49 kdy: 07. 06. 2018, 07:24:54 »
Metoda send(cíl) prostě odešle data do cíle - zavolá metodu cíl.send(data). Pokud nemám gettery, tak to vlastně ani jinak nejde.
A jak taková metoda send(cíl) zapadá do oblasti zodpovědnosti objektu User? Jak už jsem psal, takových metod může mít objekt stovky – aby vytvořil unikátní identifikátor instance, aby se hezky vypsal, aby se zvalidoval, aby vrátil svou velikost v paměti…


oNeDaL

Re:OOP jazyk - problém klasického stříhu
« Odpověď #50 kdy: 07. 06. 2018, 09:36:30 »
A jak taková metoda send(cíl) zapadá do oblasti zodpovědnosti objektu User? Jak už jsem psal, takových metod může mít objekt stovky – aby vytvořil unikátní identifikátor instance, aby se hezky vypsal, aby se zvalidoval, aby vrátil svou velikost v paměti…

Samozřejmě nijak, pokud budeme mluvit o tom, že je User "entita". Kitovo tvrzení by platilo v případě, že by User byl doménová služba (předpokládám dle původního dotazu nějakou dnešní typickou MVC-like architekturu).

Nejpřesněji to napsal Youda, konkrétně i pro PHP je to IMHO asi nejčistší přístup. Já osobně to často zjednodušuji jen na Entity/Repository/Services. Tady není co vymýšlet :-)

Kit

Re:OOP jazyk - problém klasického stříhu
« Odpověď #51 kdy: 07. 06. 2018, 10:07:43 »
Metoda send(cíl) prostě odešle data do cíle - zavolá metodu cíl.send(data). Pokud nemám gettery, tak to vlastně ani jinak nejde.
A jak taková metoda send(cíl) zapadá do oblasti zodpovědnosti objektu User? Jak už jsem psal, takových metod může mít objekt stovky – aby vytvořil unikátní identifikátor instance, aby se hezky vypsal, aby se zvalidoval, aby vrátil svou velikost v paměti…

Objekt User odpovídá pouze za data, která objektu cíl předá.

anonym

Re:OOP jazyk - problém klasického stříhu
« Odpověď #52 kdy: 07. 06. 2018, 10:24:17 »
A jak taková metoda send(cíl) zapadá do oblasti zodpovědnosti objektu User? Jak už jsem psal, takových metod může mít objekt stovky – aby vytvořil unikátní identifikátor instance, aby se hezky vypsal, aby se zvalidoval, aby vrátil svou velikost v paměti…

Samozřejmě nijak, pokud budeme mluvit o tom, že je User "entita". Kitovo tvrzení by platilo v případě, že by User byl doménová služba (předpokládám dle původního dotazu nějakou dnešní typickou MVC-like architekturu).

Nejpřesněji to napsal Youda, konkrétně i pro PHP je to IMHO asi nejčistší přístup. Já osobně to často zjednodušuji jen na Entity/Repository/Services. Tady není co vymýšlet :-)

Ono ty stateless instance typu Service mají tu nevýhodu, že tím jak si nemůžeš udělat field tak ti značně roste počet parametrů v metodách, což nevypadá moc pěkně. Ještě jeden problém který s tímto je, vznikne, když metody takto pasuješ na funkce a přesto nemůžeš vrátit více objektů z funkce, než-li jeden, jako to jde třeba v Golang. To vede k využívání způsobu, kdy parametry metody jsou zároveň výstupními parametry.

A nevím ještě čím to je, ale na všech trochu legacy Spring projektech kde jsem dělal, byly ty Service pospojovány do spletité sítě, ve které byla snad spojeno všechno se vším. Lidi tam měli tendenci až moc nerozlišovat jednotlivé třídy problému. Pamatuju si, když byl kolega naštvaný, že vytvářím pro nový komplexní validační check dat (zbytečně) novou Service, místo abych těch 150 řádků kódu přidal do již existující 800 řádkové Service. Takže ani ta Spring architektura není samospásná a když se nad tím nepřemýšlí, bude v tom bordel.

Kit

Re:OOP jazyk - problém klasického stříhu
« Odpověď #53 kdy: 07. 06. 2018, 10:43:46 »
A nevím ještě čím to je, ale na všech trochu legacy Spring projektech kde jsem dělal, byly ty Service pospojovány do spletité sítě, ve které byla snad spojeno všechno se vším. Lidi tam měli tendenci až moc nerozlišovat jednotlivé třídy problému. Pamatuju si, když byl kolega naštvaný, že vytvářím pro nový komplexní validační check dat (zbytečně) novou Service, místo abych těch 150 řádků kódu přidal do již existující 800 řádkové Service. Takže ani ta Spring architektura není samospásná a když se nad tím nepřemýšlí, bude v tom bordel.

Service jsou obvykle jen skladiště funkcí.

Re:OOP jazyk - problém klasického stříhu
« Odpověď #54 kdy: 07. 06. 2018, 17:20:53 »
A jak taková metoda send(cíl) zapadá do oblasti zodpovědnosti objektu User? Jak už jsem psal, takových metod může mít objekt stovky – aby vytvořil unikátní identifikátor instance, aby se hezky vypsal, aby se zvalidoval, aby vrátil svou velikost v paměti…

Samozřejmě nijak, pokud budeme mluvit o tom, že je User "entita". Kitovo tvrzení by platilo v případě, že by User byl doménová služba (předpokládám dle původního dotazu nějakou dnešní typickou MVC-like architekturu).

Nejpřesněji to napsal Youda, konkrétně i pro PHP je to IMHO asi nejčistší přístup. Já osobně to často zjednodušuji jen na Entity/Repository/Services. Tady není co vymýšlet :-)

Ono ty stateless instance typu Service mají tu nevýhodu, že tím jak si nemůžeš udělat field tak ti značně roste počet parametrů v metodách, což nevypadá moc pěkně. Ještě jeden problém který s tímto je, vznikne, když metody takto pasuješ na funkce a přesto nemůžeš vrátit více objektů z funkce, než-li jeden, jako to jde třeba v Golang. To vede k využívání způsobu, kdy parametry metody jsou zároveň výstupními parametry.

A nevím ještě čím to je, ale na všech trochu legacy Spring projektech kde jsem dělal, byly ty Service pospojovány do spletité sítě, ve které byla snad spojeno všechno se vším. Lidi tam měli tendenci až moc nerozlišovat jednotlivé třídy problému. Pamatuju si, když byl kolega naštvaný, že vytvářím pro nový komplexní validační check dat (zbytečně) novou Service, místo abych těch 150 řádků kódu přidal do již existující 800 řádkové Service. Takže ani ta Spring architektura není samospásná a když se nad tím nepřemýšlí, bude v tom bordel.

A jsme u toho, že Spring v tom rozdělení kompetencí moc nepomůže. Správný návrh Services a Entit je téma, které neřeší.

Youda

Re:OOP jazyk - problém klasického stříhu
« Odpověď #55 kdy: 08. 06. 2018, 03:01:09 »
...

Sice souhlasím s Tebou nastíněným kanonickým řešením, jenže debata je tu o tom, jaký je rozdíl mezi

  • User.save()
  • Lopata.priloz(Uhli)

Rozdil je zrejmy a trivialni.
Lopata je vykonny @Controller, ktery sibuje s hlopou @Entitou Uhli. Ostane proto Spring tak tyto anotace pojmenoval.

V pripade Usera je spravny pristup
UserRegistr.save(User)

Anebo, pro jeste snazsi pochopeni
Noha.nakopni(zadek), tady je hned jasne, ze zadek.nakopniSe(Nohou) je blbost.

Pri objektovem navrhu je proste nutno v danem co je iniciatorem akce a co je objektem (ne v OOP smyslu) teto akce.
A OOP objekt muze klidne v ruznem kontextu zastavat obe role
Ridic.natoc(Volant)
Volant.natoc(Kola)

Tohle jsou trivialni zaklady objektove dekompozice.


Honza

Re:OOP jazyk - problém klasického stříhu
« Odpověď #56 kdy: 08. 06. 2018, 03:38:09 »
V pripade Usera je spravny pristup
UserRegistr.save(User)

S tímhle souhlasím, otázka tedy teď je, co je špatného na User.save()?

oNeDaL

Re:OOP jazyk - problém klasického stříhu
« Odpověď #57 kdy: 08. 06. 2018, 04:40:45 »
V pripade Usera je spravny pristup
UserRegistr.save(User)

S tímhle souhlasím, otázka tedy teď je, co je špatného na User.save()?

:D

Kit

Re:OOP jazyk - problém klasického stříhu
« Odpověď #58 kdy: 08. 06. 2018, 07:32:25 »
V pripade Usera je spravny pristup
UserRegistr.save(User)

Jak metoda save() zjistí, co z objektu User má uložit? Jak se bez getterů dostane k jeho privátním atributům?

Youda

Re:OOP jazyk - problém klasického stříhu
« Odpověď #59 kdy: 08. 06. 2018, 08:01:47 »
V pripade Usera je spravny pristup
UserRegistr.save(User)

Jak metoda save() zjistí, co z objektu User má uložit? Jak se bez getterů dostane k jeho privátním atributům?

Co se ma ulozit zalisti prislusna metoda repisitory, data zjisti pres gettery. Na gettery je v eclipse dokonce generator