Itt jársz most: Kezdőlap > Alkalmazásfejlesztés > Szekvencia-diagramok készítése PlantUML nyelven

Szűrő megjelenítése

Szekvencia-diagramok készítése PlantUML nyelven

Kezdjük az elején: mi az UML?

Az UML, azaz Unified Modelling Language - mint azt a neve is mutatja - egy vizuális modellező nyelv, illetve annak specifikációja, melyet eredetileg a Rational Software fejlesztett, majd az Object Management Group (igen, OMG :) ) adoptált és fejleszti azt mind a mai napig. Számtalan önálló és integrált modellező eszköz létezik, mely támogatja az UML nyelvet, ezek természetesen legfeljebb designjukban generálnak eltérő eredményt, az építőelemek a specifikációból származnak. Sok ilyen eszköz egyébként képes a modellből konkrét implementációt is generálni, ami segíthet azon gondolatok elhessegetésében, hogy az UML modellezés csupán időpazarlás. Standardizált specifikáció lévén minden elem minden olvasó számára ugyanazt fogja jelenteni, így a szoftverfejlesztésben egy nagyon jelentős eszközről beszélünk, hiszen segítségével megtervezhetőek rendszerünk komponensei, folyamatai, külső és belső interakciói, még mielőtt azok implementálásra kerülnének.

És ezzel el is jutottunk oda, hogy mire használjuk (kellene használni) az UML diagramokat. Tekintve, hogy nem csak egy féle UML diagram típus létezik, több válasz is van erre a kérdésre:

  • Adatbázis táblák megtervezésére, a közöttük levő kapcsolatokkal, számossággal együtt;
  • Osztály definíciók megtervezésére;
  • Interface-ek specifikációjának elkészítésére;
  • Komponensek megtervezésére (nagyjából akár bármilyen tág értelemben értelmezhetjük itt a komponens fogalmát, komponens lehet egy osztály, egy library, egy egész alkalmazás, és így tovább);
  • Folyamatok (szekvenciák) és állapotátmenetek megtervezésére;
  • Alacsony szintű viselkedési folyamatok (értsd, ciklusok, feltételes elágaztatások és az őket összekötő lépések) megtervezésére;
  • "Use case"-ek modellezésére;

És még számos másra, azonban ami közös bennük, az az, hogy minden esetben vizuális modellezésről beszélünk - természetesen címkéket, feliratokat is fogunk használni, de sok esetben azok is standardizálva vannak, és alapvetően diagramunk minden komponense egy-egy kis doboz, ellipszis, rombusz, nyilak, szimbólumok, stb lesz. Nyilván a teljes specifikáció megismerése hosszú folyamat, minden eszközének megtanulása nem könnyű (viszont mindenképpen hasznos, már-már elengedhetetlen tudás), így ebben a cikkben nem is szeretném mindet kitárgyalni. Ehelyett alább az egyik személyes "kedvencemről" lesz szó, a szekvencia diagramokról, azon belül is a PlantUML nevű nyelvet fogjuk használni UML-kompatibilis szekvencia-diagramok létrehozására.

Szekvenciadiagramok

Akkor nézzük is meg gyorsan, mik azok a szekvenciadiagramok. Segítségükkel folyamatokat definiálhatunk, alacsony (pl. egy metódus implementációja által végrehajtott lépések) és magas (pl. alkalmazások egymás közötti kommunikációja) szintűeket egyaránt vizualizálhatunk - a határ csak a képzelőerőnk és hogy persze mire szeretnénk felhasználni egy folyamat vizuális reprezentációját. Személyes tapasztalat, hogy sok esetben arra is nagyon jó szolgálatot tesz, hogy hatékonyan mutathassuk meg másoknak - például csapatunk új fejlesztőinek - hogy egy-egy komplex folyamata a már régóta fejlesztett rendszerünknek hogyan működik, milyen külső komponensekkel lép kapcsolatba és hogyan, honnan és milyen jellegű bemenetet, triggert vár, és az eredmény hova fog kerülni. Persze ez csak néhány példa a lehetőségek széles tárházából.

A szekvenciadiagramok elemei, résztvevői tehát a modellezett rendszer komponensei. Ezek absztrakciós szinttől függően lehetnek osztályok, library-k, önálló elemek (alkalmazások, szolgáltatások, adatbázismotorok, felhő infrastruktúra integrált szolgáltatásai), lényegében bármi ami az adott vizualizálandó folyamatban részt vesz. A komponensek között irányított interakciós útvonalakat definiálunk, melyek megmutatják, melyik komponens mikor és hogyan hív más komponenseket. Az irányítottság itt nagyon fontos szempont, hiszen anélkül nem volna egyértelmű melyik fél hívja melyiket. Ugyanígy vizualizálhatjuk a visszatérési útvonalakat, így ha például egy felhasználói interakcióval induló folyamatot vizualizálunk, láthatjuk milyen lépések megtétele után kerül vissza az "irányítás" a felhasználóhoz. A lényeg hogy a szekvenciadiagram a végén nagyjából egy vízesésre fog hasonlítani, mely komplexitásától függően lehet akár egy klasszikus csak előrefelé "lépkedő" vízesés, vagy akár kanyaroghat is összevissza. Az utolsó lépésben viszont általában visszatér az interakciót indító résztvevőhöz, bár ez egyáltalán nem szükségszerű. Az elkészült szekvenciadiagram kielemzése abban is segítségünkre lehet, hogy időben felfedezzük rendszerünk gyenge pontjait, túlterhelt elemeit, esetleges körkörös hivatkozásokat ("A" service hívja "B" service-t, ami hívja "A" service-t - ha láttunk már ilyet, kerüljük el messziről). Ezek mind indikátorai lehetnek az architektúra elhibázott megtervezésének, aminek javítása, lévén adott esetben még csak egy modellünk van, lényegesen kisebb erőbefektetés, mint később, amikor már rendszerünk bevételt termel napi több tíz- vagy százezer kérés végrehajtásával.

A PlantUML

A PlantUML egy az UML specifikációra építő leírónyelv, mellyel kvázi kódot írva tudunk létrehozni UML diagramokat. Számos UML diagram típust támogat a nyelv, de mi most csak a szekvencia diagramokkal fogunk részleteiben foglalkozni. Egy nagyon egyszerű szintaktikájú leírónyelvről beszélünk, minden sora egy új utasítás a feldolgozónak, így blokkok is inkább csak logikai szinten léteznek, egy ilyen blokk lezárásnak hiánya sem feltétlenül okoz komoly problémát, legfeljebb a generált diagram szörnyen fog kinézni. Nyilván van egy maréknyi foglalt szava, vannak processzor direktívák, tudjuk "deklarálni" és ezzel bizonyos esetekben finomhangolni a diagramunk "résztvevőit", de a deklaráció elhagyásával a résztvevő első megjelenése a kódban automatikusan deklarálja azt. Természetesen inkább a funkcionális nyelvekre hajaz az összkép, ugyanakkor egyedi kódblokkok, viselkedés definíciók, kvázi "eljárások" létrehozására is van lehetőség, így egy meglehetősen erőteljes nyelvről beszélünk. Komplett alkalmazásokat persze azért nem fogunk tudni megírni benne, az említett eljárások is csak jobban strukturált diagramok elkészítésében tudnak segédkezni.

A PlantUML nyelvi készletének jelentős részét amúgy formázási direktívák teszik ki, emellett persze arra is bőségesen ad lehetőséget, hogy minél egyértelműbb diagramokat hozzunk létre, de már alig néhány kulcsszó használatával is kifejezetten jól használható diagramokat készíthetünk. Elöljáróban ezek közül néhány:

  • A diagram specifikációját mindig a @startuml direktíva nyitja és az @enduml direktíva zárja. Nyilván ezek jelzik a feldolgozónak, hogy a köztük megjelenő szöveg egy PlantUML nyelven leírt diagram lesz.
  • A kéréseket a résztvevők között a -> operátor jelzi, a rájuk érkező válaszokat tipikusan a <-- operátorral vizualizáljuk.
  • A résztvevőket külön deklarálás nélkül is használhatjuk, ekkor egy tetszőleges (nem foglalt nyelvi szó) lehet mindkét résztvevő, köztük az üzenetküldés irányát jelezzük, illetve a sor végén : után egy megjegyzést fűzhetünk az interakcióhoz.

Ennek megfelelően az alábbi már egy érvényes PlantUML szekvenciadiagram:

@startuml
User -> Application: A felhasználó hívja az alkalmazást
User <-- Application: Az alkalmazás válaszol a felhasználónak
@enduml

A generált szekvenciadiagram pedig így fog kinézni: PlantUML example 1

Ez persze egy nagyon egyszerű példa volt, és ennél érdemes is tovább menni. Az úgynevezett "lifeline activation" jelölőkkel a diagramunk például sokkal beszédesebb lesz abban a tekintetben, hogy melyik hívott fél egész pontosan meddig foglalkozik az adott kéréssel. Emellett bevezethetünk különböző típusú résztvevőket is, lehet például emberi felhasználót is jelölni, vagy például egy adatbázist. Nézzünk erre egy példát, legyen a vizualizált folyamat a következő: a felhasználó egy web alkalmazást hív, a web réteg meghívja a service réteget, ami egy adatbázistól kéri el az adatokat, majd meghív egy másik külső service-t, a visszatérés után pedig még elvégez egy transzformálást, ezután pedig válaszol a felhasználónak. Az eredetileg hívott API saját alkalmazásunk, míg a kérés feldolgozása során hívott másik service egy harmadik féltől származó szolgáltatás - ezt is jelölni fogjuk a diagramon csoportok segítségével.

@startuml
autoactivate on

actor User
box 1st party service #eee
  participant WebAPI
  participant ServiceLayer
  database Database
  participant Transformer
endbox
box 3rd party service #ccc
  participant ExternalService
endbox

User -> WebAPI: A felhasználó az API-t hívja
  WebAPI -> ServiceLayer: Az API delegálja a kérést a service rétegnek
    ServiceLayer -> Database: A service réteg adatokat kér az adatbázisból
    ' A return ugyanazt eredményezi mintha azt írnánk: ServiceLayer <-- Database
    return
    ServiceLayer -> ExternalService: A service réteg a külső service-t hívja
    return
    ServiceLayer -> Transformer: A service réteg "formázza" az adatokat
    return
  return
return Válasz az eredeti kérésre

@enduml

Ez már egy viszonylag komplex példa, és néhány "apróságra" hadd térjek is ki részleteiben:

  • A script elején az autoactivate on parancs olvasható. Ezzel a már korábban említett lifeline-okat aktiváljuk, illetve azok automatikus alkalmazását. Enélkül minden interakció kezdetén kézzel az activate RésztvevőNeve és a deactivate RésztvevőNeve parancsokkal lehet ki-bekapcsolgatni a lifeline-okat.
  • A visszatéréseket a <-- operátor helyett a return paranccsal jelöltem - ez egy rövidítés rá, a legutóbbi kimenő kérést zárja automatikusan. A return után is megadhatunk egy megjegyzést, pont mint a <-- operátor esetén.
  • A résztvevőket most explicit definiáltam, a participant (általános résztvevő), és database (adatbázis résztvevő) kulcsszavakkal. Van még néhány ehhez hasonló, azokkal tovább lehet finomhangolni a résztvevők listáját. Emellett csoportosítottuk is a résztvevőket a box kulcsszó segítségével, mivel a diagram ebben az esetben két különböző rendszer közötti kommunikációt is ábrázol, a saját rendszerünk alacsony szintű folyamatábrázolása mellett. Mivel a második rendszer számunkra egy "feketedoboz" a scenario alapján, így felé csak a hívás tényét ábrázoljuk. A box utáni szöveg egy tetszőleges címke lesz, míg a # szimbólum után a doboz háttérszíne adható meg. Fontos megjegyezni, hogy ha explicit definiáljuk a résztvevőket, a típusuk mellett a sorrendjüket is megadhatjuk: a diagramon a definiálásuk sorrendjében jelennek majd meg.
  • Egy sor ' szimbólummal kezdődik: ez egy megjegyzés, a feldolgozó ignorálja az ilyen sorokat.

A generált diagram így fog kinézni: PlantUML example 2

Alacsony szintű folyamatok ábrázolásánál szükségünk lehet ciklusok és feltételes elágaztatások használatára. Nézzük, hogyan ábrázolhatnánk egy batch feldolgozót: A klasszikus, kisebb "csomagokra", azaz batch-ekre felosztott ETL (extract-transform-load) folyamatot egy időzítő indítja majd. Ha a feldolgozás befejeződött, arról a sikerességtől függő tartalmú emailt küld a rendszer.

@startuml

autoactivate on

control Scheduler
participant BatchProcessor
database SourceDB
participant Transformer
database TargetDB
participant MailService

Scheduler -> BatchProcessor: Az időzítő elindítja a feldolgozást

loop Amíg elfogynak a forrás rekordok
  BatchProcessor -> SourceDB: Forrás rekord batch kérése
  return batch
  BatchProcessor -> Transformer: Adatok transzformálása
  ...Hosszantartó feldolgozás után...
  return transzformált batch
  BatchProcessor -> TargetDB: Transzformált adatok írása a cél adatbázisba
  return sikeresség jelentése
end

alt Ha sikeres a feldolgozás
  BatchProcessor -> MailService: Értesítés sikeres feldolgozásról
  note right: async hívás
  deactivate
else Ha sikertelen a feldolgozás
  BatchProcessor -> MailService: Értesítés sikertelen feldolgozásról
  note right: async hívás
  deactivate
end

@enduml

Újfent nézzük meg mi is történik itt:

  • Van egy újfajta résztvevőnk, ami control típusú. Ő egy általános külső szereplő, ez esetben egy időzítő.
  • A loop blokkal ciklust, illetve ciklusba rendezett hívásokat jelölünk. A kulcsszó utáni megjegyzéssel egyértelműsíthetjük, mi történik a ciklusban. Lezárni a ciklusblokkot az end kulcsszóval tudjuk.
  • Az alt blokk feltételes elágaztatás, természetesen a "hamis" ágat is jelölhetjük, az else kulcsszóval. A loop-hoz hasonlóan end utasítással zárjuk és itt is megadhatunk egyértelműsítő megjegyzést.
  • Van egy ... szimbólum-pár között megadott sor: ezzel tipikusan hosszú ideig tartó műveleteket, várakoztatást, async feldolgozást, stb. jelölhetünk.
  • Továbbá láthatunk két note utasítást is, ezzel további kis megjegyzés blokkokat adhatunk hozzá a diagramhoz. Az utána álló right kulcsszó a megjegyzés doboznak az interakciós vonalhoz viszonyított pozícióját jelöli, lehet még left és over is, illetve többsoros megjegyzést is létrehozhatunk, ha a blokkot az end note utasítással zárjuk. Vannak további pozicionálási és formázási lehetőségek is, természetesen a referencia dokumentáció ezekről részletesen ír (ez természetesen minden korábban felsorolt elemre is igaz).

Az elkészült diagram így fog kinézni: PlantUML example 3

Végszó

Azt hiszem, kezdésnek ez talán bőven elég is lehet ahhoz, hogy akár már komolyabb szekvencia diagramokat is össze tudjunk rakni. Remélem a példákkal sikerült legalább gondolatokat ébresztenem és láthatóak az elkészült diagramok előnyei. Amennyiben igen és szeretnétek kipróbálni a PlantUML nyelvet, illetve belevágnátok ilyesféle folyamat modellezésbe, kiindulási pontnak mindenképp a PlantUML nyelv hivatalos oldalát tudnám ajánlani, ami természetesen teljes referencia dokumentációt is tartalmaz. Ugyanitt elérhető egy online modellező eszköz is, amivel ki lehet próbálni az elkészült scripteket. Elérhetőek emellett integrált modellezők is, például Atlassian Confluence-hez is van plugin (bár ingyen már csak a self-hosted verzióhoz), de a népszerű IDE-khez (Eclipse, IntelliJ IDEA, VSCode, stb.) is elérhetőek ingyenes pluginek. Ezek természetesen a renderelés mellett szintaxis-segéddel is rendelkeznek, így segítve a nyelv szintaktikájának megtanulását.

Források

PlantUML nyelvi specifikáció, user guide, és online modellező eszköz

Az UML nyelv hivatalos oldala

Kommentek
Hozzászólok

Még senki nem szólt hozzá ehhez a bejegyzéshez.