Tento článek navazuje na předešlé 2 články o číselnících a uvedeme si v něm praktické příklady týkající se této agendy.
Analytický zápis řešení 3 v UML
Obecně je pro analytika velmi důležitou otázkou, jak nalezenou variantu řešení srozumitelně a korektně zapsat do analytického modelu tak, aby programátor následně správně pochopil zadání, například ve formě Tasku ve SCRUMU, tj. aby díky informačnímu šumu „neměl kam uhnout“. Uveďme si proto zápisy analytického modelu jako konkrétní situace z konkrétní agendy.
Půjčíme si příklad přímo z analytického workshopu resp. e-learningového kurzu profesního růstu analytika AM PROFESSIONAL , kde účastníci řeší v praxi analytický model jedné specifické agendy. Tato agenda má za úkol evidovat externí spolupracovníky dané firmy (tzv. „freelancery“) a jejich úkoly i s průběhem. Jednoduše řečeno nechť nějaká firma potřebuje řešit úkoly, které přiděluje externím spolupracovníkům (freelancerům) a veškerý průběh této spolupráce se eviduje v této agendě. Úkolem účastníků kurzu resp. workshopu je tuto agendu navrhnout.
V určité fázi prací ve workshopu resp. v internetovém kurzu se v návrhu této agendy poměrně dost rychle (díky dodržení agilnosti vývoje) přechází k analytickému modelu tříd. Uveďme si nyní na několika příkladech, jak by měl vypadat zápis nasazení našich kódovníků v praxi pomocí CASE nástroje Enterprise Architect (a současně ukážeme i přínosy našeho řešení). Současně si ukážeme, jak silná může být opětovná použitelnost a nasazení analytických vzorů.
Nechť jako příklad potřebujeme zapsat tyto 3 následující myšlenky:
- Feelancer nabízí N možných typů spolupráce (OSVČ, práce na dohodu případně další). Typy spolupráce spadají pod naše řešení kódovník. Při konkrétním řešení přiřazeného úkolu pro Freenlancera bude vybrán právě jeden prvek typu spolupráce k danému přiřazenému a řešenému úkolu.
- V agendě se bude často používat prvek Info nesoucí informaci. Každý prvek Info obsahuje buď odkaz na soubor nebo odkaz na vnější URL nebo pouze prostý text. Prvky Info se používají všude možně jako „vloženiny“. Prvky mají svůj význam alias Info Meaning (např. CV Freelancera, Hodnocení Freelancera, Profilová fotka apod.). Entita Info Meaning neboli význam Info bude opět kódovníkem.
- Řešení entit se stavy se zobecní pro libovolný stavový stroj. Stavový stroj se bude vkládat do dané entity kompozitem ku jedné (jedna entita tak může mít vloženo několik stavových strojů). Stavy daného stavového stroje zavedeme jako prvky kódovníku. Daný stavový stroj dané entity bude určen jednoznačně odkazem na daný kódovník stavů (tj. daný kódovník stavů je přiřazen k danému vloženému stavovému stroji) a stav bude určen prvkem z tohoto kódovníku. Příklady stavových strojů a odpovídající kódovníky:
a) Freelancer bude mít stavy (i s historií) zda je použitelný anebo nikoliv. Kódovník CodeList se bude nazývat „FL Availability“, prvky budou „použitelný, nepoužitelný“. (Poznámka: Nestačí jen atribut boolean, protože chceme i historii stavů, tj. nejsnadněji řešíme pomocí již řešeného stavového stroje).b) Kódovník stavů Tasku se nazývá „Task Processing States“ a má hodnoty „připravován, vyhlášen k nabídce, řešen, pozastaven, ukončen“.c) Kódovník stavů Tasku přiřazeného k Freelancerovi z titulu finančního se nazývá „FL Task Financial States“ a má stavy „není nutné vyrovnání, před vyrovnáním, probíhá zpracování pro vyrovnání, platba na cestě, vyrovnáno, znovu otevřeno“. (pozn. stav „není nutné vyrovnání“ odpovídá spolupráci na projektu Open Source bez nároku na odměnu)
Zápis myšlenek do modelu pomocí AM Class Modelu
Začněme tyto myšlenky zapisovat do AM Class Modelu. Nejprve zavedeme centrální agendu kódovníků podle řešení 3 takto:
Kód a text se opakují v obou entitách, takže se musí naprogramovat dvakrát. Pokud by však nastala situace, že by číselníky a jejich prvky měly o mnoho více společných vlastností než jenom kód a text (například ještě historie apod.), tak i ty by se také musely programovat dvakrát, což se jeví z principu re-use jako velmi nevýhodné. V tom případě by se pro opětovnou použitelnost nasadilo buď skládání objektů kompozicí ku jedné anebo se nasadila Generalizace (dědičnost) např. takto:
Je třeba ale podotknout, že v tomto případě by se Generalizace nevyužila v klasickém pojetí dědičnosti, tj. jak to zavádí princip paní Liskovové (viz např. Liskov Substitution Principle) jako využití zástupnosti instancí potomka v roli předka, ale zde by byla dědičnost nasazena pouze pro re-use společných vlastností. Z toho důvodu by stačilo pro re-use použít také skládání kompozitem ku jedné, kdy společné vlastnosti by se vložily jako dva „dummy for re-use“ objekty z téže třídy do obou prvků CodeList a CodeListItem (datově v RDB obě řešení vedou k vazbě mezi tabulkami 1:1).
Nyní máme jednoduše zavedenu agendu kódovníků a začneme ji využívat pro vyjádření našich myšlenek. U řešení 3 kódovníků musíme v modelu tříd zavést požadovaný číselník jako vybranou instanci ze seznamu číselníků, k čemuž v UML slouží mechanismus zvaný „constraint“.
Feelancer nabízí N možných typů spolupráce (OSVČ, práce na dohodu případně další). V tomto případě nasadíme silný vzor Vlak má svoje vagóny (tj. FL má N odkazů do seznamu typu spolupráce) a povedeme odkazy do číselníku Coop Type (viz constrainty):
Podobně vyřešíme i situaci s entitou Info (obecná informace jako soubor, URL nebo text) např. takto:
Pro vyjádření dalších myšlenek ohledně stavů entit nejprve zavedeme velice jednoduchý obecný stavový stroj, který budeme využívat tak, že do dané entity vložíme jednu instanci tohoto stroje jako kompozit ku jedné. Pro návrh tohoto jednoduchého stroje použijeme opět silný vzor Vlak má svoje vagóny (neboli Stavový stroj má svoje stavy ze seznamu stavů). Protože v našich řešeních budou stavy stroje časově vždy na sebe navazovat (u evidence z vnějšího světa to nemusí platit), stačí evidovat okamžik zahájení daného stavu:
V daném diagramu si daná instance stavového stroje ukazuje na „svůj“ odpovídající číselník ze seznamu číselníků. Bylo by možné zavést i malou jednoduchou optimalizaci, kdy prvek StateMachine by si ukazoval na prvek CodeListItem jako na aktuální stav a je to ten prvek, na nějž si současně ukazuje také „nejmladší“ prvek StateBeginning. Aktuální stav by se pak nemusel pracně hledat přes „nejmladší“ DateTime a by by dán přímým odkazem.
Všimněme si, že pokud bychom nasadili agendu kódovníky pomocí řešení 1 „hardcoded“, měli bychom zde problém s tím, že každá instance stavového stroje by potřebovala novou entitu kódovníku a nefungoval by nám takto jednoduše re-use jako zde. Tady v diagramu je to navrženo jednoduše jako odkaz z StateMachine na CodeList s názvem mStateMachineMeaning. (Pozn.: Možná by se to u řešení natvrdo dalo řešit nějak přes generické typy, kde typ číselníku by se stal proměnnou <TCodeList> daného stavového stroje, ale zde v tomto řešení 3 takové složitosti nepotřebujeme).
Nyní máme agendu stavového stroje připravenu a opět vyjádříme dané myšlenky velmi jednoduše a to pouze vypsáním požadovaných kódovníků přes constrainty jako zadání, vše ostatní je díky zavedenému stavovému stroji již vyřešeno. Pro realizaci se jedná o zadání: Nejprve vytvoř daný požadovaný kódovník stavů daného stroje a proveď dosazení hodnot natvrdo podle tohoto zadání, které je zde vypsáno přehledně následujícím způsobem pomocé constraintů (pozn. u následujících diagramů musíte současně sledovat i předešlý diagram, kde je zobrazen detail řešení StateMachine) :
Freelancer ma stavy použitelnosti:
Stavy Tasku:
Finanční stavy Tasku přiřazeného k Freelancerovi:
Závěr
Všimněme si, jak se celá naše část agendy výrazně „zhutnila“.
Hlavními důvody jsou:
- Snaha o maximální opětovnou použitelnost v kódu (např. zvolené řešení 3 u kódovníků, zavedený stavový stroj atd.)
- Nasazení analytických vzorů (což je také opětovná použitelnost v opakujícím se řešení). Použili jsme vzory „CodeList“, „Vlak má svoje vagóny“ a „Jednoduchý stavový stroj“. Všimněme si řešení stavů u našich tří příkladů: Jedná se de facto o tři stejné situace, což výrazně zjednodušuje celé řešení včetně dokumentace.
Nejenom, že tento náš přístup výrazně urychluje vývoj (například ve SCRUMU a tvorbě Tasků a následně jejich realizace), ale také efektivně zjednodušuje dokumentaci, která se stává součástí vývoje jako „dokumentace in situ“, nikoliv „dokumentace ex post“.
Napsat komentář