|
Doporučené Postupy při nalézání tříd v návrhu IS
autor: RNDr. Ilja Kraval, leden 2012
3. část
Object Consulting s.r.o.
Server objektových technologií
Úvod
V předešlých částech tohoto článku bylo poukázáno na nutnost použití jednoho ze základních principů, kterým je náhled na IS pomocí vzoru dichotomie třída -instance“ (pozn.: o tomto vzoru viz například kniha Analytické modelování volně ke stažení zdarma). Podle tohoto vzoru je informační systém rozdělen na dva prostory: Na prostor tříd jako prostor předpisů neboli šablon, které definují vlastnosti prvků - instancí, a na straně druhé na prostor instancí, které na základě těchto předpisů vznikají v průběhu evidence. Pomocí tohoto přístupu jsme v předešlé části nalézali nejenom třídy, ale také vztahy Asociace, tj. ty vztahy v UML definovanými mezi třídami, které vedou ke vztahům mezi instancemi. Tyto vztahy jsou většinou dost dobře viditelné - samozřejmě pokud z hlediska analýzy pochopíme požadovanou logiku evidence, pak není problém vztahy Asociace nalézt a znázornit je podle UML syntaxe.
V tomto článku si popíšeme postup vyhledávání posledního vztahu mezi třídami a tím je Generalizace.
analytická Podstata vztahu generalizace
Vztah Generalizace je analytiky někdy opomíjen, protože strukturované programování jej až tak nezdůrazňuje.
Oproti tomu v principech objektového programování je ekvivalent vztahu Generalizace znám již velmi dobře, protože jeho mapování z analýzy se do objektového programu v 99% provádí pomocí často používané dědičnosti (tj. inheritance).
Vztah Generalizace zavádí nový typ opětovné použitelnosti (re-use) tak trochu zvláštním způsobem: Zatímco Asociace využívá pro zavedení opětovné použitelnosti interakci mezi instancemi (tj. jedna „naprogramovaná“ instance může díky Asociaci mezi třídami použít druhou „naprogramovanou“ instanci a tak vznikne re-use kódu), Generalizace používá pro zavedení re-use jiný princip interakce: Využije se vztah přímo mezi pojmy, tj. třídami (nikoliv mezi instancemi).
Následující obrázek znázorňuje pomocí šipek, jak třída (jako zobecněný vzorec pro instance) použije jinou třídu (druhý vzorec) a tak spolu interagují dva vzorce - třídy a nikoliv instance:
Obrázek 1 Interakce mezi třídami při Generalizaci, směr re-use
Generalizaci je vhodné číst ve směru šipek, tedy ve směru použití, tj. od „potomka“ k „předkovi“, protože takto přesně Generalizace funguje: Na obrázku třída B používá třídu A a současně tutéž třídu používá i třída C. Výsledkem interakce Generalizace je, že pokud vznikne z třídy B instance, potom tato třída B při zrodu instance díky interakci Generalizace použije třídu A.
Pokud se hlouběji zamyslíme nad vztahem re-use mezi pojmy, který zobrazuje předešlý obrázek, tak zjistíme, že důsledkem tohoto re-use mezi pojmy je vlastně vztah zobecnění alias Generalizace (a proto se tento vztah takto nazývá): Jestli totiž dva „nižší“ pojmy, které definují vlastnosti budoucích prvků, používají jiný „vyšší“ pojem (používají jeho definici vzorce pro instance), jedná se logicky vzato o zobecnění, protože společný pojem je obecnějším pojmem a nižší pojmy jsou jeho specializací.
Poznámka: I v občanském životě zobecnění používáme: Říká se sice „nemíchej Hrušky s Jablky“, ale ono se to dá - zavedením obecnějšího pojmu Ovoce. Jestliže někdo nese košík Ovoce, jsou v něm povoleny jak Hrušky, tak Jablka a do budoucna libovolný prvek z dalšího pojmu - potomka pojmu Ovoce.
Interakce re-use je v Generalizaci velice silná a navíc výrazně zvyšuje flexibilitu a přehlednost programu: Pokud totiž naprogramujeme nějaký algoritmus aplikace na „horní“ úrovni pouze vůči obecnější třídě (viz „nesu košík ovoce“) potom tento algoritmus je aplikovatelný na prvek z dalšího do budoucna zavedeného potomka této třídy.
Vyhledávání Generalizace
V knize Analytické modelování (volně ke stažení zdarma) je hned v úvodu popsána častá chyba vyhledávání vztahu Generalizace pomocí metody Buldozer, viz strana 69.
Základní vlastností Generalizace je ta skutečnost, že všude, kde se na konci asociace objeví třída předka, může v této pozici v instancích sehrát roli libovolná instance z konkrétního potomka, protože umí tuto roli díky dědičnosti sehrát (tj. umí se vložit do konce asociace na místě svého předka). Obecnější pojem předka se tak stává zástupným pojmem pro libovolného konkrétního potomka, který může tuto roli díky generalizaci sehrát.
Postup vyhledávání Generalizace využívá určitého specifického efektu, který je důsledkem předešlé vlastnosti. Tento jev je pro Generalizaci natolik příznačný, že jej doporučuji jako dobrý signál pro vyhledání tohoto vztahu v modelu tříd.
Jak bylo řečeno v předešlých článcích, při vyhledávání vztahů mezi třídami vycházíme vždy z představ o instancích a to i v případě, kdy si to vlastně ani neuvědomujeme. Nejinak je tomu i v případě Generalizace. Pokud je totiž v modelu tříd použita Generalizace, mezi instancemi se to projeví následující situací:
Existuje několik linků (tj. vztahů mezi instancemi), které mají tutéž povahu vztahu Asociace, tj. vyjadřují totéž), ale na konci linků stejné povahy se vyskytují instance z různých tříd.
Uveďme si tuto vlastnost na příkladu na instance košíku s ovocem. Zaveďme jako příklad jednu instance K1 pocházející z třídy Košík, tato instance obsahuje ve vztahu linku komposice instance H1, H2, H3 ze třídy Hruška a instance J1, J2, J3 a J4 ze třídy Jablko. Existuje tedy 7 linků mez prvky - instancemi, viz následující obrázek
Obrázek 2 Instance hrušek a jablek v instanci košíku
Při pohledu na instance máme nyní na výběr dvě analytická řešení pro model tříd - tedy pro zobecnění od vzorců pro instance, přičemž obě řešení vedou k témuž předešlému obrázku s instancemi:
1. možnost bez použití Generalizace Bez použití Generalizace vyslovíme následující tvrzení: „Každý Košík bude obsahovat N Hrušek a současně bude obsahovat N Jablek“, model tříd pak vypadá takto:
Obrázek 3 Zobecnění košíku s hruškami a jablky bez Generalizace
2. možnost s použitím Generalizace S použitím Generalizace vyslovíme jinou větu: „Každý Košík obsahuje N Ovocí, což mohou být speciálně Hrušky a Jablka.“. Model tříd potom vypadá takto:
Obrázek 4 Zobecnění téhož modelu instancí do tříd pomocí Generalizace
Rozdíl obou řešení je zřejmý: Použití Generalizace má vyšší stupeň re-use, lze totiž naprogramovat algoritmy na úrovni „Košík s Ovocem“ pouze na horní úrovni předka. Instance z potomků automaticky tento algoritmus znovupoužijí, navíc klasické „neobjektové“ řešení bez generalizace je méně flexibilní, protože přidání dalšího typu ovoce vede u neobjektového řešení k „překopání košíku“ přidáním nového sezamu namísto jednoduchého přidání dědice v případě objektového řešení s Generalizací.
Vyhledávání Generalizace se tedy děje opět přes instance (mnohdy aniž bychom si to uvědomovali) a používáme přitom efekt heterogenních linků, kdy dané linky propojující instance mají všechny stejný analytický význam, tj. linky pocházejí ze stejné Asociace, ale přitom na koncích se vyskytují u těchto linků instance z různých tříd.
Poznámka: Je dobré připomenout, že ve zmíněné knize naleznete ještě dva základní vzory použití Generalizace, jejich znalost také napomůže najít snadněji tento vztah.
Závěr
V této kapitole si shrneme doporučení ze všech tři částí celého článku:
1. Musíme si vytvořit (byť jen v duchu) představu několika příkladů instancí a jejich vztahů (tzv. linky v UML).
2. Metodou „pokus omyl“ se snažíme z těchto příkladů nalézt obecnější meta-vzorec v modelu tříd, který bude platný jak pro naše instance, tak i pro libovolné další instance v budoucnu se narodivší.
3. Mezi instancemi hledáme vztahy Asociace a to pouze tyto: a. kompozice ku N res. kompozice ku 1 b. odkaz do seznamu c. sdílená agregace d. asociační třída
4. Vyhledáváme současně také Generalizaci metodou zástupností pojmů u heterogenních linků - nalézáme ty linky (tj. propojení instancí) stejného významu (vyjadřují analyticky totéž, např. „košík obsahuje ovoce“) a přitom instance na koncích u různých linků pocházejí z různých tříd (tj. na daném konci budoucí Asociace instance v lincích nepocházejí z jedné třídy)
Konec článku
|
|
|
|