Hlavní navigace

Nástroje pro tvorbu UML diagramů z příkazové řádky

29. 1. 2015
Doba čtení: 12 minut

Sdílet

V předchozím článku o nástrojích pro tvorbu grafů a diagramů z příkazové řádky byla popsána utilita gnuplot, sada nástrojů Graphviz a taktéž utilita Ditaa. Žádný z těchto nástrojů však neuměl vytvářet UML diagramy a z tohoto důvodu se dnes zaměříme na program nazvaný PlantUML, který tuto funkcionalitu nabízí.

Obsah

1. Nástroje pro tvorbu UML diagramů z příkazové řádky

2. PlantUML

3. Diagram aktivit

4. Změna stylu diagramu aktivit

5. Větvení v diagramu aktivit

6. Diagram tříd

7. Metody a atributy v diagramu tříd

8. Rozhraní v diagramu tříd

9. Odkazy na Internetu

1. Nástroje pro tvorbu UML diagramů z příkazové řádky

Jazyk označovaný zkratkou UML neboli Unified Modeling Language je, jak již jeho název napovídá, unifikovaný modelovací jazyk, který má, na rozdíl od převážně textově orientovaných programovacích jazyků, vlastní grafickou syntaxi (tj. pravidla určující způsob sestavování jednotlivých elementů jazyka do větších objektů) a taktéž sémantiku (tj. jednoznačná pravidla určující jednotlivým syntaktickým výrazům jejich význam). UML se dnes používá jak v průběhu návrhu architektury rozsáhlých informačních systémů, tak i na nižší úrovni: pro popis statického popř. i dynamického chování jednotlivých modulů, z nichž se informační systém skládá (jak uvidíme dále, lze například diagram aktivit použít i namísto vývojového diagramu). Některé společnosti mají celý návrh IS postavený právě na UML, ovšem většinou se dává přednost pragmatičtějšímu přístupu a využívají se jen některé UML diagramy, které bývají doplněny například pseudokódem (navíc se ukazuje, že pro neobjektové prvky informačních systémů, například pro návrh relačních databází, nemusí být UML tím nejlepším řešením, což do značné míry souvisí se způsobem vývoje UML).

Některými nástroji určenými pro tvorbu UML diagramů jsme se již zabývali téměř před deseti lety :-) v článku, který naleznete na adrese http://www.root.cz/clanky/nastroje-pro-tvorbu-uml-diagramu/. Většina zmíněných nástrojů kupodivu stále existuje (samozřejmě v modernizované podobě), i když v některých případech došlo ke změně jejich jména. Dnes se ovšem budeme zabývat utilitou, která od uživatele nevyžaduje ani ruční kreslení diagramů s využitím grafického uživatelského rozhraní a dokonce ani nezpracovává zdrojové kódy a netvoří z nich diagram tříd. Tento relativně jednoduše použitelný nástroj se jmenuje PlantUML.

2. PlantUML

Nástroj PlantUML (http://plantuml.sourceforge.net/) dokáže na základě textového popisu UML diagramu vytvořit bitmapový obrázek s tímto diagramem, přičemž uživatel může do jisté míry ovlivnit způsob jeho vykreslení, přidat popis hran apod. V současné verzi PlantUML jsou podporovány následující typy UML diagramů: diagram aktivit, stavový diagram, diagram tříd, diagram objektů, diagram komponent, diagram užití a sekvenční diagram. Ve skutečnosti sice UML popisuje i další typy diagramů, ovšem PlantUML s velkou pravděpodobností dokáže pokrýt většinu potřeb analytiků i programátorů, protože v nabídce podporovaných diagramů jsou zastoupeny všechny tři kategorie: popis struktury informačního systému, popis chování informačního systému a popis interakce či komunikace. PlantUML je naprogramovaný v Javě, ovšem podobně jako tomu bylo v případě minule popsaného nástroje Ditaa se jedná o relativně malý program, který pro svůj běh nevyžaduje enormní množství zdrojů (diskový prostor, RAM atd.). Pro uživatele PlantUML je na adrese http://sourceforge.net/pro­jects/plantuml/files/plan­tuml.jar/download k dispozici spustitelný Java archiv, dále je vhodné si stáhnout referenční příručku k jazyku z adresy http://plantuml.sourcefor­ge.net/PlantUML_Language_Re­ference_Guide.pdf.

3. Diagram aktivit

V diskuzi vedené pod předchozím článkem se mj. řešila i problematika (automatizovaného) vykreslování vývojových diagramů (flow chart). Klasické vývojové diagramy sice nejsou v UML přímo podporovány, ale existuje zde velmi podobný typ diagramu nazvaný diagram aktivit. Tímto diagramem je možné nahradit vývojové diagramy s větvením i programovými smyčkami. Diagram aktivit lze v PlantUML vytvořit velmi jednoduchým způsobem, což si ostatně ukážeme na několika demonstračních příkladech.

První příklad obsahuje definici diagramu aktivit, který obsahuje jen jedinou akci, tj. uzel představující většinou dále nedělený krok, který se v systému provádí. Diagram obsahuje symbol inicializace (černá tečka), koncový bod (kružnice s černou tečkou uprostřed) a uzel s prováděným krokem. Mezi symbolem inicializace a uzlem je nakreslena šipka, podobná šipka je pak nakreslena mezi uzlem a koncovým bodem. V PlantUML je tento diagram představován následujícím kódem (textovým souborem). Povšimněte si použití symbolů (*) jak pro symbol inicializace, tak i pro koncový bod:

@startuml
(*) --> "Aktivita"
"Aktivita" --> (*)
@enduml

Deklarace začíná řádkem @startuml a končí řádkem @enduml. Zajímavé je, že není nutné uvádět typ diagramu – ten je odvozen z kontextu.

Spuštění se provede následovně:

java -jar plantuml.jar ActivityDiagram1.txt

Obrázek 1: Diagram aktivit vygenerovaný ze zdrojového kódu prvního příkladu. Ve výchozím nastavení jsou uzly umístěné pod sebe a šipky mezi nimi směřují vertikálně dolů (v případě, že není použito rozvětvení, kterým se budeme zabývat níže).

Podívejme se nyní na nepatrně složitější diagram aktivit, který obsahuje dva sekvenčně prováděné kroky. Tento diagram je možné vytvořit explicitním uvedením všech vazeb (šipek) mezi oběma uzly, symbolem inicializace i koncovým bodem. Takto deklarovaný diagram může být výsledkem práce nějakého skriptu apod.:

@startuml
(*) --> "Aktivita1"
"Aktivita1" --> "Aktivita2"
"Aktivita2" --> (*)
@enduml

Obrázek 2: Diagram aktivit vygenerovaný ze zdrojového kódu druhého příkladu.

Ve skutečnosti je ale možné popis diagramu zjednodušit způsobem naznačeným pod tímto odstavcem. Povšimněte si, že každý uzel je zde zmíněn pouze jedenkrát, protože vazba mezi uzlem „Aktivita1“ a „Aktivita2“ je naznačena samostatnou šipkou:

@startuml
(*) --> "Aktivita1"
--> "Aktivita2"
--> (*)
@enduml

Obrázek 3: Diagram aktivit vygenerovaný ze zdrojového kódu třetího příkladu. Tento obrázek je totožný s druhým obrázkem, ovšem deklarace diagramu aktivit je jednodušší.

4. Změna stylu diagramu aktivit

Jak již bylo řečeno v úvodní kapitole, je možné při tvorbě diagramů s využitím nástroje PlantUML ovlivnit způsob vykreslení diagramu. V mnoha případech se nevyhneme přidání popisu k jednotlivým šipkám diagramu aktivit, což lze zajistit zápisem poznámky do hranatých závorek:

@startuml
(*) --> [začátek procesu] "Aktivita1"
--> [zpracování požadavku] "Aktivita2"
--> [konec procesu] (*)
@enduml

Obrázek 4: Diagram aktivit vygenerovaný ze zdrojového kódu čtvrtého příkladu. Uzly jsou v tomto diagramu umístěny pod sebe.

Taktéž je možné změnit uspořádání uzlů (a tím pádem i směr šipek). Namísto symbolu → představujícího šipku je možné alternativně použít:

  1. -down → odpovídá běžné šipce směřující (šikmo) dolů
  2. -right → šipka orientovaná doprava
  3. → stejný význam jako má předchozí symbol
  4. -left → šipka orientovaná doleva
  5. -up → šipka orientovaná nahoru

Zkusme si nyní předchozí diagram změnit takovým způsobem, aby byly všechny uzly umístěné v jedné horizontální rovině. Úprava je ve skutečnosti velmi jednoduchá:

@startuml
(*) -right-> [začátek procesu] "Aktivita1"
-right-> [zpracování požadavku] "Aktivita2"
-right-> [konec procesu] (*)
@enduml

Obrázek 5: Diagram aktivit vygenerovaný ze zdrojového kódu pátého příkladu. Nyní jsou všechny uzly zobrazeny v jedné horizontální rovině.

5. Větvení v diagramu aktivit

Velmi důležitou součástí naprosté většiny diagramů aktivit je rozvětvení. To je reprezentováno malým kosočtvercem, takže se tento prvek diagramu podobá rozvětvení používaného v klasickém vývojovém diagramu, ovšem s tím rozdílem, že se podmínka pro rozvětvení může (ale nemusí) psát do předchozího kroku (zde si dovolím sémantiku diagramu aktivit nepatrně pozměnit, protože samotné rozvětvení není v diagramu aktivit chápáno jako samostatný krok). Pojďme si nyní ukázat, jak by se postupovalo při vytváření diagramu analogickému známému vtípku o univerzálním návodu na opravu všeho: http://joyreactor.com/post/287235. Zde se již setkáme s potřebou větvení, které se do diagramu aktivit zapisuje – což mnoho programátorů patrně potěší – pomocí slov if, then, elseendif. Jednoduché rozvětvení může být zapsáno následovně:

@startuml
(*) --> "Does it move?"
if "" then
--> [yes] "WD-40"
else
--> [no] "Duct Tape"
endif
"WD-40" --> (*)
"Duct Tape" --> (*)
@enduml

Obrázek 6: Jednoduché rozvětvení reprezentované v diagramu aktivit.

Rozvětvení deklarované v předchozím diagramu se sice vykreslilo korektně (= tak, jak jsme předpokládali), ovšem následující část již způsobí problémy, neboť PlantUML bude považovat oba uzly nadepsané „Should it?“ za uzel jediný. Ostatně můžeme si to sami vyzkoušet:

@startuml
(*) --> "Does it move?"
if "" then
--> [yes] "Should it?"
else
--> [no] "Should it?"
endif
@enduml

Obrázek 7: Namísto dvou uzlů máme uzel jediný.

Řešení tohoto problému je poměrně jednoduché. PlantUML totiž umožňuje pojmenovat jednotlivé uzly (kroky), přičemž zadaná jména se mohou odlišovat od textů zobrazených v uzlu. V našem případě tedy můžeme první uzel pojmenovat s1 a druhý s2, což je patrné z následujícího upraveného demonstračního příkladu:

@startuml
(*) --> "Does it move?"
if "" then
--> [yes] "Should it?" as s1
else
--> [no] "Should it?" as s2
endif
@enduml

Obrázek 8: Dva rozdílné uzly se stejným textem.

Jednotlivé větve se samozřejmě mohou (a musí) dále rozvětvovat. V deklaraci diagramu se to zařídí jednoduše – vnořenými strukturami if-then-else-endif. Zkusme nyní upravit náš demonstrační příklad takovým způsobem, aby se použilo další rozvětvení v obou dalších větvích:

@startuml
(*) --> "Does it move?"
 
if "" then
--> [yes] "Should it?" as s1
if "" then
--> [yes] "No problem" as np1
else
--> [no] "Use duct tape"
endif
 
else
--> [no] "Should it?" as s2
if "" then
--> [yes] "Use WD-40"
else
--> [no] "No problem" as np2
endif
 
endif
 
@enduml

Obrázek 9: Návod jak opravit vše, alfa verze.

Zbývá nám doplnit koncový bod, což je již snadné:

@startuml
(*) --> "Does it move?"
 
if "" then
--> [yes] "Should it?" as s1
if "" then
--> [yes] "No problem" as np1
np1 --> (*)
else
--> [no] "Use duct tape" as tape
tape --> (*)
endif
 
else
--> [no] "Should it?" as s2
if "" then
--> [yes] "Use WD-40" as wd40
wd40 --> (*)
else
--> [no] "No problem" as np2
np2 --> (*)
endif
 
endif
 
@enduml

Obrázek 10: Návod jak opravit vše, beta verze.

Pro lepší názornost je možné jednotlivé podvětve zvýraznit odsazením, které je samozřejmě taktéž podporováno:

@startuml
(*) --> "Does it move?"
 
if "" then
 
    --> [yes] "Should it?" as s1
    if "" then
        --> [yes] "No problem" as np1
        np1 --> (*)
    else
        --> [no] "Use duct tape" as tape
        tape --> (*)
    endif
 
else
 
    --> [no] "Should it?" as s2
    if "" then
        --> [yes] "Use WD-40" as wd40
        wd40 --> (*)
    else
        --> [no] "No problem" as np2
        np2 --> (*)
    endif
 
endif
 
@enduml

Obrázek 11: Návod jak opravit vše, finální verze.

Na závěr si ještě ukažme, jak se k jednotlivým uzlům mohou přiřadit poznámky (notes). Povšimněte si, že u uzlů je možné specifikovat, zda se poznámka zobrazí nalevo či napravo a taktéž to, že je možné zapisovat poznámku na větší množství řádků:

@startuml
(*) --> "Some Activity"
note right: This activity has to be defined
"Some Activity" --> (*)
note left
This note is on
several lines
end note
@endum

Obrázek 12: Poznámky přiřazené k uzlům.

6. Diagram tříd

Druhým velmi často používaným diagramem definovaným ve standardu UML je diagram tříd (class diagram). V tomto typu diagramu je možné zobrazit jednoduché i složitější vztahy mezi třídami, například fakt, že třída Boolean je potomkem třídy Object (příklad je převzatý z Javy):

@startuml
Object <|-- Boolean
@enduml

Obrázek 13: Vztah mezi třídami Object a Boolean zobrazený v diagramu tříd.

Můžeme samozřejmě zobrazit i vazby mezi větším počtem tříd. Povšimněte si, že nikde není zapotřebí specifikovat, že se má zobrazit diagram tříd a ne diagram aktivit: toto rozhodnutí provede PlantUML automaticky:

@startuml
Object <|-- Boolean
Object <|-- String
Object <|-- Number
Number <|-- Integer
Number <|-- Double
@enduml

Obrázek 14: Vztahy mezi větším počtem tříd.

7. Metody a atributy v diagramu tříd

U jednotlivých tříd je možné deklarovat jejich atributy a taktéž metody. Příklad popsaný v předchozí kapitole je možné relativně jednoduchým způsobem vylepšit o atributy a metody. Je to velmi snadné – postačuje napsat jméno třídy a za dvojtečkou pak jméno atributu či jméno metody (i se závorkami, samozřejmě i s názvy parametrů, pokud je to nutné):

@startuml
Object <|-- Boolean
Object: equals()
Object: hashCode()
Object: clone()
Object <|-- String
Object <|-- Number
Boolean: FALSE
Boolean: TRUE
Number: byteValue()
Number <|-- Integer
Number <|-- Double
String: indexOf()
String: isEmpty()
String: length()
String: split()
Integer: MAX_VALUE
Integer: MIN_VALUE
Double: MAX_VALUE
Double: MIN_VALUE
Double: POSITIVE_INFINITY
Double: NEGATIVE_INFINITY
Double: NaN
@enduml

Obrázek 15: Atributy a metody několika tříd v hierarchii.

Pokud je nutné zvýraznit i přístupová práva k atributům, je vhodnější použít alternativní způsob zápisu metadat o třídě. Ten se podobá zápisu deklarace třídy v C++ či Javě, přičemž znaky se speciálním významem před názvem atributu určují viditelnost i přístupová práva:

@startuml
class TestClass {
-privateField
#protectedField
~packageProtectedField
+publicField
}
@enduml

Obrázek 16: Třída s atributy, které mají různá přístupová práva.

Pro úplnost doplňme třídu i o metody s různými přístupovými právy:

@startuml
class TestClass {
-privateField
#protectedField
~packageProtectedField
+publicField
-privateMethod()
#protectedMethod()
~packageProtectedMethod()
+publicMethod()
}
@enduml

Obrázek 17: Třída s atributy a metodami, které mají různá přístupová práva. Povšimněte si oddělení atributů od metod, to je provedeno automaticky.

8. Rozhraní v diagramu tříd

Poslední důležitou vlastností nástroje PlantUML při práci s diagramem tříd je vytvoření uzlů představujících rozhraní. Prvním krokem je změna stylu šipek – namísto plných úseček se použijí čárkované úsečky, a to použitím jiného symbolu pro šipky v deklaraci diagramu:

@startuml
"Iterable<E>" <|.. "Collection<E>"
"Collection<E>" <|.. "List<E>"
"Collection<E>" <|.. "Queue<E>"
"Collection<E>" <|.. "Set<E>"
"Set<E>" <|.. "SortedSet<E>"
@enduml

Obrázek 18: Třídy nebo rozhraní?

Ve skutečnosti je však předchozí diagram nekorektní, protože Iterable atd. jsou skutečná rozhraní a měla by být označena písmenem I (interface) a nikoli C (class). To lze velmi snadno napravit použitím slova interface:

@startuml
interface "Iterable<E>" <|.. interface "Collection<E>"
"Collection<E>" <|.. interface "List<E>"
"Collection<E>" <|.. interface "Queue<E>"
"Collection<E>" <|.. interface "Set<E>"
"Set<E>" <|.. interface "SortedSet<E>"
@enduml

Obrázek 19: Nyní jsou rozhraní skutečná rozhraní.

UX DAy - tip 2

Pro úplnost si ještě ukažme poněkud složitější příklad s větším množstvím rozhraní a současně i tříd. Povšimněte si, že jedna třída může implementovat větší množství rozhraní:

@startuml
interface "Iterable<E>" <|.. interface "Collection<E>"
"Collection<E>" <|.. interface "List<E>"
"Collection<E>" <|.. interface "Queue<E>"
"Collection<E>" <|.. interface "Set<E>"
"Set<E>" <|.. interface "SortedSet<E>"
"List<E>" <|.. ArrayList
"List<E>" <|.. LinkedList
"Set<E>" <|.. HashSet
"Set<E>" <|.. TreeSet
"SortedSet<E>" <|.. TreeSet
"Queue<E>" <|.. LinkedList
@enduml

Obrázek 20: Diagram rozhraní a tříd.

9. Odkazy na Internetu

  1. Nástroje pro tvorbu UML diagramů (nikoli z příkazové řádky):
    http://www.root.cz/clanky/nastroje-pro-tvorbu-uml-diagramu/
  2. PlantUML (home page)
    http://plantuml.sourceforge.net/
  3. PlantUML (download page)
    http://sourceforge.net/pro­jects/plantuml/files/plan­tuml.jar/download
  4. PlantUML (Language Reference Guide)
    http://plantuml.sourcefor­ge.net/PlantUML_Language_Re­ference_Guide.pdf
  5. Plain-text diagrams take shape in Asciidoctor!
    http://asciidoctor.org/new­s/2014/02/18/plain-text-diagrams-in-asciidoctor/
  6. Graphviz – Graph Visualization Software
    http://www.graphviz.org/
  7. graphviz (Manual Page)
    http://www.root.cz/man/7/graphviz/
  8. dot (Manual page)
    http://www.root.cz/man/1/dot/
  9. Ditaa home page
    http://ditaa.sourceforge.net/
  10. Ditaa introduction
    http://ditaa.sourceforge.net/#intro
  11. Ditaa usage
    http://ditaa.sourceforge.net/#u­sageNode, Edge and Graph Attributes
    http://www.graphviz.org/doc/in­fo/attrs.html
     
  12. Graphviz (Wikipedia)
    http://en.wikipedia.org/wiki/Graphviz

Byl pro vás článek přínosný?

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.