Pokud se podíváme do kódu a chceme zjistit, zda je „nečistý“, tak bychom neměli o tom příliš dlouho spekulovat, ale měli bychom uvidět na první pohled, zda se jedná o paskvil nebo ne. Je to spíše obdoba „Pavlovova podmíněného reflexu“ (řádově v sekundách), než že by se jednalo o složitou a dlouhou analýzu kódu.
Hlavním prohřeškem při porušení principu jedné odpovědnosti je umístění kódu tam, kam nepatří, i když přitom není narušena funkčnost programu. To je velice záludné, protože program sice chodí, ale je špatně navržen.
Jak tedy na první pohled zjistíme, že je něco s umístěním kódu podle tohoto principu špatně?
Představme si, že píšeme kód v nějakém editoru. V této dané chvíli při otevřeném kódu existují vlastně pro nás paradoxně pouze tři vrstvy kódu. Nazvěme je A, B a C anebo také „nalevo“, „uprostřed“ a „vpravo“, viz obr.:
Šipky označují směr použití, tj. označují, která vrstva kódu používá služby jiné vrstvy. Takže vrstva A nalevo používá B, přitom B používá vrstvu C. Vrstva B je „naše vrstva editovaného kódu“, tj. doslova to, co vidíme v editoru kódu a co nyní kódujeme (např. kódujeme metodu objektu, zavádíme atributy třídy apod.)
Vrstva A na obrázku je pro nás vrstvou „vnější“ a je to vrstva kódu tzv. anonymního klienta. Ten je mimo naši kontrolu (viz kapitola o Objektovém paradigmatu v knize volně ke stažení zde). Vlevo je tedy ten kód, který bude využívat naše služby, které touto vrstvou kódu nabízíme. V OOP se jedná o tyto možné interakce: Buď nabízíme interface objektu (volání metody objektu), nebo nabízíme statickou metodu třídy anebo nabízíme možnost využít inheritanci pro budoucí potomky.
Dobrá představa je, že vnější kód v A je nějaký kód od našeho kolegy (i když tomu tak nemusí být, můžeme jej programovat také my), který si „nějak přilinkuje“ náš kód, který nyní zrovna editujeme, a použije jej. Tuto jeho vrstvu samozřejmě nevidíme, ale pro ni nabízíme naše služby (např. „hlavičky metod“ neboli interface).
Střední vrstva B je vrstvou „našeho kódu“, tj. kódu, který prakticky vidíme v editoru nyní při editaci. Je to „náš kód“, který implementuje služby nabízené pro vrstvu A vnějšího anonymního klienta. Pokud píšeme metodu objektu, je to kód této metody anebo ve třídě tvoříme atributy dané třídy apod.
Pak je třetí vrstva napravo, vrstva C. Tam je kód, který používáme my, tj. my jsme vůči němu klientem podobně jako vrstva A je naším klientem. Tato vrstva kódu je sice „vnitřně neviditelná“, ale vidíme z ní „trčící“ možnost použití, např. přes interface objektu (s voláním metody resp. funkce apod.) anebo můžeme z tohoto kódu podědit.
Toto rozložení kódu na tři vrstvy se jeví jako primitivní a jednoduché… až na to, že zde se nejčastěji chybuje. Problém je v tom, že u konkrétního daného kousku kódu se chybně určí jeho pozice, tj. kód se umístí do té vrstvy z těchto tří, kam nepatří. A to je chyba vedoucí v důsledku k porušení principu jedné odpovědnosti.
Naopak platí, že pokud umístíme kód vždy tam, kam z těchto tří vrstev správně a korektně patří, potom je splněn princip jedné odpovědnosti a tím je také ekvivalentně splněna „čistá opětovná použitelnost“ znějící takto: Ten, kdo potřebuje nějaký kus kódu použít, tak jej dostane pro znovupoužití, ale při tomto použití nedostane k tomu ještě přídavkem něco navíc, tj. nedostane navíc balast, který nepotřebuje. Pokud balast dostane, tak je kód sice funkční, ale špinavý, nepřehledný a netransparentní. Takže základní problém spočívá v tom, že takový kód s balastem je sice funkční, ale špinavosti se časem projeví, zejména tehdy, pokud se nakupí.
Jak tedy rychle postupovat při posuzování čistoty?
Stačí, když budeme číst a analyzovat naši vrstvu B (samozřejmě toto provedeme pro každou vrstvu), tedy tu prostřední otevřenou vrstvu kódu. U každé části kódu této naší editované vrstvy posuzujeme, zda do naší vrstvy B patří nebo ne. Protože existují pouze další dvě vrstvy „vlevo“ anebo „vpravo“, mohou při špatném umístění kódu nastat pouze dvě chyby – chyba „levá“ anebo chyba „pravá“.
První možnost, jak zanést špinavost do kódu, spočívá v tom, že daná část kódu je sice u nás v B, ale nám nepatří a správně patří „vlevo“, tj. někam do vnější vrstvy A. Chybně je tento kód umístěn do naší vrstvy B a přitom patří do A ke klientovi vlevo. Tomuto efektu se říká také „zašpinění vnitřní vrstvy“ alias „míchání tříd“ anebo také „tvorba kočkopsa“ anebo také „zavedení molochální třídy“. Systém je sice funkční, ale špinavý a promíchaný slepenec.
Typický příklad: Zavedeme v systému evidovanou osobu ( = rodné číslo, jméno, příjmení) a k tomu ještě přidáme do této třídy osoby údaje evidovaného studenta (semestr, prospěch, atd.) a k tomu ještě přidáme údaje evidovaného zaměstnance (číslo, plat, atd.). Fungovat to bude, ale je to samozřejmě špatně.
Správně měla zůstat „osoba“ pouze „čistou osobou“, která má být použita třídou student resp. třídou zaměstnanec. Tuto chybu „zašpinění vnitřní vrstvy“ vystihuje obrázek:
Je zřejmé, že tímto promícháním tříd je porušena čistá opětovná použitelnost, protože když chceme pracovat se studentem, dostaneme i zaměstnance se všemi důsledky. Například pokud se vyskytne fatální chyba ve studentech, přestanou fungovat i zaměstnanci. Všimněte si, jak nelogicky potom zní hovor, když uživatel nahlásí chybu ve smyslu: „Nechodí nám agenda se zaměstnanci.“ A my na to odpovíme: „No jo, máme chybu ve studentech.“ „Trochu divné“, odpoví laik myslící zdravým selským rozumem…
O druhé možnosti porušení principu jedné odpovědnosti pojednáme v pokračování článku příště.
Napsat komentář