Jazyk UML Jazyk modelovací, unifikovaný (1) Programování, stejně jako mnohé další oblasti lidské činnosti, má svá "hesla dne" a kdo se jimi nezaklíná, není zkrátka "in". Módní konjunktura takového hesla ale neznamená, že se za ním nemůže skrývat užitečná věc - a právě tak je tomu s trojicí písmenek, o níž se mluví stále více: UML. Co (a na co) je UML Zkratka UML pochází z anglického Unified Modeling Language, a znamená tedy "sjednocený modelovací jazyk". Než vysvětlíme, o co jde, začneme trochu zeširoka. Každý program, každá softwarová aplikace představuje vlastně počítačový model nějakého problému. Programové vybavení zabezpečující chod elektronického obchodu musí modelovat chod tohoto obchodu; program, který řídí vstřikování do spalovacího motoru, představuje model toku paliva tímto motorem. Platí to dokonce i pro akční počítačové hry - třeba dnes už skoro zapomenutý Doom představuje model jakési základny napadené zlými příšerami. Některé modely mohou být zjednodušené, jiné musí přesně odpovídat skutečnosti - to závisí na okolnostech. K tomu, abychom mohli napsat dobrou aplikaci, musíme nejprve pochopit řešený problém. To znamená, že musíme pochopit, jak bude používán systém, ve kterém naše aplikace poběží nebo který modeluje, jaké třídy objektů se v systému vyskytují a jaké jsou jejich vzájemné vztahy, jaké instance těchto tříd jsou potřeba, jakými stavy může náš systém procházet a jak mohou tyto stavy za sebou následovat, jaké činnosti a v jakém pořadí systém vykonává a mnohé další. Ukázalo se totiž, že správně pochopit úlohu a zjistit, oč v ní jde, je možná kardinální problém programování. Je to někdy těžší, než vytvořit celou implementaci. (Přirovnáme-li tvorbu softwaru ke stavebnictví, nabízí se provokativní otázka: Je dnešní programátor spíše architekt domu, stavbyvedoucí, nebo zedník? Anebo - jak tomu také bývá - všechno dohromady?) Všimněte si, že zatím stále hovoříme o systému, nikoli o programu. V této fázi nám totiž jde o pochopení řešeného problému, tedy o vytvoření modelu - třeba na papíře nebo pomocí obrázků a textů v počítači, nikoli ještě o vlastní programování. A právě tady je "parketa" pro UML. Modelovací jazyk UML je souhrn různých diagramů, které popisují jednotlivé aspekty modelovaného systému a tak umožňují tento systém pochopit. Je jasné, že UML musí být nezávislý na programovacím jazyku, který nakonec k řešení úlohy použijeme - mlčky ovšem předpokládá, že tento jazyk bude objektově orientovaný. (Programátoři používající čistě objektové jazyky, jako třeba CLOS nebo Smalltalk, si ovšem stěžují, že jim v UML chybí delegování, závislosti, metatřídy a další věci, které tyto jazyky poskytují, a dodávají, že UML je šitý na míru hybridním jazykům typu C++.) Vytváření diagramů tužkou na papíře by ovšem bylo pracné a v praxi nepoužitelné. Na trhu se proto vyskytuje řada editorů UML, od freewarových nebo laciných sharewarových až po velice drahé profesionální nástroje. Řada z nich také umožňuje na základě těchto diagramů generovat zdrojový kód, tedy především kostry tříd a jejich metod. Pokročilejší nástroje zvládají i zpětné inženýrství - to znamená, že z hotového zdrojového textu programu dokáží vytvořit některé z diagramů UML. Trocha historie Než se pustíme do povídání o jednotlivých diagramech, které v UML používáme, podívejme se na některé historické souvislosti. Už jsme řekli, že UML předpokládá objektovou orientaci, a proto přeskočíme prehistorii a začneme ve druhé polovině šedesátých let, kdy objekty vstupují na scénu. V roce 1966 publikovali O.-J. Dahl a K. Nygaard první objektově orientovaný jazyk Simula. O rok později dali k dispozici upravenou verzi, později označovanou Simula 67. Šlo o rozšíření jazyka Algol 60, ve kterém se objevily třídy, dědičnost i polymorfismus; slůvko "objekt" se zde sice ještě nepoužívalo, ale to na věci nic nemění. Na konci 60. let byly také poprvé zveřejněny práce, které se zabývaly správností softwaru - vzpomeňme alespoň na známý Dijkstrův článek o škodlivosti skoků [1], který vyvolal řadu diskusí a dnes už patří ke "klasice" programátorské literatury. Z této doby pocházejí také jeho myšlenky o tvorbě softwaru ve vrstvách abstrakcí a požadavek maximální nezávislosti, maximálního oddělení těchto vrstev. Jde vlastně o zapouzdření, jednu z podstatných idejí objektově orientovaného programování. V téže době se také objevují první úvahy o softwarové krizi - výpočetní kapacita počítačů rapidně rostla, ale způsob tvorby programů od konce padesátých let, od příchodu Fortranu a dalších vyšších programovacích jazyků, v podstatě nijak nepokročil. Rozsah programů ovšem prudce narůstal a s tím i množství chyb v nich - a také rozsah škod, které tyto chyby způsobily. Teoretici pak formulují mj. požadavky na robustnost a znovupoužitelnost vytvořeného kódu. V sedmdesátých letech se objevily první "malé" počítače a s nimi idea grafického uživatelského rozhraní operačního systému. Vývojový tým firmy Xerox ve výzkumném středisku v Palo Alto (PARC), v němž pracovali mj. A. Kay a A. Goldbergová, se pokusil pro jeden z počítačů takovýto operační systém vyvinout; vedlejším produktem (ovšem nikoli co do významu) byl první čistě objektový programovací jazyk Smalltalk. Zde se poprvé objevuje termín "objekt"; tento jazyk také přichází s ideou programu složeného výhradně z objektů (instancí tříd), které nedělají nic jiného, než že si posílají zprávy. V průběhu osmdesátých let přicházejí na scénu osobní počítače; jejich nástup znamená prudké rozšíření softwarového trhu a urychlení vývoje, a to jak hardwaru a softwaru, tak i teorie. Objektové programování se začíná z teorie přesunovat do praxe - nikoli ovšem zásluhou Smalltalku, ale díky smíšeným jazykům, jako byl Turbo Pascal nebo C++. Tvůrci těchto jazyků se samozřejmě Simulou i Smalltalkem inspirovali, ale tím, že vytvořili jazyk, který objektové myšlení striktně nevyžadoval, poskytli praktickým programátorům čas na přechod od strukturovaného programování k přijetí nových programovacích paradigmat. Pod tlakem nabídky objektových knihoven - např. pro tvorbu grafického uživatelského rozhraní programů, jako jsou MFC nebo OWL - zároveň praktičtí programátoři pochopili, že před objekty "není úniku", a že by se s nimi tedy přece jen měli začít seznamovat. Koncem osmdesátých a začátkem devadesátých let se mnohým zdálo, že právě objektově orientované programování představuje řešení softwarové krize. Praxe ovšem ukazuje, že samotné objekty nestačí, že i objektově vytvořené programy mohou být špatné. Ze zkušenosti víme, že špatně navržený objektový program může být hůře udržovatelný a upravovatelný než špatně navržený program strukturovaný. (Špatně navržený objektový program je například takový, ve kterém je nepořádek v kódu, funkce jsou nelogicky rozesety po různých objektech, obsahuje nemnemotechnická či přímo nesmyslná pojmenování, najdeme v něm nelogické závislosti částí programu mezi sebou. Mezi typické chyby také patří nesprávné aplikování vazeb - např. chybné použití dědění v případech, kdy se naprosto nehodí). Ukázala se tedy potřeba vytvořit nástroje pro objektovou analýzu a návrh programů - podobně jako se od sedmdesátých let s úspěchem využívaly metody pro strukturovanou analýzu a návrh. (Připomeňme si např. Jacksonovy diagramy a nástroje CASE na nich založené - mnohé z nich se používají dodnes.) Na přelomu osmdesátých a devadesátých let se skutečně řada navzájem si konkurujících metod pro objektově orientovanou analýzu a návrh objevila a s nimi také první nástroje CASE, které je využívaly. Zmíníme se alespoň krátce o některých z nich. Z prostředí Smalltalku a firmy Xerox pocházejí karty CRC (Class-Responsibility-Collaboration). Jsou to papírové lístky, na nichž jsou popisy tříd, příp. instancí, a zprávy, které mohou odeslat; jejich pomocí se vytvoří model systému a testuje se jeho správnost. Návrhy metod pro objektovou analýzu a návrh vytvořili P. Coad, E. Yourdon, J. Odell a další. Jednu z úspěšných metod vypracoval G. Booch při vývoji systémů v jazyce Ada ve své firmě Rational Software; publikoval ji v na počátku 90. let v knize [2]. J. Rumbaugh vedl vývojový tým ve výzkumných laboratořích firmy General Electric. Výsledkem jeho práce byla Objektová modelovací metoda (Object Modeling Technique, OMT), publikovaná poprvé v r. 1991 [3]. I. Jacobson, autor metody Objectory, vycházel ze zkušeností, které získal u společnosti Ericsson při modelování telefonních zařízení. Jako první zavedl pojem "případ užití" (use case) [4]. Vývoj pokračoval a v polovině devadesátých let už existovala nepřehledná řada metod pro objektovou analýzu a návrh a také řada navzájem se potírajících metodiků. Konsorcium OMG proto přišlo se snahou o standardizaci, jak se zdálo, dosti beznadějnou - řadě lidí byla protivná i jen samotná idea standardizace. (Jeden vtip z té doby, tedy ještě před 11. zářím 2001: Jaký je rozdíl mezi teroristou a - nejen objektovým - metodikem? S teroristou se někdy dá vyjednávat.) V roce 1994 ale J. Rumbaugh opustil GE a připojil se k G. Boochovi a jeho firmě Rational Software. O rok později prohlásili, že "válka o metody skončila, my jsme vyhráli"; zřejmě se tak chtěli pokusit o prosazení standardizace po způsobu některých velkých firem. Řada metodiků pochopitelně ihned začala formovat antiboochovskou koalici... V roce 1995 pak G. Booch a J. Rumbaugh publikovali "unifikovanou metodu" (Unified Method) verze 0.8. V té době se k nim připojil i I. Jacobson. O rok později se skupina OMG začala znovu snažit o dosažení standardizace na poli metodik objektové analýzy a návrhu a na její výzvu předložila řada firem svá řešení - Rational Software přispěla přepracovanou verzí své unifikované metody pod označením UML 1.0. Jako oficiální standard pak pracovní skupina OMG přijala verzi 1.1, která vznikla sloučením UML 1.0 s některými dalšími návrhy. Následovalo ještě několik dalších revizí, až se v roce 1999 objevila verze 1.3. Vývoj UML všem zdaleka není uzavřen. Jako perličku uveďme, že pro G. Boocha, J. Rumbaugha a I. Jacobsona se postupně ujala anglicko-španělská přezdívka The Three Amigos, což je narážka na jakýsi film (v Latinské Americe se prý používá podobně dvojjazyčný překlad Los Tres Buddies). U nás se v poslední době objevil poněkud posměšný název svatá trojice, nejspíš jako reakce na skutečnost, že knihy o UML, ke kterým napíše někdo z nich předmluvu a na jejichž obálce je logo obsahující jejich jména, se prodávají nejen podstatně lépe, ale i podstatně dráž... Vraťme se ale k UML. I když jsme v předchozím textu hovořili především o metodikách, samotný jazyk UML žádnou metodiku neobsahuje. UML je nástroj pro zápis výsledků analýzy a návrhu - tedy jazykově nezávislého modelu - a metodiku, podle níž budeme analýzu a návrh provádět, si musíme zvolit. Firma Rational Software navrhla v rámci UML tzv. "racionální unifikovaný proces" (Rational Unified Process, RUP; překlad "unifikovaný proces firmy Rational" by však možná byl výstižnější). Vedle toho ovšem existuje i řada dalších metod, které vznikly na mnoha pracovištích po celém světě a typicky odrážejí specifika problémů, se kterými se tamní vývojáři setkávají. My zde ovšem nechceme hovořit o metodikách, ale především o vlastním UML. Diagramy v UML Už jsme si řekli, že model v UML se skládá z řady diagramů, které popisují nejrůznější aspekty řešeného problému. Podívejme se tedy alespoň v krátkosti na některé z nich. Případy užití Diagram případů užití pomáhá pochopit, jak bude daný systém používán, k čemu slouží. Můžeme se na něj dívat jako na grafické vyjádření všech možných scénářů nebo způsobů použití systému uživateli. Aktér a případ užití Diagram případů užití obsahuje dvě základní ikony: Případ užití (use case, setkáme se také s překladem "užitná činnost") a aktér (též "účastník", "participant", anglicky actor; údajně jde o špatný překlad ze švédštiny, původně se tato entita měla jmenovat role). Případ užití se znázorňuje oválem, v němž je zapsána činnost, kterou systém - na podnět aktéra - provede, nebo činnost, jejíž výsledek aktér obdrží a případně nějak využije. Aktér se znázorňuje schematickou figurkou člověka, k níž bývá připojen stručný popis jeho role. Obrázek 1 obsahuje dva aktéry a jeden případ užití. Poznamenejme, že některé editory UML zapisují činnost případu užití pod ikonu, nikoli do ní. Aktér a systém Důležité je, že aktérem může být kdokoli nebo cokoli, co interaguje s modelovaným systémem - může to být např. další program, z hlediska našeho systému chápaný jako externí, může to být datový zdroj atd. Nemusí to tedy být jen člověk. Přitom si musíme uvědomit, že aktér není součástí modelovaného systému. Nalezení všech aktérů však může posloužit k přesnému vymezení hranic systému - tato hranice se do diagramu případů užití občas také zakresluje jako čára oddělující všechny případy užití od aktérů. Vztah mezi aktérem a případem užití se znázorňuje čarou, která je spojuje. Zpravidla se vlevo od případu užití zakresluje aktér, který případ užití vyvolá, a vpravo aktér, který přijme výsledná data. (To nemusí být týž aktér: Jeden člověk může dát příkaz, aby banka vyplatila z jeho účtu peníze někomu jinému. Plátce je zde jeden aktér, příjemce peněz je jiný aktér, jak ukazuje obr. 1.) Typický diagram případů užití ovšem na rozdíl od našeho obrázku obsahuje desítky aktérů a desítky nebo stovky případů užití. Diagram případů užití může také vyjadřovat vztahy mezi různými případy užití. Jestliže se určitá činnost opakuje jako součást několika případů užití, lze ji vyjádřit samostatnou ikonou a pak na ni v dalších případech užití odkázat; hovoříme o vztahu zahrnování (anglicky include). Kdybychom zůstali u příkladu bankovního systému a pokračovali v analýze, zjistili bychom, že vyplacení peněz je jen jedna z mnoha činností, které tento systém umí. Další bude např. připsání úroků, převod peněz atd. Všechny tyto operace ale budou zahrnovat např. kontrolu stavu účtu. Tento vztah v diagramu případů užití vyjadřujeme čárkovanou šipkou směřující k oválu zahrnovaného případu užití, k níž připíšeme slovo "include" nebo "zahrnuje" v těchto podivných uvozovkách. (Takovýmto popisům připojeným ke spojnicím se v UML říká stereotyp a slouží k upřesnění druhu vazby nebo typu prvku v diagramu.) Příklad ukazuje obrázek 2. Může se také stát, že jeden případ užití představuje rozšíření působnosti případu jiného; hovoříme o vztahu rozšiřování (anglicky extend). V diagramech případů užití ho znázorňujeme podobně jako vztah zahrnování, pouze do stereotypu zapíšeme slovo "extend" nebo "rozšiřuje"; šipka směřuje od rozšiřujícího k "původnímu" případu užití. Přitom obvykle specifikujeme i tzv. body rozšíření, v nichž jsou k původnímu případu užití přidány další činnosti. Dalším vztahem, který lze mezi případy užití najít, je generalizace (zobecnění), resp. - podíváme-li se na to z druhé strany - specializace (zvláštní případ). Je to vztah velice podobný dědičnosti mezi třídami a znázorňuje se plnou šipkou směřující k obecnějšímu případu užití. Zůstaneme-li u bankovního systému, zjistíme, že jak připsání úroků, tak převod peněz bankovním příkazem mají mnohé společné rysy. Popíšeme je tedy jako obecnou činnost "převod peněz" a připsání úroků, stejně jako převod příkazem z účtu na účet specifikujeme jako specializace této obecné činnosti. Komentář Obrázek 1 také ukazuje, jak se v UML - nejen v diagramech případů užití - zapisují komentáře: Text komentáře je uzavřen v ikoně připomínající list papíru s ohnutým rohem. K součásti, jíž se komentář týká, je připojena čárkovanou čarou. Diagramy tříd a diagramy objektů Diagramy tříd jsou nejznámější a nejspíš i nejpoužívanější z diagramů jazyka UML. Vyjadřují třídy, které se v systému vyskytují, a vztahy mezi nimi - dědičnost, asociaci, agregaci atd. Diagramy objektů jsou podobné, zachycují však objekty - tedy jednotlivé instance tříd. Ikona třídy a objektu Třídu v UML znázorňujeme obdélníkem, který v má záhlaví zapsáno jméno třídy. Pod ním, odděleny vodorovnou čarou, jsou jména atributů - datových složek - této třídy. Pod atributy, opět pod vodorovnou čarou, jsou jména metod - tedy operací, které mohou být s instancemi prováděny. U atributů můžeme vyznačit i jejich datový typ: za jméno atributu připíšeme dvojtečku a za ni označení typu. U všech složek, tj. u atributů i u metod, můžeme také vyznačit přístupová práva. Veřejně přístupné (public) složky označíme symbolem +, chráněné (protected) znakem # a soukromé (private) znakem -. Toto označení se zapisuje před jméno složky. Pokud nepotřebujeme složky třídy vyznačovat, používáme zjednodušenou ikonu, která obsahuje pouze jméno třídy. Často také potřebujeme znázornit objekty, tj. instance našich tříd. Ikona objektu je podobná ikoně třídy, pouze v záhlaví obsahuje jméno objektu spolu se jménem třídy a u atributů můžeme připojit i jejich hodnoty. Obrázek 3 ukazuje úplnou a zjednodušenou ikonu třídy Bod, která reprezentuje bod ve dvourozměrném prostoru, a ikonu instance této třídy. Příště Zatím jsme se seznámili s diagramem případů užití a začali jsme si povídat o diagramu tříd a diagramu objektů. Příště povídání o diagramu tříd dokončíme a podíváme se na některé další diagramy. Vojtěch Merunka, Miroslav Virius Odkazy [1] Edsger W. Dijkstra: Go To Statement Considered Harmful. Communications of the ACM 11 (1968), č. 3, str. 147. [2] Grady Booch: Object-Oriented Analysis and Design with Applications. 2nd edition. Addison-Wesley, 1994. [3] James Rumbaugh a další: Object-Oriented Modeling and Design. Prentice Hall, 1991. [4] Ivar Jacobson a další: Object-Oriented Software Engineering: A Use Case Driven Approach. Addison-Wesley 1992. [5] Grady Booch, James Rumbaugh, Ivar Jacobson: The Unified Modeling Language User Guide. Addison-Wesley, 1999. [6] Martin Fowler: UML Distilled. 2nd Edition. Addison-Wesley, 2000. [7] Joseph Schmuller: Myslíme v jazyku UML. Grada Publishing, Praha 2001. [8] Meilir Page-Jones: Základy objektově orientovaného návrhu v UML. Grada Publishing, Praha 2001.