Dědičnost je vyzdvihována jako jedna z největších předností objektově orientovaného programování. Je to ale dvousečná zbraň – pokud dědičnost používáte špatně, způsobí více škody, než-li přinese užitku. Já se snažím dědění vyhýbat, jak to jen jde, takže moje dědičné hierarchie nikdy neuvidíte zasahovat do nějakých extrémních hloubek, já zůstávám hezky na mělčině. Maximálně tak dvě generace a konec.
Nejde ani tak o to, že bych tvrdil, že jak je třída již ve 3. generaci, je celý návrh špatně, ale povětšinou nevidím důvod, aby bylo více, jak 2 generace.
On vůbec ten pojem „dědičnost“ je pěkně zle zvolený. Dědičnost… Dědičnost ve mně vyvolává vzpomínky na hodiny biologie, kdy jsme se bavili o rozmnožování a dědičnosti genetické informace. Aby k takovému dědění mohlo dojít, jsou potřeba dva jedinci. A hned u tohoto se OOP v mnoha současných jazycích liší. Není totiž povoleno, aby potomek dědil z více jak jedné třídy. Kde je tedy ta dědičnost, když jde akorát o sdílení některého kódu s rodičem, o nic jiného. (V takovém C++ by se již o dědičnosti mělo smysl bavit, protože C++ mnohonásobnou dědičnost podporuje.)
Slovo „Dědičnost“ je tedy špatný zvoleno. Lepší je „specializace“ – potomek definuje, či upravuje možnosti předka. A když se na to začnete dívat z tohoto úhlu pohledu, že potomek specializuje rodiče, není důvod, proč by mělo být více než dvou generací. Máme specializovanou třídu (potomka). Její potomek bude ještě specializovanější? A potomek potomka nejspecializovanější? Podle mě to zní divně.
Dále se při velkém zanoření dědičnosti dá setkat s tím, že jsou porušovány takové základní principy jako je neopakování kódu zbytečně (a k tomu se vztahující akronym DRY). Můžete se ptát, jak může dědění ublížit neopakování se kódu, vždyť by mu to mělo prospět, ne? Ale vezměme si takovou třídu obstarávající zpracování požadavku na stránku (nadává se tomu myslím Page Controller pattern). Když budeme mít stránky jako např. tento blog, tak by bylo logické, že bychom si vytvořili dva potomky – BlogController a AdminController, kde by z prvního dědily stránky blogu a z druhého stránky administračního rozhraní. V tom druhém by se navíc v inicializační metodě kontrolovalo, jestli je uživatel přihlášen. Ale ouha, co když budeme chtít, aby administrátor nemusel pořád chodit do admin rozhraní, např. k úpravě komentářů? Zduplikovat kód pro ověření přihlášení? Ne, to by přece bylo ošklivé. Dědit všechny stránky (jak blogu, tak admin rozhraní) z jednoho základního controlleru? Ne, tady se dědění vůbec nehodí, všechny stránky mohou dědit přímo z Page controlleru a inicializaci je lepší zařídit jinak.
Dědění, ač by to byl taky opak toho, než co by „ostřílení“ OOPčkáři řekli, svádí k tomu porušovat Single Responsibility Principle (princip jednotné zodpovědnosti). Řečeno jednoduše by každá třída měla dělat jenom jednu věc. Např. třída pro práci s databází by vůbec neměla vědět o požadavku na aplikaci atd. Bohužel toto je přesně toto, na co hodně lidí pomyslí. Tak tady si udělám třídu pro jednu stránku… Potřebuju tam pracovat s databází, tak ji podědím z třídy s databází.
Kde je ale ten problém? Proč tak hodně lidí smýšlí o dědičnosti takhle? Může to být proto, že přecházejí z jiného způsobu programování (pravděpodobně procedurálního), ale mně se to nějak nezdá. Problém je v tom, že dědičnost je prezentována jako jedna z nejlepších a většinou i všespásných vlastností OOP – je příliš přeceňována. Začátečník pak získá dojem, že když programuje stylem OOP, musí dědičnost používat, co to jen jde, jinak by totiž přeci neprogramoval objektově!
Když se podívám na jakýkoli článek o OOP pro začátečníky, vidím, že OOP je o: dědičnosti, zapouzdření a polymorfismu. Ale vždyť toto jsou vlastnosti pokřivené implementací několika jazyků, které pro OOP poskytují syntaktický cukr (objektově se dá programovat i v C – viz GLib) – myslím tím hlavně Javu a všechny jazyky, které si z ní berou příklad (což znamená i PHP).
Co s tím dělat? Nejdůležitější podle mě je programátorům začínajícím se o OOP zajímat poskytovat pohled na problematiku z mnoha úhlů, takže nejen z toho Javovského, ale dobrý by byl též Smalltalkovský model (všechno je o tom, že objeky spolu komunikují pomocí zpráv) a Javascriptovský (prototypová dědičnost, něco úplně jiného než ta třídní).
Komentáře
Přidat komentář