Vítejte na blog.vyvojar.cz Přihlásit | Registrovat | Pomoc

Ars programatica

Udělat dobrý sotware je řemeslo, udělat výjimečný software je umění
Fundamenty objektového paradigmatu

V diskusi pod článkem Můžeme se obejít bez dědičnosti vyvstala otázka, jaké že jsou vlastně základní pilíře OOP. Ukázalo se totiž, že každý za ně považuje něco jiného. Následujícím text je reakcí na tuto diskusi.

 

 

 

Základní vs. odvozené

Předně je třeba si ujasnit, jaký je rozdíl mezi pojmy primárními a sekundárními, čili základními a odvozenými. Odvozené (sekundární) pojmy je možno vyjádřit pomocí pojmů základních (primárních), zatímco naopak to neplatí. Jinak řečeno, existence sekundárních vlastností je bez existence primárních nemožná.

Bohužel, v případě OOP je realita taková, že primární a sekundární pojmy jsou často směšovány a zaměňovány, a nejednou to jde až tak daleko, že jsou sekundární pojmy ztotožňovány přímo s OOP samotným. Důvod tohoto nepochopení je nasnadě: sekundární pojmy se odrážejí přímo v objektových programovacích jazycích a bývají tím prvním (a pohříchu často jediným), s čím přijde nový adept OOP do styku.

Dělení pojmů na základní a odvozené je následující: Primární pojmy jsou identita, zapouzdření a skládání; sekundární jsou třída, dědění, polymorfismus.

V dalším textu proberu jednotlivé pojmy podrobněji a pokusím se vysvětlit, proč mnou uváděné rozdělení mezi pojmy primární a sekundární odpovídá výše uvednému.

Objektového paradigma

Výpočetní model

Možná poněkud netradičně začnu výpočetním modelem, který stojí ve středu programu vytvořeného podle paradigmatu OOP. Platí, že objektový program je systém, tedy množina prvků a vazeb mezi nimi (statická struktura), která vykazuje v čase identifikovatelné chování (dynamika). A právě tato dynamika, tedy v čase rozpoznatelné změny, je reprezentována výpočetním modelem, který je v OOP založen na posílání zpráv.

Jinými slovy, běh objektového programu spočívá v posílání zpráv mezi objekty a v jejich zpracováním na straně příjemce.

Je ovšem důležité mít na paměti, že toto platí pro konceptuální úroveň. Na fyzické úrovni, tedy v počítači, může být konkrétní realizace jiná, například volání procedur, skoky do podprogramů, přerušení.

Základní pojmy

Identita

Identita objektu znamená, že každé dva objekty jsou od sebe navzájem odlišitelné na základě prostého faktu své existence. Identita objektu nijak nezávisí na hodnotách vnitřních atributů objektu.

Toto je kardinální rozdíl například ve srovnání s relačními databázemi, ve kterých není z konceptuálního hlediska možno rozlišit dva záznamy, které mají stejné hodnoty všech atributů. Mimo jiné proto se do relačních tabulek zavádějí primární klíče, aby bylo možno přesně určit, který záznam je který. Identita objektu na konceptuální úrovni však není žádné číslo, není to primární klíč, je to fakt.

Identita je nezbytným předpokladem pro správnou funkci výpočetního modelu, protože pouze na jejím základě je možno přesně určit, kterému objektu je zpráva určena.

Zapouzdření

Každý objekt je vzhledem k svému okolí „černá skříňka“, která se navenek reprezentuje pouze svým protokolem – množinou zpráv, které je objekt schopen přijmout. Žádný z dalších prvků systému (objektů) nemá žádnou znalost o tom, co je uvnitř, jak je dotyčný objekt implementován.

Zapouzdření je klíčovým předpokladem pro zachování konzistence systému, protože vylučuje, aby data (tedy stav) objektu mohl neočekávaně či nesmyslně změnit jiný objekt. Zapouzdření přesně vymezuje odpovědnosti a jeho důsledkem je každý objekt může svá data považovat vždy za validní, protože nikdo jiný než on sám je nemůže změnit.

Zapouzdření představuje nejenom nástroj pro zajištění bezpečnosti a konzistence dat (potažmo celého systému, respektive programu), ale v podstatě vynucuje (opět na konceptuální úrovni) anonymitu klienta, čímž přispívá k lepší udržovatelnosti a škálovatelnosti programu.

Bez zapouzdření by nebylo možno jednoznačně určit, kde jsou hranice objektu, která data jsou jeho, a tedy za jaká data je objekt ještě odpovědný, a za jaká již ne.

Skládání

Skládání je vyjádřením HAS-A vztahu. Skládání znamená, že jeden objekt v sobě může obsahovat jiný objekt. Často se v této souvislosti hovoří o vztahu pán-sluha, protože typickou motivací pro vytvoření tohoto vztahu je, že pán (celek) pověřuje (deleguje) sluhu (část) vykonáním těch operací, které sám neumí. Navenek to však vypadá, jako kdyby vše vykonával sám pán (viz zapouzdření).

Skládání umožňuje vyvářet vazby mezi objekty, tedy definovat strukturu programu, a tím jednoduše a intuitivně směrovat zprávy k jejich příjemcům. Bez skládání by nebylo možno vytvořit navigační graf, ale program by sestával s chaotické změnit objektů, z níž by se příjemci zpráv museli složitě vybírat.

Je dobré rozlišovat dva typy skládání: silnou a slabou vazbu. Silná vazba (agregace) představuje takový vztah, kdy existence části bez existence celku nemá smysl. Slabá vazba (asociace) je vztah dvou objektů, které mohou existovat samostatně.

Odvozené pojmy

Význam odvozených pojmů tkví v tom, že usnadňují tvorbu programu, zlepšují udržovatelnost kódu, zvyšují kvalitu (a čitelnost) výsledného kódu. Odvozené pojmy tedy představují velmi silné a prospěšné nástroje pro úspěšnou tvorbu programu podle objektového paradigmatu, nejsou však pro vytvoření funkčního programu nezbytné, na rozdíl od pojmů základních.

Třída

Třída je šablona na instance. Třída určuje, jaké atributy (datové členy) a metody (funkční členy) bude objekt mít a umožňuje rychle a bezpečně vytvářet objekty, které mají stejný protokol, stejný počet a typ datových členů a stejné metody (jejichž kód je často sdílený na úrovni třídy), a liší se od sebe (není to však podmínkou) pouze v hodnotách svých datových členů.

Třída ovšem není totéž, co typ. Objekty, které reprezentují entity (není míněna entita v kontextu relačního paradigmatu), stejného typu, jsou rovněž stejného typu, přestože k jejich vytvoření nemusí být použita třída (šablona).

Třída není pro vytváření objektů nezbytná, každý objekt je vždy možno postavit „na zelené louce“, tedy vždy zas a znova specifikovat všechny jeho členy. Neexistence tříd neznamená nemožnost vytváření objektů, ovšem z důvodů značné redundance nebezpečně zvyšuje rizika spojená s tvorbou a údržbou programu.

Dědění

Dědění je vztah IS-A, tedy vztah mezi podobnými typy, z nichž jeden je spíše abstraktní (předek) a druhý spíše konkrétní (potomek).

Pro dědění platí obdobně jako pro třídu, že není nezbytné pro vytvoření programu, protože lze členy všech typů definovat vždy znova; samozřejmě s riziky, která jsou spojena s redundancí. Vzhledem k existenci zapouzdření je jedno, zda objekt získal některé své vlastnosti děděním, nebo je má nadefinovány znova, navenek to nelze nijak rozlišit, protože protokol (na kterém z pohledu výpočetního modelu jedině záleží) je v obou případech stejný.

Dědění lze velmi dobře nahradit skládáním tak, že „potomek“ skládá svého „předka“ a deleguje na něj ty operace, které jsou pro oba stejné, a sám vykonává pouze ty, ve kterých se liší.

Polymorfismus

Polymorfismem je obecně míněno, že stejná zpráva vyvolá různé reakce, které se mohou lišit podle typu příjemce (polymorfismus 1. druhu), ale i podle času (polymorfismus 2. druhu), či dokonce podle typu volajícího (polymorfismus 3. druhu).

Existence polymorfismu implicitně vyplývá z existence protokolu, výpočetního modelu a zapouzdření. Objekt zprávě (výpočetní model) buď rozumí, nebo nerozumí (protokol), pokud jí rozumí, je zcela na jeho odpovědnosti, jak jí zpracuje (zapouzdření).

Polymorfismus tedy není třeba definovat jako základní pojem, protože ze základních implicitně vyplývá.

Závěr

Jistá zmatečnost, která v ohledu dělní na základní a odvozené pojmy panuje, je podle mého přesvědčení způsobena tím, jak jsou navrženy (dominantně používané) programovací jazyky, které ve své většině neumožňují přístup k základním pojmům jinak, než prostřednictvím pojmů odvozených.

Všechny mně známé objektové programovací jazyky neumožňují vytvořit objekt jinak, než jako instanci třídy, přičemž každá třída vždy dědí (často implicitně) od jednoho triviálního předka (většinou třídy Object).

Mojí snahou bylo osvětlit rozdělení pojmů obecně užívaných v OOP na základní a odvozené a toto dělení i náležitě zdůvodnit. Obecný princip dělení je takový, že funkční (což ještě neznamená snadno realizovatelný a snadno udržovatelný) objektový program je možno vytvořit pouze na základně pojmů základních, naopak pojmy odvozené k vytvoření takového programy samy o sobě nestačí.

Posted: 30. července 2008 18:07 by pbouda
Vedeno pod:

Komentář

Borek napsal:

Na teoretický článek je to moc hezky a čtivě napsáno, díky.

# července 31, 2008 8:17

naraga napsal:

vynikajuci clanok!!!

# srpna 4, 2008 16:36

SB napsal:

Výborný článek. Akorát to asi někteří čtenáři nepřekousnou...

# července 27, 2010 15:25
Nejsou povoleny nové komentáře k tomuto příspěvku
Vyvojar.cz na prodej!