V předchozím článku jsem se zabýval jednoduchými diagramy případů užití, jejichž hlavní předností je přehlednost pro všechny zainteresované. Komplikovanější systém však vyžaduje, abychom nalezli složitější vztahy mezi případy užití a aktory, protože jinak se z diagramu stane odpudivá a sémanticky rozplizlá pavučina zkonstruovaná z překřížených čar a oválů. Intuitivní orientace v tom, jaké funkční požadavky systém pokrývá a kdo se na nich podílí, bude pro každého účastníka projektu ztížená a u extrémně složitých systémů nemožná.

Na počátku všeho je problém

Před vysvětlením pokročilých vztahů mezi elementy v diagramu případů užití (UseCase diagram) je vhodné zmínit problémy, které před námi vyvstanou při vytváření složitých projektů, aby bylo zřejmé, že komplexní vztahy jsou reakcí na tyto problémy a ne samoúčelnou exhibicí analytického umu autorů jazyka UML.

  1. Při analýze bylo identifikováno mnoho aktorů, jejichž odpovědnosti se překrývají. Nepříjemným důsledkem této situace je nárůst relace přiřazení u každého případu užití, jež vyjadřují stále to samé – aktor xy používá tuto funkci. Potřebovali bychom najít způsob, jak sdílené odpovědnosti aktorů vyčlenit a navázat na jednu společnou entitu („pseudoaktora“), jejíž odpovědnosti by byly všemi aktory implicitně přejímány bez explicitního zachycení přiřazení každého aktora ke každému případu užití.
  2. Podobný problém představuje nárůst případů užití. Často nalezneme případy užití s mnoha společnými rysy, ale drobné nuance v jejich účelu či realizaci nám zabraňují vytvořit jediný invariantní případ zahrnující všechny variace. Jeden aktor často používá všechny podobné případy užití a proto v systému opět existuje množství nadbytečných vazeb přiřazení, jež znesnadňují pochopení relevance vztahů. Řešením by bylo vytvoření jednoho obecnějšího případu užití, k němuž by se aktor vztahoval a pod který by byly subsumovány všechny jeho varianty, takže by z diagramu bylo patrné, že přiřazení aktora k obecnému případu užití značí i přiřazení ke každé variantě obecného případu užití.
  3. Ve scénářích jinak nezávislých případů užití zjistíme v každém z nich stejnou sekvenci kroků – stejné chování systému. Namísto redundantního zachycení celého scénáře v textové specifikaci každého případu užití bychom chtěli vyčlenit společné chování do samostatného případu, na nějž se ostatní případy odkáží. Výhodou pro implementaci by také bylo, že místo zdržující ex post extrakce metody či třídy při refaktorizaci redundantního kódu vývojářem separujeme ihned v úvodní fázi analýzy sdílenou funkcionalitu a dáváme od počátku najevo vývojáři naši intenci, jak má být strukturován kód. Moje agresivní pravidlo číslo jedna v libovolné fázi návrhu a vývoje systému je: „Jakákoli duplicita musí být ihned odstraněna za použití veškerého analytického arzenálu“.
  4. Případ užití může být volitelně rozšiřován při splnění určitých podmínek. Chceme vizuálně zachytit, že do scénáře mohou být vloženy nepovinně další kroky, jež reagují na specifické podmínky konkrétní instance případu užití.

Snad ani nemusím dodávat, že při vytváření diagramu případů užití složitějších systémů se potýkáme se všemi zmíněnými problémy najednou.

Generalizace aktorů

Řešením problém s aktory, u nichž se překrývají odpovědnosti, je generalizace (zobecnění). Vytvoříme nového aktora, na nějž budou delegovány sdílené odpovědnosti. Představme si situaci, kdy vytváříme HelpDesk – systém, v němž se evidují závady nahlášené zákazníky a průběh jejich řešení. Pro každou nahlášenou závadu se zakládá takzvaný průvodní lístek (incident), jenž nese všechny informace o konkrétní závadě a průběhu řešení. (Zákazníka, sériové číslo výrobku, zda se jedná o záruční opravu). Při analýze je nám sděleno, že zakládat a upravovat vlastnosti incidentů může operátorka na call centru a řešitel incidentu. Rozhodnutí o uzavření incidentu může však vydat jen operátorka na call centru a řešení zapisuje pouze řešitel. Jde o typický případ – dva aktoři, jejichž množiny odpovědností mají společný průnik a současně každý z nich má své vlastní a s žádným jiným aktorem nesdílené odpovědnosti. Řešením je vytvoření (abstraktního) předka obou aktorů s názvem zakladatel a správce incidentu, jehož odpovědností bude vytváření a editace incidentů. Aktor je abstraktní, protože se jedná jen o hypotetický analytický konstrukt, který nemá žádnou předlohu v realitě. I když to není tak časté, i zobecnění aktoři mohou být konkrétní, to znamená že jde o plně autonomní a nezávislé role mající svůj předobraz v problémové doméně zákazníka. U generalizace vždy platí, že potomci mají („dědí“) všechny vlastnosti předka. Při generalizace aktorů potomci od předka dědí všechny vazby k případům užití.

Generalizace se v UML zakresluje nevyplněnou šipkou směřující od potomka k předkovi.

Generalizace aktorů
Generalizace aktorů (plná velikost, cca 15 kB)

Generalizace případů užití

Stejně jako zobecňujeme aktory, můžeme zobecnit i podobné případy užití. Typickými kandidáty na zobecnění jsou případy užití zaměřené na správu číselníků. Případy užití s názvy Založení uživatele, Úprava uživatele a Editace uživatele mohou být zobecněny v případu užití Správa uživatelů. Ve zobecnění mohu pokračovat a pro všechny případy užití s názvy Správa <Název číselníku> vytvořit jednoho předka – případ užití Správa systému, který bude používat aktor administrátor. Výhoda je zřejmá – diagram případů užití se nejen zpřehlední, ale také jsou v něm seskupeny související případy užití, a proto poskytne svému čtenáři více informací.

Budeme-li pokračovat analýzou HelpDesku vidíme, že můžeme například zobecnit případy užití Založení incidentu a Editace incidentu do případu užití Správa incidentu.

Generalizace případů užití
Generalizace případů užití (plná velikost, cca 5 kB)

Zajímavostí pro nováčky v návrhu aplikace může být, že abstraktní aktor používá abstraktní případ užití, ale v praxi takový vztah analytik zachycuje velmi často.

Vkládání povinných případů užití – relace <<Include>>

Více případů užití sdílí stejnou funkčnost. Jinak řečeno, při psaní textu případu užití zjistíme, že kroky scénáře se ve více případech užití opakují. Společnou část případů užití můžeme v UML vyjmout do samostatného případu užití a ostatní případy užití se na něj budou odkazovat pomocí relace <<Include>>. Relace Include je speciálním typem závislosti mezi elementy – případ užití se společnou logikou je nazýván dodavatelský případ užití a případy, jež se na něj odkazují (a zahrnují jeho funkcionalitu), jsou klientské případy užití. Musí platit, že scénář dodavatelského případu užití je zahrnován do klientského případu užití povinně a vždy. Bez dodavatelského případu užití je klientský případ užití neúplný a nelze jej realizovat.

Dodavatelský případ užití může být samostatným případem užití, který mohou aktoři používat i samostatně, nebo může obsahovat pouhý fragment chování, jež nabývá významu jen ve spojení s chováním definovaném v klientském případu užití.

Představme si, že v HelpDesku před jakoukoli operací s incidentem musí dojít k zobrazení detailu incidentu. Abychom nepsali stále dokola postup, jak uživatel otevře detail incidentu, vytvoříme samostatný případ užití Otevření detailu incidentu a ostatní případy užití vyjadřující operace nad incidentem s ním budou propojeny relací <<Include>>.

Otevření detailu incidentu
Otevření detailu incidentu (plná velikost, cca 20 kB)

Vkládání nepovinných případů užití – relace <<Extend>>

Relaci Extend použijeme pro vyjádření faktu, že případ užití může být nepovinně rozšířen o chování z jiného případu užití. Slovo nepovinně zdůrazňuji, protože narozdíl od relace <<Include>> je klientský případ užití úplný i bez dodavatelského případu užití a jazyk UML dokonce vyžaduje, aby byl jeho základní scénář zcela oproštěn od scénáře případu užití, s kterým je spojen vazbou <<Extend>>. Klientský případ užití jen deklaruje takzvané body rozšíření (Extension points), které si můžete představit jako sloty, do nichž je zasouváno chování (Vkládané segmenty – Insertion segments) dodavatelských případů užití. Počet vkládaných segmentů v dodavatelském případě musí být shodný s počtem bodů rozšíření, o něž má v klientském elementu zájem. Informaci, jaké body rozšíření dodavatelský případ užití rozšiřuje, nese samotná relace Extend. Jestliže nejsou u relace <<Extend>> žádné body rozšíření zadány, předpokládá se, že dodavatelský případ užití rozšiřuje všechny body rozšíření. Představme si, že v Helpdesku chceme VIP zákazníkům odeslat zdarma informativní SMS vždy, kdy jimi nahlášený incident byl uzavřen. U případu užití Uzavření incidentu nabídneme bod rozšíření „Zákazník je VIP“. Nový případ užití Odeslání SMS VIP zákazníkovi propojíme relací <<Extend>> s případem užití Uzavření incidentu a vytvoříme v něm vkládaný segment pro odeslání SMS.

Vkládání nepovinných případů užití
Vkládání nepovinných případů užití (plná velikost, cca 20 kB)

Doporučení

I když jsou popsané techniky při vytváření případů užití velmi efektivní a zpřehledňují diagramy, tak jejich nadměrné používání má za následek neporozumění mezi námi a zákazníkem, protože zákazník většinou bohužel není analytický guru, který ocení naše finesy a graciézní hrátky s modely. Nezapomeňte, že past dokonalého modelu je stále jen pastí, do níž se chytíte vy, až zákazník, s nímž jste se u případů užití nepochopili, teprve při pilotním provozu začne vřískat, že chtěl zcela jiný systém, než to kukaččí vejce, co se mu nyní v dobré víře, že jste si s ním vše vyjasnili v průběhu analýzy, snažíte podvrhnout. Aby tomu tak nebylo, je důležité shodnout se se zákazníkem na textových specifikacích případů užití, o nichž si povíme jindy.

Moje pravidlo druhé, sociologické: „Nikdy nevěřte zákazníkovi, který tvrdí, že vše v složitém diagramu případů užití napoprvé pochopil. Většinou jen maskuje svůj intelektuální deficit.“

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

2 Příspěvků v diskuzi

  1. K výbornému článku jen drobná jazyková poznámka – slovo „aktor“ v češtině neexistuje, jedná se o celkem škaredý anglicismus (nebo taky rusismus, mimochodem :-) ). Správně by mělo být aktér. A jinak díky.

Odpovědět