ugrás a tartalomhoz

Demeter törvénye??

eddig bírtam szó nélkül · 2012. Szep. 19. (Sze), 08.47
Help! Ezt nem tudom értelmezni... Demeter törvénye szerint egy objektum metódusa
... a következőket hívhatja:

O-t magát
M paramétereit
M-en belül létrehozott/példányosított objektumokat
O közvetlen komponenseit


OK, ez így szerintem érthető, ebbe beleférne minden, amit eddig láttam, de...

A Clean Code-ot olvasgatva (magyar fordítás, 6. fejezet - most nincs kéznél, nem tudom pontosan idézni) bukkantam egy olyanra, miszerint a felhasznált objektumok által visszaadott objektumok metódusaira már nem szabad hivatkozni.
És itt elakadtam. A fenti felsorolásban az "M-en belül létrehozott"-ba belefér, hogy egy objektum metódusa ad vissza egy másik, általam ismert típusú objektumot, tehát azt nyugodtan használhatom, nem sértem meg vele pl. az említett Demeter törvényét. A könyvben írtak szerint viszont ez már nem fér bele, ha az objektum nem adatszerkezetet ad vissza.
Gyanítom, hogy ezzel valami nem stimmel, mivel egy v. két oldallal később, ezt demonstrálandó felhasznál egy, a példaként hozott, belső objektum által előállított stream objektumot, amit java-s emlékeim szerint nem csak paraméterként adok át más osztályoknak, hanem közvetlenül a metódusaira hivatkozva lehet rajta műveleteket végezni.
Akkor ez most hogy van (fejvakargatós smiley) ?
Nem beszélve arról, hogy pl. a DIC, mint olyan nem sérti ugyanezt az elvet, ha a könyv szerinti változatot fogadom el? Hiszen egy másik objektum által létrehozott objektummal akarunk dolgozni és annak ismerni kell a belsejét is...
Valószínűleg kimaradt valami az olvasmányaimból, de nagyon nem értem.

---
update:

Rendben, a könyv olvasása közben egy sort átugrottam: "a példányváltozókban tárolt objektumok metódusait" is hívhatom.
Viszont ettől kezdve az nem teljesen tiszta, hogy mi a különbség (ebből a szempontból) ezek közt:

a=objektum.metodus().metodus2()

illetve

x=objektum.metodus()
a=x.metodus2()


Utóbbi hosszabb, mondjuk olyan nyelveknél (pl. java), ahol előre deklarálni kell a változókat, ott értem: dokumentálva van, hogy az "x" milyen típust vár. De ez (szerintem) nyelvspecifikus, egy PHP-ben, perl-ben, Pythonban mi értelme? Ezeknek az elveknek nem kellene általános érvényűeknek lenni? Mit hagytam ki megint?
 
1

PHPban is

blacksonic · 2012. Szep. 19. (Sze), 11.29
PHPban is meg tudod adni hogy milyen tipusu parametert varjon, ha az osztaly vagy tomb tipusu
2

De csak ha paraméterként

eddig bírtam szó nélkül · 2012. Szep. 19. (Sze), 11.35
De csak ha paraméterként kapod, nem? (rég nem foglalkoztam PHP-vel)
Végeredményben nincs jelentősége, sok olyan nyelv van, ahol ha akarod sem tudod előre deklarálni a változóid típusát.
3

pontosan

blacksonic · 2012. Szep. 19. (Sze), 12.54
pontosan, csak akkor ha parameterkent adod at
4

Encapsulation és loose coupling

Endyl · 2012. Szep. 19. (Sze), 15.01
Szerintem ennek a törvénynek a mondanivalója az, hogy próbáljuk az encapsulationt helyesen magvalósítani, ezáltal közelebb kerülve a modulárissághoz, loose couplinghoz.

Tehát ha A objektumnak szüksége van B egyik alrendszerének -C- szolgáltatására, akkor ne kérje el B-től C-t, hogy azon hívjon meg egy metódust, hanem B szolgáltasson interfészt az adott szolgáltatáshoz.

// A egy metódusában a következő helyett:
B.getC().someMethod();
// inkább legyen egy ilyen:
B.performSomeServiceOfC();
Ha viszont A-nak B-től függetlenül is szüksége van C-re, akkor nem tekinthető (csak) B alrendszerének, így akár A-nak is lehet C-típusú példányváltozója.

Ebben a Demeter törvényéről és a "pontszámolásról" szóló cikkben a következő példát hozzák fel (egy másik írást idézve (pdf)):

Vegyük egy újságos és egy vevő esetét. Ahelyett, hogy az újságos elkérné a vevő pénztárcáját, hogy kivegye belőle az újság árát, az ellenértéket közvetlenül a vásárlótól kéri el.

Kódra lefordítva ez a következők miatt jó (Újságos, Vevő és Pénztárca osztályok esetén):
-Újságos közvetlenül Vevőtől kéri el az ellenértéket, nincs hozzáférése Pénztárcához
-Pénztárca megvalósítása változhat, Újságosnak nem kell tudnia, hogy Pénztárca melyik részében keresse a megfelelő fizetőeszközt
-ebből következően Vevő saját ízlésének megfelelő Pénztárcát használhat (változhat a "fizetés()" metódus megvalósítása)

Az, hogy melyik objektumnak/osztálynak melyik másik objektumot/osztályt kell ismernie, tervezéskor kell eldönteni és később nem hívogatni olyan objektumok metódusait, amit a hívó objektum nem "ismer".

Ugyanakkor persze ez sem kőbe vésett törvény, inkább csak irányelv, amit szem előtt tartva, ezáltal átgondoltan tervezve talán jobb/könnyebben karbantartható kódot írunk majd.
7

Köszi! Ami a "kőbe vésett

eddig bírtam szó nélkül · 2012. Szep. 19. (Sze), 17.26
Köszi! Ami a "kőbe vésett törvényeket" illeti, egyelőre úgy vagyok vele, hogy egy magamfajta kezdő jobban teszi, ha úgy kezeli ezeket az elveket, mintha bele lennének vésve ama kőbe. (fotós hasonlatot tudnék rá hozni ;-) )
5

A könyvben írtak szerint

inf · 2012. Szep. 19. (Sze), 17.04
A fenti felsorolásban az "M-en belül létrehozott"-ba belefér, hogy egy objektum metódusa ad vissza egy másik, általam ismert típusú objektumot, tehát azt nyugodtan használhatom, nem sértem meg vele pl. az említett Demeter törvényét. A könyvben írtak szerint viszont ez már nem fér bele, ha az objektum nem adatszerkezetet ad vissza.
Gyanítom, hogy ezzel valami nem stimmel, mivel egy v. két oldallal később, ezt demonstrálandó felhasznál egy, a példaként hozott, belső objektum által előállított stream objektumot, amit java-s emlékeim szerint nem csak paraméterként adok át más osztályoknak, hanem közvetlenül a metódusaira hivatkozva lehet rajta műveleteket végezni.


De ez stimmel, de én sem veszem annyira szigorúan...
Ha a belső objektum metódusa ad vissza egy másik objektumot, amit te használsz, akkor hacsak nem valami Container/Provider/Factory-ről van szó, akkor nem fér bele. Nyilván a fentieknek az a feladata, hogy létrehozzanak egy olyan objektumot, amit M tud használni. Ha más lenne a feladatuk, akkor már sértenék a Demeter törvényét, mert mutatnák a belső szerkezetüket. A fentiek nem mutatják...
6

Köszi, erre időközben

eddig bírtam szó nélkül · 2012. Szep. 19. (Sze), 17.23
Köszi, erre időközben rájöttem én is: "update" utáni szakasz. :-)
De végülis van benne valami, hogy úgy is felfoghatjuk, hogy egy konténer v. egy factory nem a saját szerkezetéről ad ki infót, hanem egy általam kért objektumot gyárt, ennél fogva nem is sérti ezeket az elveket.
8

Ja, nem kell ezeket annyira

inf · 2012. Szep. 19. (Sze), 18.06
Ja, nem kell ezeket annyira szigorúan venni. Pl az elején is írja Clean Code-nak, hogy ne legyenek "and", "if" meg ilyesmik a metódus nevekben, de az is olyan, hogy simán lehet, csak akkor utána annak a metódusnak két másikat kell meghívnia...