NAUČTE SE MALOVAT SI INSTANCE! část 2. RNDr. Ilja Kraval, září 2009 http://www.objects.cz
ÚVOD
V předešlém článku jsme otevřeli jeden ze základních problémů, který musí analytik řešit: Jak vypadá skladba informace v informačním systému. Uvedli jsme, že pomocí někdy až hektických konzultací s budoucím zákazníkem - zadavatelem analytik dospěje nakonec k určité představě, jak mají být informace v systému spravovány a v jakém jsou vztahu. Přitom však musí použít (ať už vědomky nebo nevědomky) základní vzor analytického návrhu – „Dichotomie třída instance“ na analytické úrovni. Upozornili jsme na to, že tento vzor se prolíná všemi úrovněmi abstrakce a jeho nasazení nalezneme v libovolné technologii. Na analytické úrovni abstrakce laik tomuto vzoru dobře rozumí a chápe jej, jenom o něm explicitně neví. Závěrem jsme uvedli, že práce s instancemi jako s příklady možné evidence je nezastupitelnou částí analytických postupů a je tedy třeba velmi dobře znát, jak se má s instancemi vlastně pracovat. Proto je na našich školeních této problematice věnována velká pozornost (například nepřehlédněte blížící se školení Návrh IS pomocí UML v Praze zde). Existují základní dvě situace, kdy práce s instancemi vystupuje do popředí: 1. Při vyhledávání vztahů mezi informacemi v systému 2. Při vyhledávání logických chyb ve stávajícím řešení O obou postupech pojednává tento článek. VYHLEDÁVÁNÍ VZTAHŮ MEZI INFORMACEMI V SYSTÉMU POMOCÍ INSTANCÍ
Při hledání vztahů mezi evidovanými informacemi a tedy vyhledávání analytických tříd musíme vždy nejprve uvažovat na úrovni instancí jako o příkladech evidence, poté teprve provedeme zobecnění do „meta vzorce“, tj. modelu tříd. Tento postup provádíme zákonitě vždy a nevyhneme se mu nikdy. Nikdo totiž ještě totiž nevymyslel vzorec metodou „ad hoc“ bez znalosti příkladů, které vedou ke znalosti tohoto vzorce.
http://www.objects.cz strana 2
V některých opravdu jednoduchých příkladech evidence je však matoucí to, že tento postup logického uvažování „od instancí ke třídám“ bývá opravdu dílem okamžiku, tj. několika málo desetin sekundy našeho přemýšlení a to aniž bychom si to uvědomovali. Například pokud zavedeme tzv. číselníkovou vazbu „Každé auto má svou barvu z číselníku barev“ takto:
Auto
+mB
Barv a
1
Obrázek 1 Každé auto má svou barvu z číselníku barev tak v tomto případě vidíme ihned v duchu evidované instance „několik aut“ na straně jedné a „seznam barev“ na straně druhé, přičemž každá instance auta má odkaz na jednu instanci barvy ze seznamu barev - přitom je díky povaze této vazby žádoucí, aby dvě instance auta, které mají tutéž barvu, ukázaly na tutéž instanci barvy. V takovýchto případech není nutné malovat si instance, protože je vidíme zřetelně a logika jejich vztahů po jejich zrození je jasná a transparentní. Jiná situace nastane, pokud je problém sám o sobě složitější a není na první pohled vidět.
ZNÁZORNĚNÍ INSTANCÍ PŘI SLOŽITÉ LOGICE PROBLÉMU
Jako příklad bych uvedl situaci v jedné firmě, která vyrábí informační systémy pro evidenci úvěrů, půjček a podobných finančních produktů. Jednou z opravdových lahůdek pro analytika je v takovém systému vymyslet logiku fungování splátkových kalendářů pro všechny typy úvěrů s následnou generací pokynů pro převody peněz z účtu klienta. V takovémto případě je umění „malovat si“ instance nezastupitelné. Existuje totiž příliš mnoho typů splátek, generovaných pokynů atd., které s daným produktem mohou souviset (splátky jistiny, splátky úroků, poplatky ze služby, sankční splátky a spousta dalších). Následují další požadavky na logiku, například možnost nastavení pořadí priorit splátek (např. pořadí splátek sankce, poplatky, úroky, jistina anebo sankce, úroky, poplatky, jistina apod.). Poté přidáme skutečnou analytickou delikatesu tzv. „rollback splátkového kalendáře“, například když se má vyřešit příchod opožděné platby. Znamená to mimo jiné, že již vygenerované sankce přestanou být platnými, ale už byly zaplaceny apod. Výsledkem je situace, kdy pokusy o nalézání tříd bez znázornění instancí jako příkladů evidence musejí nutně selhat a na 99 procent budou obsahovat logické chyby a nedostatky.
strana 2
http://www.objects.cz strana 3
ZNÁZORNĚNÍ INSTANCÍ PŘI VYHLEDÁVÁNÍ VZTAHU GENERALIZACE
Dalším případem, kdy je třeba malovat si instance, je vyhledávání vztahu Generalizace. Zde bych rád upozornil na jednu obzvlášť nebezpečnou chybu, které se může analytik dopustit při vyhledávání vztahu generalizace. Tato chyba je natolik rozšířená, navíc se bohužel hojně vyskytuje i v literatuře týkající se OOP anebo modelování v UML. Její záludnost spočívá v tom, že model tříd se zavedeným vztahem Generalizace vypadá sice „pěkně“, ale není logicky správný a systém je navržen chybně. Tuto chybu bych nazval „vyhledávání vztahu Generalizace metodou buldozer“. Prohlédněme si nejprve příklad vztahu Generalizace znázorněný takto:
A -
a1 a2
B -
C
b1 b2
-
c1 c2
Obrázek 2 Vztah generalizace (slangově dědičnost) Uvedený obrázek ukazuje, že třída B používá třídu A ve vztahu generalizace a stejně tak třída C také používá třídu A ve vztahu generalizace. Díky generalizaci tyto třídy spolu interagují jako dva předpisy, tedy třída B (jako předpis) použije třídu A (jako předpis – tedy pozor, zde není řeč o vztahu mezi instancemi!). Třídě, která je v generalizaci použita (zde A), se říká předek, a třídě, která používá (zde B a C), se říká potomek. Vrchní třída je třídou více obecnou a třída potomek je třídou více speciální. Generalizace v tomto případě znamená, že třída B použila třídu A ještě před vznikem instancí. Nejedná se tedy o interakci mezi instancemi, ale o interakci přímo mezi třídami, tedy o interakci, kdy jeden předpis použije rovnou a přímo druhý předpis, když rodí svou instanci. Důsledkem Generalizace na obrázku je, že když požádáme třídu B o vznik instance, tak třída B se kromě svého předpisu „podívá“ přes interakci Generalizace také na předpis třídy A a vydá instanci, která bude mít vlastnosti podobné situaci, jako kdybychom obě třídy (tedy předpisy obou tříd) slili dohromady. Totéž platí samozřejmě i pro třídu C. Tuto skutečnost strana 3
http://www.objects.cz strana 4
bychom mohli znázornit pomocí dalšího obrázku, kde si namalujeme také instance vzniklé z těchto tříd:
Obrázek 3 Vznik instancí z tříd, které interagují přes generalizaci
Chybná metoda vyhledávání generalizace jako „Metoda generalizačního buldozeru“ vychází z tohoto obrázku (a vřele ji nedoporučuji). Uvedená metoda spočívá v tomto postupu: Hledáme nejprve jako příklady instance a nalezneme pomocí rozhovoru se zákazníkem strukturu instance B1 jako (a1, a2, b1, b2). Třídy nyní ještě neznáme a zkusíme jako řešení zavést třídu B, která bude definovat tyto atributy. Poté hovoříme o instanci C1 a zjistíme, že instance má strukturu (a1, a2, c1, c2). Zavedeme tedy třídu C, která zavádí tyto atributy, a přitom si ověříme, že analyticky je a1 a a2 v obou případech totéž. To samozřejmě musíme vyřešit. Rozhodneme se tedy o vytknutí společného a zavedeme proto společného předka A, do něj dáme společnou strukturu. Dostaneme tak zmíněný předešlý obrázek s generalizací, kde A je předek.
strana 4
http://www.objects.cz strana 5
Vypadá to sice jako postup pěkně, když jsme dostali stejný obrázek. Ale v úvaze je bohužel jedna hrubá chyba spočívající v otočení implikace. Z předešlého obrázku generalizace správně vyplývá, že pokud vznikne instance ze třídy B, potom má vlastnosti (a1, a2, b1, b2) a stejně tak relevantně má instance z C atributy (a1, a2, c1, c2). Z toho ale vůbec neplyne opačná implikace: Jestli totiž nalezneme, že instance B1 „umí“ atributy (a1, a2, b1, b2) a C1 „umí“ (a1, a2, c1, c2), ještě z toho neplyne, že musíme použít generalizaci, abychom dosáhli tohoto efektu. V mnoha případech (a dokonce ve většině!) se „to společné“ vyřeší pomocí skládání instancí, tedy to společné se vloží do instance, která se kompozicí vloží do prvku B i C. Vznikne tak jiné a mnohdy lepší řešení, které řeší „to společné (a1, a2)“:
B -
b1 b2 1 A -
a1 a2
1 C -
c1 c2
Obrázek 4 Možné a mnohdy lepší řešení společné části informace A
Jako příklad bych uvedl tvrzení, že pokud evidovaný prvek typu X obsahuje IČO a evidovaný prvek jiného typu Y také obsahuje IČO (a jsou to prvky z různých tříd), vůbec to neznamená, že kvůli tomu musí mít společného předka. IČO lze totiž do obou prvků vložit jako kompozit ku jedné. Otázkou tedy je, jak se správně hledá Generalizace, když tato metoda není správná? Ke správnému nalezení vztahu Generalizace slouží jiný postup založený na hlavní vlastnosti Generalizace a tou je tak zvaná „zástupnost rolí neboli pojmů zespodu nahoru“. Namalujeme si ji jako pomyslnou šipku takto:
strana 5
http://www.objects.cz strana 6
A -
a1 a2
B -
C
b1 b2
-
c1 c2
Obrázek 5 Zástupnost rolí a pojmů zespodu nahoru
Prakticky se tato vlastnost projeví v efektu tzv. heterogenního linku mezi instancemi. To si nyní vysvětlíme nejčastěji používaném analytickém vzoru, který zavádí generalizaci.
VZOR HETEROGENNÍ SEZNAM
Vzor si vyjádříme pomocí následujícího obrázku:
A
X *
B
C
Obrázek 6 Vzor heterogenní seznam
strana 6
http://www.objects.cz strana 7
Všimněte si, že na straně kompozice ku N je jako třída „vlastněného“ uvedena abstraktní třída A. Z ní nikdy nebudou vznikat instance. Třídy B a C již nejsou abstraktní, tedy jsou konkrétní. Nyní je dobré si představit namalovanou zelenou šipku ve vlastnosti zástupnosti rolí zespodu nahoru. Ta funguje tak, že instance ze tříd B a C vstupují do vztahů linků z kompozice na straně vlastněných (jako by se vtělovaly do pozice v třídě A na konci kompozice) a jsou to tedy ony, kdo tento vztah v instancích realizují. Možný instanční model by mohl tedy vypadat například takto:
B1
B2
X1 C1
C2
B3
Obrázek 7 Heterogenní seznam v instancích
Všimněte si, že prvek X1 drží v seznamu instance z různých tříd (tedy z B i z C), ale přitom všechny linky v tomto vztahu jsou chápány jako instanční realizace jednoho jediného vztahu kompozice ku N v modelu tříd. Tuto situaci bychom pro vysvětlení mohli znázornit takto:
strana 7
http://www.objects.cz strana 8
jeden vztah kompozice ku N v modelu tříd
B1
B2
X1 C1
C2
B3
Obrázek 8: Několik linků do prvků z různých tříd, ale přitom se jedná o jeden vztah v modelu tříd A nyní se vrátíme k tématu článku: Dokud si nemalujeme tyto instance anebo si je dobře nepředstavíme v duchu, nejsme schopni heterogenní linky vidět a nalézt správným způsobem vztah Generalizace, tj. model pak obsahuje logické chyby. (poznámka: Této problematice je proto věnována velká pozornost na školeních viz například blížící se školení Návrh IS pomocí UML v Praze zde).
ZÁVĚR
Práce s instancemi jako s příklady možné evidence je nezastupitelnou částí analytických postupů a proto je dobré velmi dobře znát, jak se má s instancemi vlastně pracovat. Bez nich totiž nebude model tříd v pořádku. Jednak hrozí zavlečení logických chyb do modelu a kromě toho bez znázornění instancí můžeme zavést vztah Generalizace chybně se všemi nepříjemnými důsledky. Konec článku
Věnujte pozornost cenově výhodnému školení Návrh IS pomocí UML (termín 13.10.2009). Koná se přímo v Praze, pouze jeden termín v tomto roce!
strana 8