Zum Hauptinhalt springen

Sequenzdiagramm

Überblick​

Ein Sequenzdiagramm ist ein Verhaltensdiagramm der UML und gehört zur Gruppe der Interaktionsdiagramme. Es zeigt, welche Kommunikationspartner welche Nachrichten austauschen und in welcher Reihenfolge das geschieht. Die Partner stehen nebeneinander, die Zeit läuft von oben nach unten.

Typische Anwendungsfälle:

  • Detaillierung eines einzelnen Szenarios eines Anwendungsfalls, meist der Normalablauf und eine Ausnahme
  • Dokumentation des Zusammenspiels von Objekten oder Komponenten für eine Funktionalität
  • Beschreibung eines Protokolls zwischen Systemen, beispielsweise Client, Server und Datenbank
  • Prüfung eines Entwurfs gegen das Klassendiagramm in beide Richtungen: Eine Nachricht, die keine Klasse als Operation anbietet, deckt eine fehlende Operation auf, eine Lebenslinie ohne eingehende Nachrichten eine unerreichbare Klasse

Ein Sequenzdiagramm zeigt immer einen konkreten Ablauf. Alternativen und Wiederholungen lassen sich über kombinierte Fragmente ausdrücken, ein Diagramm, das jeden Fall zugleich abdecken will, wird jedoch unlesbar. Mehrere kleine Diagramme sind daher einem großen vorzuziehen.


Notation​

ElementNotationBedeutung
DiagrammrahmenRechteck mit Fünfeck-Reiter, beschriftet mit sd und NameGrenze und Name der Interaktion
Kopf der LebenslinieRechteck mit name : Class, :Class oder nameEin Kommunikationspartner: Objekt, Komponente oder Akteur
LebenslinieGestrichelte senkrechte Linie unterhalb des KopfesExistenz dieses Partners im Zeitverlauf
AusführungsspezifikationSchmales Rechteck auf der Lebenslinie (Aktivierungsbalken)Zeitraum, in dem der Partner aktiv ist oder einen Aufruf bearbeitet
Synchrone NachrichtDurchgezogene Linie, gefüllte Pfeilspitze ──▶Der Sender wartet, bis die Antwort eintrifft
Asynchrone NachrichtDurchgezogene Linie, offene Pfeilspitze ──>Der Sender läuft sofort weiter, es wird nicht gewartet
AntwortnachrichtGestrichelte Linie, offene Pfeilspitze <- - -Rückgabe der Kontrolle, wahlweise mit dem Rückgabewert beschriftet
SelbstaufrufPfeil, der dieselbe Lebenslinie verlässt und wieder erreichtEin Partner ruft eine eigene Operation auf
ErzeugungsnachrichtGestrichelter Pfeil mit «create» auf einen LebenslinienkopfDer Empfänger entsteht während der Interaktion
ZerstörungsereignisKreuz X am unteren Ende einer LebenslinieDas Objekt wird zerstört, die Lebenslinie endet dort
Kombiniertes FragmentRechteck mit dem Operator in der linken oberen EckeKontrollstruktur, beispielsweise alt, opt, loop, par
OperandAbschnitt eines Fragments, durch gestrichelte Linie getrenntEin Fall oder ein Zweig innerhalb des Fragments
Guard[condition] am Anfang eines OperandenBedingung, unter der dieser Operand gilt
InteraktionsverwendungFragment mit dem Operator refVerweis auf eine Interaktion, die ein eigenes Diagramm besitzt
Zustandsinvariante{condition} auf einer LebenslinieBedingung, die zu diesem Zeitpunkt gelten muss
NotizRechteck mit geknickter Ecke an gestrichelter LinieKommentar ohne Semantik

Benennungsregeln, die ein Diagramm lesbar halten:

  • Eine Nachricht trägt die Signatur der aufgerufenen Operation, beispielsweise reserve(seatNo), keinen Satz wie the seat is reserved
  • Eine Antwort wird mit dem Rückgabewert beschriftet, nicht erneut mit dem Operationsnamen
  • Lebenslinien werden nach Objekten benannt, nicht nach Tätigkeiten: :SeatRepository ist ein Partner, Save seat nicht
  • Anonyme Objekte werden als :Class geschrieben, ein benanntes Objekt als seat : Seat, eine Rolle nur mit ihrem Namen

Bausteine​

Lebenslinie, Ausführungsspezifikation und Antwort​

Eine Nachricht von einem Partner an einen anderen startet beim Empfänger eine Ausführungsspezifikation, die Antwort beendet sie. Eine synchrone Nachricht passt zu einem Aufruf, dessen Ergebnis der Aufrufer braucht, bevor er weiterarbeiten kann, z.B. ein Methodenaufruf oder eine HTTP-Anfrage, auf deren Antwort gewartet wird.

:Client :AuthService
│ │
┌┴┐ │
│ │─── login(user, pw) ────▶┌┴┐
│ │ │ │
│ │<- - - - - token - - - - └┬┘
│ │ │
└┬┘ │
│ │

Die Antwort darf entfallen, wenn sie keine Information trägt.

Asynchrone Nachricht​

Eine asynchrone Nachricht wird übergeben, der Sender läuft ohne Warten weiter. Sie passt zu Ereignissen, Benachrichtigungen, Nachrichten an eine Warteschlange und Aufrufen in einem eigenen Thread, bei denen der Sender kein Ergebnis braucht. Der Balken des Senders ist unabhängig vom Balken des Empfängers und darf vor diesem enden.

:OrderService :MailService
│ │
┌┴┐ │
│ │──── sendMail(order) ───────>┌┴┐
└┬┘ │ │
│ │ │
│ └┬┘
│ │

Selbstaufruf​

Ein Selbstaufruf ist ein Pfeil, der eine Lebenslinie verlässt und etwas weiter unten dieselbe Lebenslinie wieder erreicht. Er wird gezeichnet, wenn ein interner Schritt eines Partners, etwa eine Prüfung oder Berechnung, für das Verständnis des Ablaufs wichtig ist. Private Hilfsaufrufe ohne diese Bedeutung entfallen. Ein streng gezeichneter Selbstaufruf erhält eine geschachtelte Ausführungsspezifikation, also einen leicht versetzten zweiten Balken auf dem ersten.

:OrderService
│
┌┴┐
│ ├───┐ validate()
│ ┌─┐◀┘
│ │ │
│ └─┘
│ │
└┬┘
│

Erzeugung und Zerstörung von Objekten​

Ein Objekt, das erst während der Interaktion entsteht, wird mit seinem Kopf auf der Höhe gezeichnet, auf der es erzeugt wird. Die Erzeugungsnachricht zeigt auf den Kopf, nicht auf die Lebenslinie. Die Zerstörung wird mit einem Kreuz am Ende der Lebenslinie markiert.

:Session
│
┌┴┐
│ │ «create»
│ │- - - - - - - - - ->┌─────────┐
│ │ │ :Cart │
│ │ └────┬────┘
│ │──── addItem(item) ────▶┌┴┐
│ │ └┬┘
│ │──── «destroy» ────────▶ X
└┬┘
│

Kombinierte Fragmente​

Ein kombiniertes Fragment ist ein Rechteck um einen Teil der Interaktion. Der Operator in der linken oberen Ecke legt fest, welche Kontrollstruktur für die eingeschlossenen Nachrichten gilt, z.B. eine Alternative oder eine Schleife. Gestrichelte waagerechte Linien teilen das Fragment in Operanden, und in einem alt-Fragment trägt jeder Operand einen Guard.

OperatorBedeutungEntspricht
altAlternativen, genau ein Operand läuft, der verbleibende Fall wird mit [else] beschriftetif / else if / else
optEin einzelner Operand, der nur läuft, wenn der Guard erfüllt istif ohne else
loopWiederholung, geschrieben als loop(min,max) oder mit einem Guardwhile, for, do … while
breakDer Operand ersetzt den Rest der umgebenden InteraktionVorzeitiges return, Ausnahme
parDie Operanden laufen nebenläufig, ihre Nachrichten dürfen sich verschränkenThreads, Tasks, parallele Aufrufe
refVerweis auf eine Interaktion, die in einem eigenen Diagramm gezeichnet wirdMethodenaufruf, Teilablauf
criticalDer Operand darf nicht von nebenläufig laufenden Operanden unterbrochen werdenKritischer Abschnitt, Sperre
negDie eingeschlossene Folge ist ungültig und darf nicht auftretenNegativer Testfall
assertDie eingeschlossene Folge ist die einzig gültige FortsetzungZusicherung

In der Praxis decken alt, opt und loop die weitaus meisten Diagramme ab.

Alternative​

:Client :Booking
│ │
┌┴┐ │
│ │──── reserve(seatNo) ───────▶┌┴┐
│ │ │ │
┌──────┼─┼─────────────────────────────┼─┼────────┐
│ alt │ │ [seat is free] │ │ │
│ │ │<- - - - reservationId - - - │ │ │
├╌╌╌╌╌╌┼╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌┼╌╌╌╌╌╌╌╌┤
│ │ │ [else] │ │ │
│ │ │<- - - SeatTakenError - - - -│ │ │
└──────┼─┼─────────────────────────────┼─┼────────┘
└┬┘ └┬┘
│ │

Die Guards eines alt-Fragments müssen sich gegenseitig ausschließen und sollten jeden Fall abdecken.

Schleife​

:Order :LineItem
│ │
┌┴┐ │
┌──────┼─┼──────────────────────────────┼─────────┐
│ loop │ │ [more items] │ │
│ │ │──── subtotal() ────────────▶┌┴┐ │
│ │ │<- - - - amount - - - - - - -└┬┘ │
└──────┼─┼──────────────────────────────┼─────────┘
└┬┘ │
│ │

loop(1,n) drückt eine Anzahl statt einer Bedingung aus, loop ohne Zusatz bedeutet eine unbegrenzte Wiederholung.


Beispiel: Detaillierung des Anwendungsfalls Sitzplatz buchen​

Detailliert wird hier der Normalablauf des Anwendungsfalls Sitzplatz buchen: Ein Kunde bucht einen bestimmten Platz, das System schlägt den Platz nach und markiert ihn als gebucht, sofern er noch frei ist. Das Diagramm wird in diesen Schritten aus der textuellen Beschreibung des Anwendungsfalls abgeleitet:

  1. Ein Szenario des Anwendungsfalls wird ausgewählt, üblicherweise der Normalablauf aus der textuellen Beschreibung.
  2. Der auslösende Akteur wird zur äußerst linken Lebenslinie.
  3. Die internen Partner kommen hinzu, typischerweise entlang der Schichten der Architektur: Oberfläche, Steuerung, Fachobjekt, Persistenz.
  4. Jeder Schritt des textuellen Ablaufs wird zu einer Nachricht, deren Name zu einer Operation des Empfängers passt.
  5. Ausnahmen aus der textuellen Beschreibung werden zu alt- oder break-Fragmenten oder zu je einem eigenen Diagramm.
┌────────────────┐
│ sd BookSeat │
├────────────────┴─────────────────────────────────────────────────────┐
│ │
│ :Customer :BookingService :SeatRepository │
│ │ │ │ │
│ ┌┴┐ │ │ │
│ │ │── bookSeat(id) ────▶┌┴┐ │ │
│ │ │ │ │── findSeat(id) ────▶┌┴┐ │
│ │ │ │ │<- - seat - - - - - -└┬┘ │
│ │ │ │ │ │ │
│ │ │ ┌──────┼─┼──────────────────────┼───────┐ │
│ │ │ │ opt │ │ [seat is free] │ │ │
│ │ │ │ │ │── markBooked(id) ──▶┌┴┐ │ │
│ │ │ │ │ │<- - - - ok - - - - -└┬┘ │ │
│ │ │ └──────┼─┼──────────────────────┼───────┘ │
│ │ │<- - confirmation - -└┬┘ │ │
│ └┬┘ │ │ │
│ │ │ │ │
└──────────────────────────────────────────────────────────────────────┘

Was sich aus diesem Beispiel ablesen lässt:

  • Der Fehlerfall des opt-Fragments ist hier nicht gezeichnet, er würde entweder mit alt oder in einem eigenen Diagramm modelliert.
  • Der Bezahlvorgang würde als ref-Fragment eingefügt, damit dieses Diagramm lesbar bleibt und die Bezahlung eine eigene Interaktion erhält.

Sequenz-, Aktivitäts- oder Kommunikationsdiagramm​

Alle drei sind Verhaltensdiagramme.

KriteriumSequenzdiagrammAktivitätsdiagrammKommunikationsdiagramm
SchwerpunktNachrichtenaustausch im ZeitverlaufKontrollfluss eines AblaufsStruktur der Zusammenarbeit
ZeitExplizit, als senkrechte AchseImplizit, über die FlussrichtungNur über die Nummerierung der Nachrichten
BeteiligteLebenslinien nebeneinanderOptional, als PartitionenFrei platzierte Objekte, durch Links verbunden
VerzweigungenKombinierte Fragmente, schnell unübersichtlichEntscheidungs- und Verbindungsknoten, gut lesbarKaum lesbar
Nebenläufigkeitpar-FragmentParallelisierung und SynchronisationMöglich, aber schlecht lesbar
Typischer ZweckDetaillierung eines SzenariosModellierung eines ganzen AblaufsDarstellung, welches Objekt welches kennt

Faustregeln:

  • Viele Verzweigungen und Schleifen, wenige Beteiligte => Aktivitätsdiagramm
  • Wenige Verzweigungen, viele Beteiligte und eine relevante Reihenfolge => Sequenzdiagramm
  • Die Frage wer ist mit wem verbunden statt in welcher Reihenfolge => Kommunikationsdiagramm
  • Das Verhalten eines einzelnen Objekts über seine gesamte Lebensdauer => Zustandsdiagramm

Häufige Fehler​

  1. Zeitachse ignoriert: Die Zeit läuft über alle Lebenslinien hinweg von oben nach unten. Ein nach oben gezeichneter Pfeil kehrt die beabsichtigte Reihenfolge deshalb um. Zwei Nachrichten auf gleicher Höhe haben keine festgelegte Reihenfolge.
  2. Antwort als durchgezogener Pfeil: Eine Antwort wird als gestrichelte Linie mit offener Pfeilspitze gezeichnet. Eine durchgezogene Linie mit gefüllter Pfeilspitze wird als neuer Aufruf in die Gegenrichtung gelesen.
  3. Synchron und asynchron verwechselt: Die gefüllte Pfeilspitze bedeutet, dass der Sender auf die Antwort wartet. Ereignisse, Benachrichtigungen und Nachrichten an eine Warteschlange sind asynchron und erhalten die offene Pfeilspitze.
  4. Ausführungsspezifikationen nicht geschlossen: Der Balken eines Aufrufers muss mindestens bis zum Eintreffen der Antwort reichen. Ein früher endender Balken behauptet, der Aufrufer sei bereits fertig gewesen.
  5. Tätigkeiten statt Objekte auf den Lebenslinien: Eine Lebenslinie steht für einen Kommunikationspartner wie :SeatRepository. Ein Schritt wie Check availability ist kein Partner und wird stattdessen zu einer Nachricht.
  6. Fehlende Guards an alt-Operanden: Ohne Guards zeigt das Diagramm nicht, unter welcher Bedingung welcher Operand des alt-Fragments gilt.

Werkzeuge​

  • draw.io / diagrams.net (kostenlos, browserbasiert, UML-Formenbibliothek enthalten)
  • PlantUML (textbasiert, besonders stark bei Sequenzdiagrammen, lässt sich versionieren)
  • Mermaid (textbasiert, wird auf vielen Plattformen direkt in Markdown gerendert)
  • Visual Paradigm, StarUML, Lucidchart (kommerziell, mit kostenlosen Tarifen)

Siehe auch​