UML Aktivitätsdiagramm und die Modellierung mit plantUML
https://oer-informatik.de/uml-aktivitaetsdiagramm-plantuml
https://bildung.social/@oerinformatik/112066979165700523
tl/dr; (ca. 6 min Lesezeit): Mithilfe von PlantUML lassen sich auch UML-Aktivitätsdiagramme per “Diagramm as Code” erstellen. Das geht nicht ganz so leicht von der Hand wie Sequenz- oder Klassendiagramme, da plantUML hier etwas umständlich ist. Für einfache Diagramme wird der Aufbau hier erklärt… (Zuletzt geändert am 04.03.2025)
Dieser Artikel ist Teil einer Artikelreihe über UML-Diagramme: Klassendiagramm / Sequenzdiagramm / Aktivitätsdiagramm / Zustandsdiagramm (State) / Anwendungsfall-Diagramm (Use Case). Für alle sind jeweils auch PlantUML-Anleitungen verlinkt.
PlantUML bietet die Möglichkeit, UML-Diagramme als Code zu definieren und so einfach in die Dokumentationen der Repositories einzubinden. Man braucht dazu eigentlich nur einen Browser und einen Webservice wie Planttext oder PlantUML.
Die Markdown-Engines von Gitlab, Github, Bitbucket & Co. unterstützen PlantUML nativ und zeigen die Diagramme direkt an. Wenn man sich an den UML-Standard halten will, macht es einem PlantUML aber nicht immer einfach - und auch die Online-Referenz (plantuml.com/de/activity-diagram-beta) geht sehr pragmatisch mit der UML um.
Im Folgenden werden einige Tipps gegeben, wie sich mit PlantUML ansehnliche und relativ standardkonforme Aktivitätsdiagramme darstellen lassen.

Ein einfaches unverzweigtes Aktivitätsdiagramm
Plantuml fügt die einzelnen Aktivitäten zwischen start
und stop
ein, wobei jede Aktivität mit Doppelpunkt beginnt und mit Semicolon endet: :aktivitätsname;
:
@startuml 'Muss immer am Anfang stehen
start
:Schritt 1;
:Multiline
Schritt **2**;
stop
@enduml
In diesem Beispiel ist das einfache Aktivitätsdiagramm um Kommentare ergänzt worden:

Codebeispiel: ( online bearbeitbar / vollständiger Quelltext )
Kontrollstrukturen: Verzweigung und Vereinigung
Kontrollstrukturen sind leider in PlantUML wenig intuitiv. Da wir die Guards an den Kanten notieren wollen, müssen wir die Syntax etwas aufbohren. Von Haus schreibt PlantUML einen Text in die decision node und zeichnet sie dann als Sechseck - das ist nicht im Standard enthalten. Ich löse das so: die erste Bedingung wird hinter then()
in Klammern notiert, den else
-Block sollte man in jedem Fall notieren:
Codebeispiel: ( online bearbeitbar / vollständiger Quelltext )
if() then ([Geld ausreichend])
:kaufe Produkt;
else ([else])
endif

Beispiel mit Aktivitäten an beiden Alternativkanten ( online bearbeitbar / vollständiger Quelltext: )
start
if() then ([Code fehlerfrei])
:Code compilieren;
else ([else])
:Fehlermeldung erstellen;
endif
stop

Nicht alle Bedingungen lassen sich unmittelbar als Prädikat formulieren. Sofern nähere Eräuterungen nötig sind sieht die UML vor, dass diese über eine Notiz mit dem Stereotyp <<decision input>>
erfolgt, die mit der decision node verbunden wird.
In PlantUML gibt es diese Möglichkeit nicht, daher muss man sich mit einer Notiz, die neben der vorigen Aktion steht, behelfen. Gemäß UML wird innerhalb der decision node nichts notiert - hier weicht die PlantUML-Dokumentation vom UML-Standard ab.

Codebeispiel: ( online bearbeitbar / vollständiger Quelltext )
:Schritt davor;
if() then ([true])
note right
<<decision input>>
Ist hinreichend
Bonität vorhanden?
end note
:Kaufvertrag abwickeln;
else ([false])
:zunächst Beratung anbieten;
endif
Für mehrfache Verzweigungen können multiple Bedingungen als verschachtelte If-Statements modelliert werden:

Codebeispiel: ( online bearbeitbar / vollständiger Quelltext )
if() then ([Taste A])
:Bewegung nach links;
elseif() then ([Taste D])
:Bewegung nach rechts;
else ([else])
:ignorieren;
endif
Mehrfache Verzweigungen können aber auch als Switch/Case-Statement umgesetzt werden:

Codebeispiel: ( online bearbeitbar / vollständiger Quelltext )
switch ()
case ( [Taste A] )
:Bewegung nach links;
case ( [Taste D] )
:Bewegung nach rechts;
case ( [else] )
:nur geradeaus fahren;
endswitch
Wiederholungsstrukturen: kopf- und fussgesteuerte Schleifen
Mit PlantUML erfolgt die Modellierung eine fussgesteuerten Schleife mit einem repeat / repeat while () is ([
guard ])
-Block:

Codebeispiel: ( online bearbeitbar / vollständiger Quelltext )
start
repeat
:Stufe hochsteigen;
repeat while () is ([else])
->[oben angekommen];
stop
Im Fall einer kopfgesteuerten Schleife wird die Bedingung zunächst geprüft, die zu wiederholenden Aktionen also ggf. nie ausgeführt.

Codebeispiel: ( online bearbeitbar / vollständiger Quelltext )
start
while() is ([hungrig])
:Brot schmieren;
:Brot essen;
endwhile ([satt])
stop
Concurrency: Parallelisierung von Aktionen (Splitting und Synchronisation)
Im Gegensatz zu einem decision node oder merge node müssen bei Gabelungen (fork node) oder Synchronisierung (join node) an allen eingehenden Kanten ein Token anliegen, damit sie wiederum Token weiterreichen. Entsprechend werden an allen ausgehenden Kanten dann Token weitergereicht. In PlantUML wird dies durch einen fork... fork again... end fork
-Block erreicht:

Codebeispiel: ( online bearbeitbar / vollständiger Quelltext )
start
fork
:Mache dies;
fork again
:...und mache
gleichzeitig das;
end fork
stop
Partitionen / Swimlanes zur Unterscheidung von Verantwortungsbereichen
Die UML sieht vor, dass modelliert werden kann, welche Akteurin oder welches System für bestimmte Aktionen verantwortlich oder organisatorisch Zuständig ist. Aufgrund des Aussehens werden diese Verantwortungsbereiche, die die UML partition nennt, oft swimlanes genannt. Diese Verantwortungsbereiche werden in PlantUML definiert, indem in der Zeile oberhalb einer Aktivität zwischen Pipes der Partitionsname steht (|Partition|
). Das wird leider schnell etwas unübersichtlich, aber mit etwas Übung klappt das:

Codebeispiel: ( online bearbeitbar / vollständiger Quelltext )
'Durch Nennung Reihenfolge festlegen
|Geschäftsführer|
|Fachabteilung|
|Kunde|
start
|Kunde|
:Lastenheft;
|Fachabteilung|
:Pflichtenheft;
|Geschäftsführer|
:Angebot auf
Pflichtenheft
basierend;
|Kunde|
:Angebotsprüfung;
:Vertragsabschluss;
stop
Signale/ Ereignisse senden und empfangen; Objektflüsse darstellen
Wenn neben dem Kontrollfluss noch der Objektfluss in ein Diagramm einfließen soll, stößt PlantUML schnell an seine Grenzen. Es können Signale empfangen (:empfange<
) und gesendet werden (:sende>
). Ausserdem können mit Objekten Daten und der Kontrollfluß von einer Aktivität zur nächsten übergeben werden (:übergebenes Objekt]
). Aber präziserte Notationen (Pin-Notation, Parametergruppen, Streams) sind leider mit PlantUML nicht möglich (oder mit nicht bekannt).

Codebeispiel: ( online bearbeitbar / vollständiger Quelltext )
:HTTP-POST-Request<
:Message Header + Body]
:Nachricht verarbeiten und
Antwortnachricht erzeugen;
:Response]
:sende Response>
stop
Ablaufende
Wenn das Erreichen eines Endes zwar den aktuellen Ausführungsstrang beendet - also den eingetroffenen Token konsumiert - aber in der Gesamtaktivität noch weitere Token vorhanden sein können, muss ein Ablaufende mit einem einfachen end
modelliert werden.

Codebeispiel: ( online bearbeitbar / vollständiger Quelltext )
start
fork
:atmen;
fork again
:denken;
fork again
:singen;
end
end fork
stop
Konnektoren (Sprungmarken) zur übersichtlicheren Darstellung
Konnektoren lassen sich relativ einfach über geklammerte Sprungmarkennamen ((A)
) erzeugen. Wenn danach keine ausgehenden Kanten dargestellt werden sollen, muss zusätzlich ein detach
notiert werden:

Codebeispiel: ( online bearbeitbar / vollständiger Quelltext )
start
fork
(A)
detach
(B)
fork again
:Mach' das;
end fork
stop
(A)
repeat
:immer wieder das;
repeat while () is ([weiter])
->[aufhören];
(B)
Vor- und Nachbedingungen
Aktionen können mit Vor- und Nachbedingungen versehen werden. Diese werden jeweils als Notiz mit dem jeweiligen Stereotyp notiert. Die Position kann rechts oder links erfolgen.

Codebeispiel: ( online bearbeitbar / vollständiger Quelltext )
start
:Schritt 1;
note right
<<localPrecondition>>
Diese Vorbedingung muss <b>vor</b>
Ausführung dieser Aktion erfüllt sein
====
<<localPostcondition>>
Diese Nachbedingung muss <b>nach</b>
Ausführung dieser Aktion erfüllt sein
end note
stop
plantUML-Webservice
PlantUML bietet einen Webservice, der Diagramme unmittelbar online rendert.
Variante 1: der PlantUML-Quelltext ist online als Resource verfügbar und soll gerendert ausgegeben werden. Hierzu muss eine URL nach dem Muster:
http://www.plantuml.com/plantuml/proxy?fmt=AUSGABEFORMAT&src=https://URL_PLANTUMLSOURCE
erstellt werden, wobei als AUSGABEFORMAT png
, svg
, eps
, epstext
und txt
genutzt werden kann.
Variante 2: PlantUML kodiert den Quelltext, um ihn so über den Webservice zugänglich (und bearbeitbar) zu machen. Die URL ist in diesem Fall wie folgt aufgebaut:
https://www.plantuml.com/plantuml/AUSGABEFORMAT/CODIERTERQUELLTEXT
wobei als AUSGABEFORMAT png
, svg
, eps
, epstext
und txt
genutzt werden kann. Wird als AUSGABEFORMAT uml
gewählt erhält man den bearbeitbaren Quelltext.
Editierbare Links lassen sich auch über den Service von planttext.com erstellen, sie nutzen die selbe Quelltextcodierung und URLs nach dem Muster:
https://www.planttext.com/?text=CODIERTERQUELLTEXT
Auch in den erzeugten PNG-Dateien wird der codierte Quelltext als Titel hinterlegt, so dass sie sich relativ einfach später weiterverarbeiten lassen.
plantUML-Formatierung: Aufhübschen von Aktivitätsdiagrammen
Wenn die Diagramme erstmal stehen, will man sie aufhübschen. Dafür stehen allerlei möglichkeiten zur Verfügung, die v.a. auf der plantUML-Seite dargestellt werden. Einige Beispiele sind hier abgebildet:
Der Standard bei PlantUML ist mittlerweile recht ansehnlich. In früheren Versionen waren die Diagramme für meine Begriffe zu bunt, heute sehe ich fast keine Notwendigkeit, hier anzupassen:
Codebeispiel: ( online bearbeitbar / vollständiger Quelltext )
@startuml
|QM|
|Dev|
|Customer|
start
repeat
:add Requirment;
|Dev|
fork
|QM|
:Review;
|Dev|
fork again
:ask Customer>
Detach
:get response<
fork again
:test;
fork again
:deploy;
end
|Dev|
end fork
|Customer|
repeat while () is ([open tasks])
->[finished];
|Dev|
stop
@enduml

Ich habe mir trotzdem angewöhnt, die Farben und Schriften anzpassen. Die meisten Diagramme, die ich hier verwende haben die folgenden skinparams
gesetzt:
Codebeispiel: ( online bearbeitbar / vollständiger Quelltext )
@startuml
skinparam DefaultFontName "Lucida Sans Typewriter"
skinparam Activity{
BackgroundColor snow
BorderColor DarkSlateBlue
DiamondBackgroundColor ghostwhite
DiamondBorderColor DarkSlateBlue
}
skinparam Note{
BorderColor DarkSlateBlue
BackgroundColor LightYellow
}
skinparam ArrowColor DarkSlateBlue
|Dev|
|QM|
|Customer|
start
...
stop
@enduml

Wenn man den Entwurfscharakter hervorheben will, ist vielleicht die handwritten
-Option geeignet. Mit eine Handschrift-Schrift (die im PlantUML-System hinterlegt sein muss) sieht das ganz ansehnlich aus. Ich nutze hier lokal “FG Virgil” (der Webservice kenn diese Schrift jedoch nicht und ersetzt sie). Ist natürlich Geschmackssache.
Codebeispiel: ( online bearbeitbar / vollständiger Quelltext )
@startuml
' Welche Schriften gibt es auf dem System?
' listfonts als plantUML-Kommando gibt's aus.
skinparam DefaultFontName "FG Virgil"
skinparam handwritten true
skinparam monochrome true
skinparam packageStyle rect
skinparam shadowing false
|Dev|
|QM|
|Customer|
start
...
stop
@enduml

Links und Referenzen
Projektwebsite https://www.plantuml.com/,
Website, auf der direkt plantUML-Quelltexte geparst werden können: https://www.planttext.com/
Hinweis zur Nachnutzung als Open Educational Resource (OER)
Dieser Artikel und seine Texte, Bilder, Grafiken, Code und sonstiger Inhalt sind - sofern nicht anders angegeben - lizenziert unter CC BY 4.0. Nennung gemäß TULLU-Regel bitte wie folgt: “UML Aktivitätsdiagramm und die Modellierung mit plantUML” von Hannes Stein, Lizenz: CC BY 4.0. Der Artikel wurde unter https://oer-informatik.de/uml-aktivitaetsdiagramm-plantuml veröffentlicht, die Quelltexte sind in weiterverarbeitbarer Form verfügbar im Repository unter https://gitlab.com/oer-informatik/uml/umlaktivitaet. Stand: 04.03.2025.
[Kommentare zum Artikel lesen, schreiben] / [Artikel teilen] / [gitlab-Issue zum Artikel schreiben]