Názor k použití objektů podle Ronnieho
Minulý týden jsem si přečetl příspěvek Ronnieho "Proč používat objekty - pokračování" a nedalo mi to, abych nereagoval v komentářích. Přeci jen mám trochu jiný pohled na danou problematiku vycházející z mých zkušenosti a dosavadních znalostí.
Pod článkem se rozjela fajn debata, ze které jsem poznal pohled i jiných vývojářů na používání objektů. Pokud jsem správně pochopil jejich výroky, nelíbí se jim možnost používat protected viditelnost u objektů. Konzistence a zapouzdření je pro objekty požadováno, avšak můj názor je takový, že tyto požadavky nejsou porušeny tím, že objekt zpřístupní svůj rozšířený interface svým potomkům. Znamená to, že objekt má vesměs dva (v případě .net tři) přístupné interface.
Public interface
První interface je tvořen public viditelností vlastností a metod. Tento interface je přístupný všem okolním objektům, které chtějí s naší instancí třídy komunikovat.
Rozšířený interface za pomoci protected viditelnosti
Public interface však není jediný, který může architekt zpřístupnit. Dalším a neméně důležitým je i tento interface - byť se to někomu nemusí zdát. Samozřejmě v tomto případě hodně záleží na samotném tvůrci, aby zajistil, že tento interface neporuší konzistenci objektu. To znamená, zpřístupnil pouze takový interface, který konzistenci neporuší. Nemusí se však jednat o public interface, ale pouze takový, který uvidí třídní potomci. V .net frameworku, a vesměs asi v každém propracovaném a dobře navrženém frameworku, nalezneme spoustu tříd, který zpřístupňují svůj rozšířený interface svým potomkům.
K čemu rozšířený interface použít
Napadá mě hned několik možností, při kterých návrhář třídy bude využívat tohoto rozšířeného interface k zajištění konzistence a přitom nedojde k porušení zapouzdření. Pro lepší názornost bude vhodnější uvést příklad takové třídy a jejího potomka.
Dejme tomu, že máme třídu Osoba, která má několik vlastností (atributů) a metod pro manipulaci s touto třídou. Jednou z veřejných metod je i metoda pro uložení objektu, tato metoda by měla zkontrolovat, zda je při splnění komplexnějších podmínek umožněno uložit objekt Osoba. Tyto podmínky platí i pro potomky.
V případě, že bych Osoba poskytovala pouze veřejný interface, musel by každý potomek zajistit kontrolu těchto podmínek, neboť ukládání je pro každého potomka malinko odlišné. Jak si ale v takovém případě může být autor třídy Osoba v tomto jistý? Řešení je v tomto případě zajištěno implementací návrhového vzoru Template method a tedy rozšířením interface pomocí protected metody. V takovém případě nebudeme public metodu k uložení označovat jako virtuální a po zkontrolování podmínek budeme volat protected metodu.
Taková třída tedy může vypadat následovně:
public abstract class Osoba {public void Save() { if (podminkySplneny()) { saveInternal(); } else { // zalogování informací a případné vyvolání výjimky }}protected abstract void saveInternal();}
Tímto způsobem máme zajištěno, že objekt zůstane zapouzdřený a viditelný zůstane pouze požadovaný veřejný interface, neboť je celkem oprávněný požadavek, aby okolí nemohlo volat žádost o uložení objektu, bez kontroly splnění podmínek.
Je to jen jeden z mnoha případů, proč si myslím, že není nebezpečné používat také protected viditelnost u objektů. Ale jak jsem se již někde vyjadřoval, vše je to o konkrétním člověku. Pokud navrhnu veřejný interface špatně, může to být více nebezpečné než pokud správně navrhnu celou třídu i s rozšířeným interfacem.
Samozřejmě je to jen můj pohled na danou problematiku a nemusí to být ten nejlepší pohled, vychází však z mých současných znalostí a zkušeností. Určitě se nebudu bránit jakékoli konzultaci nebo připomínkám, neboť jenom tak je možné si utřídit poznatky a porovnat je s okolím.
1 Comment
Vlasta said
To co popisuješ v článku je tzv. "Open/Closed princip". Open for extending, Close for modification.
Ještě bych doplnil, že metoda Save v třídě Osoba by měla být final - jinak by si její potomci mohli tuto metoda překrýt a vesele ukládat bez splnění podmínek.