Bevezetés
Robert L. Glass azt állította, hogy a gyakorlat megelőzi az elméletet. A szoftverfejlesztés különösen olyan terület, ahol a gyakorlat megelőzi az elméletet, és a fejlesztők a legtöbbet akkor tanulják meg, amikor konkrét kódot írnak, és „beszennyezik a kezüket”. Ezért az elméletet és a fogalmakat egyelőre félretesszük, és egy egyszerű programot szeretnénk megvizsgálni.
Jegyértékesítési alkalmazás implementálása
- Egy kis színház népszerűsítése céljából egy kis eseményt szeretnénk szervezni.
- Az esemény tartalma: sorsolás útján kiválasztott nézőknek ingyenes meghívót küldünk a színházi előadásra.
- Szelektálnunk kell a sorsoláson nyertes és a vesztes nézők között.
- Sorsoláson nyertes nézők: a meghívót jegyre válthatják.
- Sorsoláson vesztes nézők: a jegyet pénzért vásárolhatják meg.
Gyakorlati kód: https://github.com/Java-Crew/objects-study/tree/jayon/src/main/java/chapter01/step01
Mi a probléma?
Robert Martin három funkciót ír le, amelyekkel a szoftvermoduloknak (mérettől függetlenül, például osztályok, csomagok vagy könyvtárak, amelyek a programot alkotják) rendelkezniük kell.
- Futás közben megfelelően működik.
- A módosítás céljából létezik.
- A módosításnak egyszerűnek kell lennie.
- Kommunikál a kódot olvasókkal.
- A fejlesztőknek könnyen olvashatónak és érthetőnek kell lennie.
Az előző jegyértékesítési alkalmazás kielégíti az első korlátozást, vagyis a megfelelő működést, de a módosíthatóság és a kommunikáció céljait nem éri el.
Váratlan kód
Nézzük meg, miért nem felel meg a kommunikáció céljának.
- A Theater osztály enter() metódusa mit csinál?
- A színház kinyitja a néző táskáját, és megnézi, hogy van-e benne meghívó.
- Ha van meghívó a táskában, akkor a pénztárosnak utasítást ad, hogy tegye a néző táskájába a pénztárban lévő jegyet.
- Ha nincs meghívó a táskában, akkor a néző táskájából veszi ki a jegy árát, megvásárolja a jegyet, és beteszi a táskába.
- A néző szempontjából a színház, mint harmadik fél, szabadon kotorászhat a táskájában, elveheti a pénzét, és beleteheti a jegyet.
- A pénztáros szempontjából a színház, mint harmadik fél, engedély nélkül manipulálja a pénztárban lévő jegyeket és pénzt.
- Az érthető kód olyan kódot jelent, amelynek működése nem tér el túlságosan a várakozásainktól, a fenti színház azonban eltér a várakozásainktól.
- A nézőnek saját maga kell kivennie a pénzét a táskájából, és fizetnie kell a pénztárosnak a jegyért.
- A pénztárosnak saját maga kell kivennie a jegyet a pénztárból, átadnia a nézőnek, és pénzt kapnia tőle, amit a pénztárba tesz.
- Ezenkívül az enter() metódus megértéséhez számos részletet kell megjegyezni.
- Az Audience (Néző) osztálynak van egy Bag (Táska) osztálya.
- A Bag (Táska) osztályban van pénz és jegy.
- A TiketSellet (Jegyárus) osztálynak van egy TicketOffice (Jegyiroda) osztálya, ahol jegyeket árusít, és a TicketOffice (Jegyiroda) osztályban pénz és jegy van.
Módosításra érzékeny kód
Az enter() metódus két feltételezést tesz.
- A néző mindig hordoz egy táskát, amelyben pénzt és meghívót tárol.
- A pénztáros csak a pénztárban árusít jegyeket.
Mi a helyzet az alábbi helyzetekkel?
- Lehet, hogy a nézőnek nincs táskája.
- A néző hitelkártyával fizethet.
- A pénztáros a pénztár előtt is árusíthat jegyeket.
Például az első követelmény kielégítéséhez el kell távolítanunk az Audience (Néző) osztály Bag (Táska) osztályát, és módosítanunk kell a Theater (Színház) osztály enter() metódusát. Ennek oka, hogy a Theater (Színház) osztály túlságosan részletesen támaszkodik arra a tényre, hogy a nézőnek van egy táskája, és hogy a pénztáros csak a pénztárban árusít jegyeket. Ha ezek közül a részletek közül bármelyik megváltozik, akkor a Theater (Színház) osztályt és az attól függő osztályokat (pl. a Theater (Színház) osztályt) is módosítani kell.
Ez az objektumok közötti függőséggel kapcsolatos probléma, és a függőség a változás hatását jelzi. Az objektumorientált tervezés célja azonban olyan objektumok közösségének felépítése, amelyek együttműködnek és egymástól függenek, ezért nem szabad a függőségeket vakon eltávolítani, hanem a minimális függőség fenntartásaés a felesleges függőségek eltávolítása.
Ha az objektumok közötti függőség túlzott, akkor azt „magas kapcsoltságnak”mondjuk, és minél magasabb a két objektum közötti kapcsoltság, annál nagyobb a valószínűsége annak, hogy együtt változnak. Ezért a tervezés célja az, hogy csökkentsük az objektumok közötti kapcsoltságot, és olyan tervet készítsünk, amely könnyen módosítható.
A tervezés javítása
A Theater (Színház) osztálynak nem kell tudnia, hogy a nézőnek van-e táskája, és hogy a pénztáros a pénztárban árusít-e jegyeket. A Theater (Színház) osztály csak azt akarja, hogy a néző belépjen a színházba. Ezért a nézőnek saját maga kell kezelnie a pénzt és a meghívót a táskájában, és a pénztárosnak saját maga kell kezelnie a pénztárban lévő jegyeket és az árat.
Növeljük az autonómiát
Azokat az objektumokat, amelyek csak szorosan összefüggő feladatokat végeznek, és a nem kapcsolódó feladatokat más objektumokra bízzák, „magas kohéziónak” nevezzük. Ha olyan autonóm objektumokat hozunk létre, amelyek saját adataikat kezelik, akkor csökkenthetjük a kapcsoltságot és növelhetjük a kohéziót.
Eljárásorientált és objektumorientált
- Eljárásorientált
- A Theater (Színház) osztály enter() metódusa egy folyamat, az Audience (Néző), TicketSeller (Jegyárus), Bag (Táska) és TicketOffice (Jegyiroda) osztályok pedig adatok.
- A folyamatokat és az adatokat külön modulokba helyező megközelítést eljárásorientált programozásnak nevezzük.
- Sok olyan kód van, amely ellentmond az intuíciónknak. (Pl. a néző maga kezeli a pénzét és a meghívóját.)
- Nehéz leszűkíteni az adatok módosítása miatt bekövetkező hatásokat.
- A felelősség központosított (a Theater (Színház) osztály kezeli az egészet).
- Objektumorientált
- Az adatok és a folyamatok ugyanabban a modulban vannak elhelyezve. Ezt az objektumorientált programozásnak nevezzük.
- Így intuitív kódot írhatunk.
- A kapszulázás révén hatékonyan leszűkíthetjük az adatok módosítása miatt bekövetkező hatásokat.
- Minden objektum felelős önmagáért.
Gyakorlati kód: https://github.com/Java-Crew/objects-study/tree/jayon/src/main/java/chapter01/step02
Még tovább javítható
- Az Audience (Néző) osztály Bag (Táska) osztálya továbbra is passzív, és az Audience (Néző) osztály irányítja. Ezért a Bag (Táska) osztályt autonóm objektummá kell tenni.
- A TicketSeller (Jegyárus) osztály TicketOffice (Jegyiroda) osztálya is a TicketSeller (Jegyárus) osztály által irányított. A TicketOffice (Jegyiroda) osztályt autonóm objektummá kell tenni.
- De a módosítás után a TicketOffice (Jegyiroda) osztály és az Audience (Néző) osztály között fokozott kapcsoltság alakul ki.
- A tervezés során figyelembe kell venni a kompromisszumokat. Ebben az esetben megállapodhatunk abban, hogy a TicketOffice (Jegyiroda) osztályt bizonyos mértékben passzív objektummá tesszük, hogy csökkentsük a kapcsolatot az Audience (Néző) osztálysal.
Gyakorlati kód: https://github.com/Java-Crew/objects-study/tree/jayon/src/main/java/chapter01/step03
De ez hazugság!
- A valóságban, még akkor is, ha egy objektum passzív, ha belép az objektumorientált világba, minden aktív és autonóm objektummá válik.
- Használjuk a megszemélyesítést, és képzeljük el a passzív objektumokat úgy, mintha nevetnének, beszélgetnének, és dühösek lennének.
Objektumorientált tervezés
Miért van szükség tervezésre?
- A tervezés a kód elhelyezése.
- A jó tervezés olyan, amely teljesíti a mai követelményeknek megfelelő funkciókat, és zökkenőmentesen befogadja a holnapi változásokat.
Objektumorientált tervezés
- A módosítható kód könnyen érthető kód.
- Az objektumorientált paradigma segít abban, hogy a világ megtekintésének módjához hasonlóan írjunk kódot.
- Az objektumok autonóm entitások, amelyek felelősek saját adataikért.
- A kiváló objektumorientált tervezés megfelelően kezeli az együttműködő objektumok közötti függőségeket.
Forrás
- Objektumok
Hozzászólások0