- enpassant blogja
- A hozzászóláshoz be kell jelentkezni
- 1316 megtekintés
Hozzászólások
Nekem erről a Clean Code függvényekről szóló fejezete jutott eszembe: "Small!", "Do One Thing", "One Level of Abstraction per Function", "Use Descreptive Names". Szerencsétlen runLogic függvény még egy rendes nevet se kaphatott (code smell :)), annyi mindent csinál. Még az utolsó megoldás main függvénye is túl sokat csinál szerintem, bár értem hogy így jobban szemlélteti amit ki akartál fejezni.
Ami még eszembe jutott, hogy az OOP-s megoldás olyan, mintha el akarná rejteni a ronda kódot. Kívülről csak a Readeren és a Writeren keresztül vizsgálható, a többi a Greeting privát dolga. Ez szerintem nem absztrakció, legfeljebb az absztrakció illúziója. Sajnos pl. Java programokban rendszeresen találkozom ilyen megoldásokkal. Tipikus ismertető jele amikor egy program rengeteg interface-t definiál de a legtöbbnek egyetlen implementációja van, rosszabb esetben Impl postfixszel ellátva. Általában hosszú hívási láncokat kell végigkövetni mire megtalálod a lényeget, a köztes elemek leginkább csak delegálnak a következő szintre és a végén lesz egy jó bonyolult függvény ami megcsinálja az érdemi munkát.
- A hozzászóláshoz be kell jelentkezni
Sok helyen írnak erről, hogy valós reuse nélkül az absztrakció néhol csak növeli az összetevők számát, jön rögtön a felvetés: honnan tudhatnánk, hogy később nem lesz máshol újrahasznosítva, vagy itt cserélve.
- A hozzászóláshoz be kell jelentkezni
honnan tudhatnánk, hogy később nem lesz máshol újrahasznosítva, vagy itt cserélve.
A cseréléssel nincs gond, mint ahogy írtam is a blogban, egyedül azzal, ha futásidőben cserélnéd, vagy több implementációt használnál.
Ez utóbbi esetben pedig, majd akkor kell átmenni a hídon, ha odaértünk. Ahogy előre nem jó mikró optimalizálni, ugyanúgy nem jó mindent cserélhetőre, újrahasznosíthatóra csinálni.
- A hozzászóláshoz be kell jelentkezni
Szerencsétlen runLogic függvény még egy rendes nevet se kaphatott (code smell :)), annyi mindent csinál.
A Clean Code-dal valóban vannak kisebb problémák, de nem azért nem kapott rendes nevet, mert sok mindent csinál. Ezt a sok mindent csinált, ezt sokan félre is értik. Nem arról van szó, hogy csak egy dolgot csinál, még arról sem, hogy csak egy fajta dolgot csinál, hanem arról, hogy egy absztrakciós szinten van az egész, egyik része sem megy mélyebbre, mint a másik. Ennek pedig nagyjából megfelel, esetleg az üzenet formázását lehetne még kirakni egy függvénybe.
/Lecseréltem a runLogic-ot greet-re/.
Még az utolsó megoldás main függvénye is túl sokat csinál szerintem, bár értem hogy így jobban szemlélteti amit ki akartál fejezni.
Pontosan!
Tipikus ismertető jele amikor egy program rengeteg interface-t definiál de a legtöbbnek egyetlen implementációja van ...
Innentől egyetértek a végéig, pont erről szól a cikk. Ezek azok az esetek, amikor azért van interface-elve (laza kapcsolat), mert hátha majd valamikor lecserélésre kerül. Pedig a lecserélés miatt pont nem kellene a DI, a DI akkor kell, ha egyszerre több implementációját szeretnénk használni.
- A hozzászóláshoz be kell jelentkezni
Amit sohasem fogok megérteni: miért kell az interface, ha van abstract class? Mit ad az interface, amit egy abstract class nem? (bocs, OOP csak mint hobbi olvasmány került elém, leragadtam a procedurális programoknál)
- A hozzászóláshoz be kell jelentkezni
Nem minden népszerű nyelv tud többszörös öröklést, nem véletlenül.
- A hozzászóláshoz be kell jelentkezni
Ez részben jogos, részben nem értem.
Mennyiben jobb n+1 elemű lista az implements után, mint a többszörös öröklődés? (Gondolom, erre céloztál azzal, hogy "nem véletlenül")
- A hozzászóláshoz be kell jelentkezni
Mivel a "tisztel" poszt-toló leugatott, hogy ez itt offtopik, így köszi, tárgytalan (amennyit láttam az egészből, ugyanez kijöhet interface-ekkel is, de mivel nem értek hozzá, tévedés joga fenntartva)
- A hozzászóláshoz be kell jelentkezni
Peldaul, ha van egy Vehicle class, akkor annek kell lennie egy startEngine()-nek valahol.
VehicleInterface -> AbstractGroundVehicle -> Car, Bus, etc
VehicleInterface -> AbstractAirPlane -> Cropduster, B17, etc
AbstractGroundVehicle startEngine methodusa tartalmaz oninditot, de az AbstractAirPlane egy foldi propeller forgatot
- A hozzászóláshoz be kell jelentkezni
Ez az abstract létét indokolja, nem az interface-ét.
- A hozzászóláshoz be kell jelentkezni
Ez a téma egyáltalán nem kapcsolódik az adott bloghoz!
Légy szíves nyiss egy fórumot és ott kérdezd meg és beszéld meg a dolgaidat.
- A hozzászóláshoz be kell jelentkezni
Hogy egyáltalán nem, azt erős túlzásnak érzem, de mindegy...
Lassan itt tényleg csak a bunkó trollok maradnak. :D
- A hozzászóláshoz be kell jelentkezni
Alapvetoen orulok a blogbejegyzesnek es pont ma adott otletet, hogy hogy szervezzem a kodot, de a drupalnak, es altalanossagban a hiearchikus kommenteknekbaz a baromi nagy elonye, hogy szinte semmi sem offtopic, ami valami asszociacio menten kapcsolodik a temahoz.
Ha osszecsukhatoak lennenek a komment szalak, szerintem teged se zavarna. Na, ez ugyanaz, csak a kulonbozo "altopicok" mindig latszanak.
- A hozzászóláshoz be kell jelentkezni
Igazság szerint HZ-nek köszönhető, hogy ráakadtam erre a blogra. :)
Szerintem hasznos amit írtál, valóban nem a loose coupling a lényeg, hanem hogy "pure" / "functional" legyen a kód, azzal lehet a tesztelhetőségen jelentősen javítani.
Viszont ez nem jelenti azt, hogy a DI minden esetben rossz. Pl. ha van egy algoritmusod, amit meg kell hívnod sokszor, van mondjuk 10 állandó és 3 esetenként változó paraméter. Akkor ezt nem jobb úgy megcsinálni, hogy van egy osztály, amibe mondjuk DI-vel drótozod be az állandó paramétereket? Én most Dagger2-t használok ahol lehet (és van a DI-nek értelme).
Nyilván az sem jó, ha mindenből interfészt csinálsz. Pl. van ahol az adatstruktúrákhoz is interfészeket gyártanak, ahol a konkrét osztályok teljesen jól működnének. Viszont ha algoritmusokról van szó, akkor sokkal több értelmét látom már akkor interfészként deklarálni, ha még csak 1 konkrét megvalósítás létezik, mert sokkal valószínűbb, hogy a későbbiek során lesz szükség alternatívákra mint a konkét adatstruktúráknál.
Ahol még hasznosnak tartom az interfészek használatát:
- Input / Output absztrakciója
- Platformspecifikus API-k eltakarása a kód többi része elől.
PS: Fentebb az interfész az alatt az explicit deklarált Java interface-eket értem, természetesen minden osztály külső felhasználó számára elérhető metódusai és mezői interfészt alkotnak, amit ugyanúgy jól meg kell tervezni és dokumentálni Javadoc-kal, különös tekintettel az erőforráskezelésre.
- A hozzászóláshoz be kell jelentkezni
Köszi az észrevételeket!
Viszont ez nem jelenti azt, hogy a DI minden esetben rossz.
Egyáltalán nem rossz minden esetben, csak a legtöbb esetben, amire használva van.
A Dependency Injection-t kétféle módon is lehet használni. Gondoltam is rá, hogy kifejtem a blogban, de valamiért nem tettem.
1. Amikor külön válik a wiring, vagyis teljesen más helyen történik a létrehozás a függőség megadásával, és teljesen más helyen a használata.
2. Amikor a létrehozás után egyből használva van. Ez szinte ugyanaz, mint a tight coupling.
Az elsőre nagyon jó példa az IoC-k használata, ahol fogalmunk sincs mikor, hol és mivel történik a függőség feloldása.
A másodikra nagyon jó példa a filter, map, ... használata, pl.:
salaries.filter(SalaryFilters::isHigh)
Ahol még hasznosnak tartom az interfészek használatát
Tight couplinggal is meg tudod ezeket tenni, a blogomban is volt erre példa, a read
és write
eltakarta a platform specifikus dolgokat, ráadásul I/O.
Összefoglalva:
- Nem rossz a DI használata, sok esetben kifejezetten nagyon jó (pl. filter), a túlzott, általános használata ami nagyon rossz.
- Nem rossz a tight coupling sem, és nem is az egyedüli üdvözítő mód. Itt figyelni kell, ha jól tesztelhető kódot akarunk írni, akkor sok esetben át kell egy kicsit terveznünk a kódot, ami többlet munka, de nagyon hasznos a végeredmény szempontjából.
- A hozzászóláshoz be kell jelentkezni