Übungsaufgaben zum UML-Sequenzdiagramm
https://bildung.social/@oerinformatik/
https://oer-informatik.de/uml-sequenzdiagramm-uebungsaufgaben
UML, Sequenzdiagramm, kombinierte Fragmente, Beobachter-Muster, Stellvertreter-Muster, REST, Pseudocode, Übungsaufgaben, Prüfungsvorbereitung
tl/dr; (Bearbeitungszeit insgesamt 132 min, mehrere Aufgaben): Vier Übungsaufgaben zum UML-Sequenzdiagramm. Du leitest ein Diagramm aus einem Server-Protokoll ab, liest daraus Wartezeiten ab und entscheidest zwischen synchronen und asynchronen Nachrichten. Danach modellierst Du Objekterzeugung, Selbstaufrufe, verschachtelte Fragmente und Objektzerstörung, bewertest einen REST-Ablauf mit Cache, leitest ein Beobachter-Muster aus Java-Code ab, korrigierst einen fehlerhaften Entwurf, stellst einen Ablauf zwischen Menschen dar und setzt Pseudocode, ein Stellvertreter-Muster und einen Diagrammentwurf in Code bzw. Diagramme um. Alle Lösungen sind ausgeblendet und mit Punkteverteilung versehen [AI-Assisted]. (Zuletzt geändert am 29.10.2026)
Dieser Artikel ist Teil einer Artikelreihe über UML-Sequenzdiagramme: Einstieg in das Sequenzdiagramm (Übungsaufgaben) / Sequenzdiagramme mit PlantUML erstellen / Kurzübungen: TCP-Handshake, 2FA, CRAM-MD5, MQTT-Nachrichtenfluss, Webpage per MVP-Pattern, Zugriff erlauben mit OAuth2, Authentifizieren mit Passkey.
Diese Übungsaufgaben gehören zum Artikel UML-Sequenzdiagramme. Sie setzen die Grundlagen des UML-Klassendiagramms voraus und greifen die Entwurfsmuster Beobachter und Stellvertreter auf, die Du im Artikel zum Sequenzdiagramm kurz kennenlernst. Weitere, kleinere Übungen findest Du unter Übungsaufgaben zu UML-Sequenzdiagrammen.
Hinweise zur Bearbeitung: Als FIA, FIDP oder FIDV musst Du zur Teil-2-Prüfung Aufgaben auf Kernkompetenz-Ebene lösen können, das ist Aufgabe 2.1. Von FIA wird zusätzlich erwartet, dass ihnen Aufgaben auf Profilkompetenz-Ebene (Aufgabe 3.1, Aufgabe 3.2 und Aufgabe 3.3) keine Probleme bereiten. Zeichne Deine Diagramme auf Papier oder mit einem Werkzeug Deiner Wahl, bevor Du die Beispiellösung aufklappst. Eine saubere Handskizze genügt. Achte auf die Pfeilarten (synchron: durchgezogen mit gefüllter Spitze, Antwort: gestrichelt, asynchron: durchgezogen mit offener Spitze), auf die Beschriftung jedes Pfeils und auf die Ausführungsbalken. Du darfst eine Notationsübersicht nutzen:
Weitere Interaktionsoperatoren für kombinierte Fragmente: alt, opt, loop, break, par, neg, seq, strict, critical, ref (Verweis). Eine Objektzerstörung wird mit einem X am Ende der Lebenslinie notiert.
Andere fachlich richtige Lösungen sind ebenfalls richtig, z. B. abweichende Variablennamen für Rückgabewerte. Pseudocode darf in jeder üblichen Schreibweise notiert werden.
Du möchtest eigene Aufgaben zum Üben von einem KI-Sprachmodell generieren lassen?
Kopiere den Text in ein KI-Sprachmodell Deiner Wahl und passe Kompetenzstufe, Anzahl, Bearbeitungszeit und Szenario bei Bedarf an. Wie die Aufgaben aufgebaut sind, beschreibt der Artikel Wie sind die Aufgaben aufgebaut?. Prüfe die Ergebnisse mit dem Lehrartikel: KI-Sprachmodelle machen Fehler.
Erstelle neue Übungsaufgaben zum Thema „UML-Sequenzdiagramm“.
Bauplan: Halte Dich an Aufbau, Kompetenzstufen, Operatoren,
Anforderungsbereiche, Punkte und Zeitschätzung, die im Artikel
https://oer-informatik.de/aufgaben-aufbau beschrieben sind.
Fachliche Grundlage:
- https://oer-informatik.de/uml-sequenzdiagramm
- https://oer-informatik.de/uml-klassendiagramm
- https://oer-informatik.de/uml-sequenzdiagramm-plantuml
- Stilbeispiel: https://oer-informatik.de/uml-sequenzdiagramm-uebungsaufgaben
Die Aufgaben sollen Inhalte zu diesen Schlagwörtern abdecken:
- UML
- Sequenzdiagramm
- kombinierte Fragmente
- Beobachter-Muster
- Stellvertreter-Muster
- REST
- Pseudocode
Kompetenzstufe: Profilkompetenz (alternativ: Basiskompetenz, Kernkompetenz, Expertise)
Anzahl: 1 Aufgabe mit Teilaufgaben
Bearbeitungszeit in Minuten ca.: <5 bis 30 min>
Szenario: eines der Szenarien aus dem Bauplan
Vorgehen:
1. Lies zuerst die verlinkten Artikel. Kannst Du keine Webseiten
abrufen, sag mir das, statt zu raten.
2. Steht bei einer Angabe noch ein Platzhalter in <…>, frag mich
zuerst danach. Richte Punkte und Zahl der Teilaufgaben nach der
Bearbeitungszeit (ca. 0,9 min je Punkt).
3. Gib je Aufgabe Titel mit Kompetenzstufe, Ausgangssituation und
Teilaufgaben mit Operator und Punktzahl aus, dazu die geschätzte
Bearbeitungszeit.
4. Gib die Beispiellösungen mit Punkteverteilung erst aus, wenn ich
danach frage.
Aufgabe 2.1: Einlass in eine Werkstatt-Session beim Barcamp (Kernkompetenz)
(ca. 26 min Bearbeitungszeit)
Beim Barcamp „Lernen.Digital.Leben 2027“ am Ratz und Rübe Berufskolleg (RRB) haben einige Werkstatt-Sessions nur wenige Plätze, etwa Mia Schröders „Escape-Room mit Mikrocontrollern“ (Session S14, Raum B.104, 12 Plätze). An der Tür solcher Räume hängt ein Raumscanner, der den QR-Code auf dem Badge liest und die Teilnahme bei der SessionAPI einträgt. Daneben zeigt ein E-Ink-Türschild die freien Plätze an. Jeder Scanner hat beim Aufbau einen eigenen Geräteschlüssel erhalten, den er bei jeder Anfrage im Header mitschickt. Eine Anmeldung per Benutzername und Passwort gibt es am Scanner nicht.
Dimitrios Papadopoulos hat für die Dokumentation einen gelungenen Einlass aus dem Protokoll der SessionAPI herauskopiert. Alle Zeitstempel stammen von der Uhr der API, Laufzeiten im Schul-WLAN vernachlässigst Du.
10:58:31.402 von scanner-B104 PUT /api/sessions/S14/teilnahmen/P-0273
Authorization: Bearer gk-b104-…
10:58:31.405 intern geraetPruefen(schluessel) -> gueltig
10:58:31.409 an db SELECT plaetze, belegt FROM session WHERE id = 'S14'
10:58:31.425 von db plaetze = 12, belegt = 11
10:58:31.428 an db INSERT INTO teilnahme (session_id, person_id) VALUES ('S14', 'P-0273')
10:58:31.447 von db 1 Zeile
10:58:31.449 an schild-B104 zeigeFreiePlaetze(0) (wartet nicht auf Rückmeldung)
10:58:31.451 an scanner-B104 201 Created
Was das Protokoll nicht zeigt: Ist die Session schon voll, trägt die API nichts ein, schickt dem Türschild nichts und antwortet mit 409 Conflict. Der Scanner leuchtet nach 201 grün (leuchteGruen()), nach 409 rot (leuchteRot()).
a) Leite aus dem Protokoll und der Ergänzung ein UML-Sequenzdiagramm ab. Verwende die Lebenslinien scanner :Raumscanner, :SessionAPI, :Datenbank und schild :Tuerschild. Kläre vorher für jede Zeile: Wer schickt hier wem etwas, und wartet der Absender auf ein Ergebnis? Welche Zeilen beschreiben etwas, das ein Teilnehmer nur selbst tut? (15 Punkte)
Bewertung:
PUT /api/sessions/S14/teilnahmen/P-0273als synchrone Nachricht, der Geräteschlüssel als NotizAuthorization: Bearer …am Pfeil statt als Parameter (2 Punkte),geraetPruefen(schluessel)als Selbstaufruf mit versetztem Balken und Antwortgueltig(2 Punkte),SELECT …an die Datenbank mit Antwortplaetze = 12, belegt = 11(2 Punkte),alt-Fragment mit[belegt < plaetze]und[else], die Abfrage liegt davor (2 Punkte),INSERT INTO teilnahme …mit Antwort im ersten Operanden (1 Punkt),zeigeFreiePlaetze(0)asynchron (offene Pfeilspitze, keine Antwort) und nur im ersten Operanden (2 Punkte),Response 201 Createdim ersten,Response 409 Conflictim zweiten Operanden, jeweils gestrichelt zum Scanner (2 Punkte),leuchteGruen()bzw.leuchteRot()als Selbstaufruf des Scanners im passenden Operanden (je 1 Punkt).
Der Balken des Scanners bleibt vom PUT bis zur Antwort bestehen, weil er wartet. Die Zeilen „intern“ und das Leuchten sind keine Nachrichten an andere Teilnehmer, sondern Selbstaufrufe. Die Werte 12 und 11 darfst Du auch weglassen und allgemein plaetze, belegt schreiben.
b) Werte die Zeitstempel aus.
ba) Bestimme, wie lange der Raumscanner auf seine Antwort wartet und wie viel dieser Zeit die SessionAPI ihrerseits auf die Datenbank wartet. Erkläre mit dem Diagramm aus a), warum die Wartezeit der Datenbank in der Wartezeit des Scanners enthalten ist. (3 Punkte)
bb) Das Türschild braucht etwa 800 ms, bis die E-Ink-Anzeige umgeblättert ist. Emre Aksoy schlägt vor, zeigeFreiePlaetze synchron aufzurufen, „damit die API sicher weiß, dass das Schild stimmt“. Bewerte den Vorschlag. Berechne dazu, wie lange der Scanner dann warten würde, und schätze die Folgen ab, wenn zu Beginn der Session zwölf Personen nacheinander scannen. (4 Punkte)
ba) Der Scanner wartet von 31.402 bis 31.451, also 49 ms (1 Punkt). Die API wartet zweimal auf die Datenbank: 31.409 bis 31.425 = 16 ms und 31.428 bis 31.447 = 19 ms, zusammen 35 ms (1 Punkt). Beide Datenbankaufrufe sind synchron und liegen innerhalb des Ausführungsbalkens der API, der wiederum innerhalb des wartenden Balkens des Scanners liegt. Jede Millisekunde, die die API wartet, wartet der Scanner mit (1 Punkt).
bb) Synchron müsste die API die 800 ms des Türschilds abwarten, bevor sie mit 201 antwortet. Die Antwort käme etwa um 32.251 an, der Scanner wartet dann rund 849 ms statt 49 ms (1 Punkt). Zwölf Personen hintereinander warten zusammen etwa 12 · 0,849 s ≈ 10,2 s nur auf das System statt etwa 0,6 s; an der Tür entsteht eine Schlange, obwohl für den Einlass nur die Datenbank zählt (1 Punkt). Ist das Schild per Funk gerade nicht erreichbar (z. B. leerer Akku), hängt der Scanner bis zu einer Zeitüberschreitung, und niemand kommt mehr hinein (1 Punkt). Der Vorschlag ist deshalb abzulehnen: Die Anzeige ist eine Nebensache, der Einlass darf nicht von ihr abhängen. Ob das Schild stimmt, lässt sich anders sichern, z. B. indem das Schild nach dem Umblättern selbst eine asynchrone Meldung schickt oder die API den aktuellen Stand regelmäßig erneut sendet (1 Punkt).
c) Für das nächste Barcamp sind drei Erweiterungen geplant. Entscheide jeweils, ob die neue Nachricht synchron oder asynchron modelliert werden sollte, und begründe Deine Entscheidung. (6 Punkte)
- Vor dem Eintragen fragt die
SessionAPIbeimTicketdienstnach, ob das Badge zu einem gültigen Tagesticket gehört. - Nach jedem Einlass erhöht ein
Statistikdienstden Zähler für die Abschlussfolie im Plenum. - Antwortet die API mit 409, bekommt die Session-Leitung eine Push-Nachricht aufs Handy, damit sie bei Bedarf Stühle holen lässt.
Je Fall 1 Punkt für die Entscheidung und 1 Punkt für die Begründung:
- Synchron: Das Ergebnis entscheidet, ob die API überhaupt einträgt und ob der Scanner grün oder rot leuchtet. Ohne Antwort kann die API nicht weitermachen.
- Asynchron: Die API braucht vom Statistikdienst kein Ergebnis. Fällt der Dienst aus oder ist er langsam, soll der Einlass trotzdem sofort funktionieren.
- Asynchron: Ob und wann die Nachricht auf dem Handy ankommt, ändert nichts an der Antwort an den Scanner. Die Zustellung über einen Push-Dienst kann Sekunden dauern oder scheitern, wenn das Handy offline ist.
Andere Entscheidungen sind richtig, wenn die Begründung trägt, z. B. Fall 2 synchron, wenn der Zähler ausdrücklich vor der Antwort an den Scanner stimmen muss.
Aufgabe 3.1: Teilnahme an einer Freizeitaktivität (Profilkompetenz)
(ca. 35 min Bearbeitungszeit)
Du bist Auszubildende*r im Entwicklungsteam der Let’s Meet GmbH in Bielefeld. Die Kennenlern-App „Let’s Meet“ bringt Menschen für gemeinsame Freizeitaktivitäten zusammen. Für das neue Backend soll die Anmeldung zu einer Aktivität mit Warteliste umgesetzt werden. Bevor Jonas Weber mit der Programmierung beginnt, bittet Euer Ausbilder Yusuf Demir Dich, den Ablauf als Sequenzdiagramm zu dokumentieren. Er gibt Dir einen Auszug aus dem Klassenmodell:
TeilnahmeController
+ anmelden(aktivitaetId: Integer, benutzerId: Integer): String
+ absagen(aktivitaetId: Integer): String
- istZugelassen(b: Benutzer, akt: Aktivitaet): Boolean
Verwaltung
+ findeBenutzer(benutzerId: Integer): Benutzer
+ findeAktivitaet(aktivitaetId: Integer): Aktivitaet
+ loescheAktivitaet(akt: Aktivitaet): void
Aktivitaet
+ istAltersgerecht(b: Benutzer): Boolean
+ freiePlaetze(): Integer
+ fuegeHinzu(t: Teilnahme): String
+ getTeilnahmen(): Teilnahme[]
+ loeschen(): void
Teilnahme
+ Teilnahme(b: Benutzer)
+ setStatus(status: String): void
+ getBenutzer(): Benutzer
Benutzer
+ getPushToken(): String
PushDienst
+ sendePush(b: Benutzer, text: String): void
MailDienst
+ sendeMail(b: Benutzer, text: String): void
Yusuf beschreibt die Anmeldung so:
- Die App ruft beim
TeilnahmeControllerdie Methodeanmelden(aktivitaetId, benutzerId)auf. - Der Controller lässt sich von der
Verwaltungzuerst den Benutzerbund dann die Aktivitätaktgeben. - Mit seiner eigenen Methode
istZugelassen(b, akt)prüft der Controller, obbteilnehmen darf. Dazu fragtistZugelassendie Aktivität mitistAltersgerecht(b), obbdas Mindestalter der Aktivität (16 oder 18 Jahre) erfüllt. Weitere Prüfungen, z. B. auf eine Sperre, erledigtistZugelassenohne weitere Aufrufe. - Ist
bnicht zugelassen, erhält die App den Text „nicht zugelassen“. - Andernfalls erzeugt der Controller für
bein neues Objekttder KlasseTeilnahmeund übergibt es mitfuegeHinzu(t)an die Aktivität. Die Aktivität ermittelt mit ihrer eigenen MethodefreiePlaetze()die Zahl der freien Plätze. Ist mindestens ein Platz frei, setzt sie den Status vontauf „angemeldet“, sonst auf „warteliste“.fuegeHinzugibt den gesetzten Status zurück. - Ist der Status „angemeldet“, schickt der Controller über den
PushDienstdie Nachricht „Du bist dabei!“ anb, sonst „Du stehst auf der Warteliste.“. Der Controller wartet nicht, bis die Nachricht zugestellt ist. - Zum Schluss erhält die App den Status.
a) Erstelle für die Anmeldung ein UML-Sequenzdiagramm mit dem Interaktionsrahmen „sd Teilnahme anmelden“. Verwende die Lebenslinien :App, :TeilnahmeController, :Verwaltung, akt :Aktivitaet, t :Teilnahme und :PushDienst. Zeichne alle Nachrichten mit Beschriftung, alle Antworten mit Rückgabewerten und alle Ausführungsbalken ein. (24 Punkte)
Punkteverteilung (Vorschlag):
- 2 Punkte: Erzeugung von
t :Teilnahmemit gestricheltem Pfeil und offener Spitze, Kopf der Lebenslinie erst auf Höhe der Erzeugung (new(b)). - 11 Punkte: je 1 Punkt für jede richtig gerichtete und beschriftete Nachricht:
anmelden(…),findeBenutzer(…),findeAktivitaet(…),istZugelassen(b, akt)als Selbstaufruf,istAltersgerecht(b),fuegeHinzu(t),freiePlaetze()als Selbstaufruf der Aktivität,setStatus("angemeldet"),setStatus("warteliste"), zweimalsendePush(…). - 5 Punkte: je 0,5 Punkte für jede Antwort mit Rückgabewert (
b,akt,alterOk,zugelassen,plaetze, zweimalsetStatus,status, „nicht zugelassen“,statusan die App). - 3 Punkte: je 1 Punkt für die drei
alt-Fragmente mit Bedingungen in eckigen Klammern ([zugelassen == false]/[else],[plaetze > 0]/[else],[status == "angemeldet"]/[else]); das Fragment zu den freien Plätzen liegt im Ausführungsbalken der Aktivität, das Fragment zu den Push-Nachrichten im zweiten Zweig des äußeren Fragments. - 2 Punkte: Ausführungsbalken, insbesondere die verschachtelten Balken der Selbstaufrufe (der Aufruf von
istAltersgerechtstartet im inneren Balken vonistZugelassen). - 1 Punkt:
sendePushals asynchrone Nachricht (offene Pfeilspitze, keine Antwort).
Hinweise: Die Antwort auf istZugelassen darf auch direkt im Bedingungstext ausgewertet werden ([nicht zugelassen]). Ein opt-Fragment statt des äußeren alt ist falsch, weil beide Fälle unterschiedliche Abläufe haben.
b) Begründe, warum sendePush als asynchrone Nachricht, findeBenutzer dagegen als synchrone Nachricht modelliert wird. (2 Punkte)
findeBenutzer: Der Controller braucht das Ergebnis (das Benutzerobjektb), um weiterzuarbeiten. Er muss also warten, bis die Methode beendet ist → synchron (1 Punkt).sendePush: Der Controller braucht keine Antwort; die Zustellung an das Smartphone kann dauern oder scheitern (Gerät aus), und die Anmeldung soll trotzdem sofort abgeschlossen werden. Der Sender arbeitet also ohne zu warten weiter → asynchron (1 Punkt).
c) Organisator*innen können eine Aktivität absagen. Yusuf beschreibt den Ablauf so:
- Die App ruft beim Controller
absagen(aktivitaetId)auf. Der Controller lässt sich von derVerwaltungdie Aktivitätaktgeben und fragt sie mitgetTeilnahmen()nach allen Teilnahmen. - Für jede Teilnahme
tfragt der Controller mitgetBenutzer()den Benutzerbab und lässt sich mitgetPushToken()dessen Push-Token geben. Ist der Token ein leerer String (App-Benachrichtigungen ausgeschaltet), schickt der Controller über denMailDienstdie Nachricht „Abgesagt“, sonst über denPushDienst. In beiden Fällen wartet er nicht auf die Zustellung. - Danach ruft der Controller
loescheAktivitaet(akt)bei derVerwaltungauf. Diese ruftloeschen()an der Aktivität auf, wodurch das Objektaktzerstört wird. (Dass dabei auch die Teilnahmen gelöscht werden, musst Du nicht darstellen.) - Die App erhält den Text „abgesagt“.
Zeichne das Sequenzdiagramm „sd Aktivitaet absagen“. Ergänze dazu die Lebenslinien b :Benutzer und :MailDienst. (12 Punkte)
Punkteverteilung (Vorschlag):
- 4,5 Punkte: je 0,5 Punkte für die neun beschrifteten Nachrichten (
absagen,findeAktivitaet,getTeilnahmen,getBenutzer,getPushToken,sendeMail,sendePush,loescheAktivitaet,loeschen). - 3,5 Punkte: je 0,5 Punkte für die sieben Antworten mit Rückgabewerten (
akt,teilnahmen,b,token, Antwort aufloeschen(), Antwort aufloescheAktivitaet(akt), „abgesagt“). - 1,5 Punkte:
loop-Fragment mit Bedingung (z. B.[für jede Teilnahme t in teilnahmen]), das genau die Nachrichten je Teilnahme umschließt. - 1,5 Punkte:
alt-Fragment innerhalb der Schleife mit den Bedingungen[token == ""]und[else];sendeMailundsendePushasynchron. - 1 Punkt: Zerstörung von
aktmit einem X am Ende der Lebenslinie direkt nachloeschen(); danach keine Nachrichten mehr anakt.
Hinweis: Die Lebenslinien t :Teilnahme und b :Benutzer stehen in der Schleife jeweils für das gerade bearbeitete Objekt. Wer getPushToken() weglässt und den Token als Bedingung [b hat keinen Push-Token] notiert, verliert 1 Punkt (Nachricht und Antwort).
Aufgabe 3.2: Schließanlagen und Lagerbestand im Fahrradshop (Profilkompetenz)
(ca. 36 min Bearbeitungszeit)
Du bist Auszubildende*r in der IT der CSB-Rad GmbH in Bielefeld. Im Onlineshop können Kund*innen über den Konfigurator weitere Schlösser zu einer bestehenden gleichschließenden Schließanlage nachbestellen. Die Daten der Schließanlagen stellt die Lipper SchließTec KG über eine REST-API bereit. Sie erlaubt dem Shop nur eine begrenzte Zahl von Abrufen je Stunde; wer mehr anfragt, erhält den Statuscode 429 (Too Many Requests). Das Shop-Backend legt abgerufene Schließanlagen deshalb in einem eigenen Zwischenspeicher-Dienst ab, dem AnlagenCache. Der bisherige Ablauf sieht so aus:
Michael Hartmann vom Zweckverband Radwege OWL beschwert sich: Seine Schließanlage wurde vor drei Tagen um zwei Schlüssel erweitert, der Konfigurator zeigt aber immer noch den alten Stand. Cem Sarıkaya, Geschäftsführer Technik und IT, legt deshalb Regeln für die fünf möglichen Fälle fest:
| Fall | Eintrag im Cache | Antwort der SchließTec-API | Reaktion des Backends gegenüber dem Konfigurator |
|---|---|---|---|
| 1 | vorhanden, jünger als 24 Stunden | API wird nicht gefragt | 200 mit der Anlage aus dem Cache |
| 2 | fehlt oder älter als 24 Stunden | 200 mit der Anlage | Eintrag im Cache neu anlegen bzw. ersetzen, 200 mit der neuen Anlage |
| 3 | fehlt oder älter als 24 Stunden | 404 | Eintrag aus dem Cache entfernen, 404 |
| 4 | älter als 24 Stunden | 429 | 200 mit der alten Anlage und dem Hinweis „veraltet“ |
| 5 | fehlt | 429 | 503 (Service Unavailable) |
a) Prüfe für jeden der fünf Fälle, ob der bisherige Ablauf ihn richtig, nur teilweise oder gar nicht abbildet. Erkläre damit auch die Beschwerde von Herrn Hartmann. (5 Punkte)
- Fall 1: richtig abgebildet – liegt ein Eintrag vor, antwortet das Backend aus dem Cache (1 Punkt).
- Fall 2: nur teilweise – ein fehlender Eintrag führt zum Abruf bei der API. Ein veralteter Eintrag ist aber auch
!= nullund landet im ersten Operanden. Das Backend liefert ihn ohne Altersprüfung aus. Genau das passiert Herrn Hartmann: Der Eintrag ist drei Tage alt, die Erweiterung erreicht den Konfigurator nie (2 Punkte). - Fälle 3 bis 5: gar nicht abgebildet – der bisherige Ablauf geht davon aus, dass die API immer mit 200 antwortet. Bei 404 oder 429 ist nicht festgelegt, was das Backend tut (je Fall 0,5 Punkte, zusammen 1,5 Punkte; 0,5 Punkte für die Begründung).
b) Zeichne das Sequenzdiagramm neu, sodass es alle fünf Fälle abbildet. Behalte die Lebenslinien bei. Der AnlagenCache bietet die Methoden hole(code) (liefert den Eintrag samt Alter oder null), lege(code, anlage) und entferne(code). (14 Punkte)
Punkteverteilung (Vorschlag):
- 1 Punkt:
hole(code)an denAnlagenCachemit Antworteintrag. - 2 Punkte: äußeres
alt-Fragment, dessen erste Bedingung auch das Alter prüft ([eintrag != null und eintrag.alter < 24 h]), und[else]. - 1 Punkt: Antwort 200 aus dem Cache im ersten Operanden.
- 1 Punkt: GET-Anfrage an die SchließTec-API im zweiten Operanden.
- 2 Punkte: inneres
alt-Fragment mit drei Operanden für die Antworten 200, 404 und 429 (zwei verschachtelte Fragmente sind ebenso richtig). - 1,5 Punkte: je 0,5 Punkte für die drei Antworten der API.
- 1 Punkt:
lege(code, anlage)mit Antwort im Operanden für 200. - 1 Punkt:
entferne(code)mit Antwort im Operanden für 404. - 1,5 Punkte: innerstes
alt-Fragment mit[eintrag != null]/[else]im Operanden für 429, darin 200 mit der veralteten Anlage bzw. 503. - 1 Punkt: Antworten 200 und 404 an den Konfigurator in den passenden Operanden.
- 1 Punkt: Ausführungsbalken (Backend während der ganzen Anfrage aktiv, Cache und API nur während ihrer Bearbeitung).
Hinweise: HTTP-Anfragen werden wie synchrone Aufrufe notiert, weil der Client auf die Antwort wartet. Fall 4 entspricht der Idee von stale-if-error aus RFC 5861: Lieber einen leicht veralteten Stand zeigen als gar keinen. Wer die Altersprüfung als eigene Nachricht modelliert (z. B. eintrag.istFrisch()), erhält die vollen Punkte.
Für den Einkauf entstehen zwei Programme, die auf knappe Artikel reagieren: ein Dashboard, das eine Warnung anzeigt, und eine automatische Nachbestellung beim Großhandel. Bastian Ludwig, zuständig für Werkstatt und Einkauf, wollte sie unabhängig vom Lager entwickeln lassen. Beide sind deshalb über das Beobachter-Muster an den Lagerbestand gekoppelt. Der Code ist schon geschrieben (Java, Ausschnitt):
public interface LagerBeobachter {
void artikelKnapp(String artikelNr);
}
public class Lagerbestand {
private final List<LagerBeobachter> beobachter = new ArrayList<>();
private final Map<String, Integer> bestand = new HashMap<>();
private final Map<String, Integer> mindestbestand = new HashMap<>();
public void anmelden(LagerBeobachter b) {
beobachter.add(b);
}
public int getBestand(String artikelNr) {
return bestand.getOrDefault(artikelNr, 0);
}
public void entnehmen(String artikelNr, int menge) {
int neu = getBestand(artikelNr) - menge;
bestand.put(artikelNr, neu);
if (neu < mindestbestand.getOrDefault(artikelNr, 0)) {
for (LagerBeobachter b : beobachter) {
b.artikelKnapp(artikelNr);
}
}
}
}
public class EinkaufsDashboard implements LagerBeobachter {
private final Lagerbestand lager;
// Konstruktor ausgelassen
@Override
public void artikelKnapp(String artikelNr) {
int rest = lager.getBestand(artikelNr);
zeigeWarnung(artikelNr, rest);
}
private void zeigeWarnung(String artikelNr, int rest) { /* ... */ }
}
public class Nachbestellung implements LagerBeobachter {
private final Grosshandel grosshandel; // String bestelle(String artikelNr, int menge)
// Konstruktor ausgelassen
@Override
public void artikelKnapp(String artikelNr) {
grosshandel.bestelle(artikelNr, 20);
}
}Beim Start der Anwendung wurden die Objekte dash :EinkaufsDashboard und danach nb :Nachbestellung bei lager :Lagerbestand angemeldet. Im Lager liegen 48 Lichtsets (LIC-SET-01), der Mindestbestand beträgt 20 Stück. Für einen Werkstattauftrag bucht das :Lagerterminal die Entnahme entnehmen("LIC-SET-01", 30).
c) Zeichne das Sequenzdiagramm, das beim Ausführen dieser Entnahme entsteht. Zeige beide Beobachter mit ihren eigenen Folgeaufrufen und trage, wo möglich, die konkreten Werte ein. (10 Punkte)
Punkteverteilung (Vorschlag):
- 1 Punkt:
entnehmen("LIC-SET-01", 30)vom Lagerterminal mit Antwort am Ende. - 1 Punkt: Selbstaufruf
getBestand("LIC-SET-01")mit Rückgabe 48. - 1,5 Punkte:
opt-Fragment mit Bedingung ([neu < mindestbestand]oder[18 < 20]), das die gesamte Benachrichtigung umschließt. - 2 Punkte:
artikelKnapp("LIC-SET-01")erst andash, dann annb(Anmeldereihenfolge), jeweils mit Antwort, bevor der nächste Beobachter aufgerufen wird. - 1 Punkt: Rückruf
getBestand("LIC-SET-01")vondashanlagermit Rückgabe 18; dafür ein zweiter, verschachtelter Balken auflager. - 1 Punkt:
zeigeWarnung("LIC-SET-01", 18)als Selbstaufruf vondash. - 1 Punkt:
bestelle("LIC-SET-01", 20)vonnban den:Grosshandelmit RückgabeauftragNr. - 1,5 Punkte: Ausführungsbalken (
lagerwährend der ganzen Entnahme aktiv, Beobachter nur währendartikelKnapp).
Ein loop-Fragment ist hier nicht nötig, weil das Diagramm einen konkreten Durchlauf mit zwei bekannten Beobachtern zeigt (siehe Teilaufgabe d). Wer die Schleife zusätzlich als loop um beide Aufrufe zeichnet, erhält die vollen Punkte.
d) Eine Kollegin zeichnet die Benachrichtigung anders: ein loop-Fragment [für jeden b in beobachter] mit einer einzigen Lebenslinie b :LagerBeobachter, an die artikelKnapp(artikelNr) geht. Vergleiche ihre Darstellung mit Deiner aus c). Erläutere, was jede Darstellung zeigt und was nicht, und für welchen Zweck welche besser geeignet ist. (3 Punkte)
- Konkreter Ablauf wie in c): Er zeigt, was bei genau dieser Anmeldung wirklich passiert: Reihenfolge der Beobachter, der Rückruf
getBestanddes Dashboards, die Bestellung beim Großhandel, konkrete Werte. Er gilt aber nur für diese Konstellation; meldet sich ein dritter Beobachter an, stimmt das Diagramm nicht mehr (1 Punkt). - Schleife über das Interface: Sie zeigt die Struktur des Musters: Der Lagerbestand kennt nur
LagerBeobachterund ruft bei allen dieselbe Methode auf, egal wie viele es sind und welche Klasse dahintersteht (Polymorphie). Was die einzelnen Beobachter danach tun, bleibt unsichtbar. Es lässt sich bei Bedarf je Klasse in einem eigenen Diagramm zeigen und mitrefeinbinden (1 Punkt). - Zweck: Für die Dokumentation des Entwurfs (Wie funktioniert die Kopplung?) passt die Schleife über das Interface; für Tests, Fehlersuche oder das Nachvollziehen eines bestimmten Falls passt der konkrete Ablauf (1 Punkt).
e) Ein Praktikant hat für die Übergabe eines Fertigungsauftrags an die Rahmenwerk OWL GmbH folgendes Diagramm entworfen. Gewünscht ist dieser Ablauf:
- Sobald eine Bestellung bezahlt ist, erzeugt der Shop einen Fertigungsauftrag
fa(Konstruktor mit Bestellnummer und Konfiguration). - Der Shop fragt die Terminplanung mit
berechneLiefertermin(konfiguration)nach der Lieferzeit in Wochen und wartet auf das Ergebnis. - Beträgt die Lieferzeit höchstens 8 Wochen, übermittelt der Shop den Auftrag an das MES (Fertigungssteuerung) von Rahmenwerk OWL, ohne auf die Bearbeitung zu warten. Das MES meldet die Annahme später mit der Auftragsnummer des Partners zurück.
- Bei mehr als 8 Wochen informiert der Shop die Kundin oder den Kunden über den Mailserver.
Der Entwurf enthält vier Fehler. Benenne die Fehler und korrigiere das Diagramm. (8 Punkte)
| Nr. | Fehler | Korrektur |
|---|---|---|
| 1 | fa :Fertigungsauftrag steht oben, als gäbe es das Objekt schon vor dem Ablauf; die Erzeugung ist als synchrone Nachricht gezeichnet. |
Kopf der Lebenslinie auf Höhe der Erzeugung; new(bestellNr, konfiguration) als gestrichelter Pfeil mit offener Spitze. |
| 2 | Die Antwort der Terminplanung ist als durchgezogener Pfeil (wie ein neuer Aufruf) und nur mit dem Wert beschriftet. | Gestrichelte Antwort mit Methodenname, Argument und Rückgabewert: berechneLiefertermin(konfiguration): wochen. |
| 3 | Die Bedingungen [wochen < 8] und [wochen > 8] lassen genau 8 Wochen aus, obwohl dann übermittelt werden soll. |
[wochen <= 8] und [else] (oder [wochen > 8]). |
| 4 | Auf die asynchrone Nachricht uebermittle(fa) folgt eine Antwort; der Ausführungsbalken des MES suggeriert, dass der Shop wartet. |
Antworten gibt es nur auf synchrone Nachrichten. Die Rückmeldung des MES ist eine eigene asynchrone Nachricht, z. B. auftragAngenommen(auftragsNr). |
Punkteverteilung (Vorschlag): je Fehler 1 Punkt für das Benennen und 1 Punkt für die Korrektur. Wer statt Fehler 4 die Nachricht uebermittle synchron macht (Shop wartet auf die Auftragsnummer), erhält die Punkte nur mit Begründung, denn laut Beschreibung soll der Shop nicht warten.
Aufgabe 3.3: Einwilligung, Flurmonitore und Fahrzeugdaten in der Mitfahr-App (Profilkompetenz)
(ca. 35 min Bearbeitungszeit)
Du bist Auszubildende*r und arbeitest im FIA-Projektteam der Mitfahr-App „RatzFahrt“ des Ratz und Rübe Berufskollegs in Bielefeld mit. Die App vermittelt Fahrgemeinschaften zu den Berufsschultagen. Projektleiter Thomas Becker möchte die wichtigsten Abläufe für die Dokumentation als Sequenzdiagramme festhalten. Oksana Melnyk aus dem Projektteam unterstützt Dich.
a) Minderjährige dürfen RatzFahrt nur mit Einwilligung der Erziehungsberechtigten nutzen. Andrea Wolf, die Datenschutzbeauftragte der Schule, beschreibt den Ablauf am Beispiel von Aylin Kaya (17):
- Aylin registriert sich in der App. Die App teilt ihr sofort mit, dass ihr Konto bis zur Einwilligung gesperrt ist.
- Aylin bittet im Gespräch ihre Mutter um die Einwilligung. Die Mutter liest die Datenschutzhinweise, unterschreibt das Formular und gibt es Aylin zurück.
- Aylin legt das Formular in das Postfach von Frau Wolf im Sekretariat. Sie wartet dort nicht auf eine Reaktion.
- Frau Wolf trägt die Einwilligung über die Verwaltungsoberfläche in der App ein. Die App schaltet das Konto frei und bestätigt Frau Wolf die Speicherung.
- Anschließend erhält Aylin von der App eine Push-Nachricht, dass ihr Konto freigeschaltet ist.
Stelle den Ablauf in einem UML-Sequenzdiagramm dar. Verwende für die beteiligten Menschen und die App je eine Lebenslinie. Modelliere Gespräche und Bedienvorgänge, bei denen jemand auf das Ergebnis wartet, als synchrone Nachrichten mit Antwort, alles andere als asynchrone Nachrichten. Tätigkeiten, die eine Person oder die App allein ausführt, notierst Du als Selbstaufruf. (12 Punkte)
Punkteverteilung (Vorschlag):
- 2 Punkte: je 0,5 Punkte für die vier Lebenslinien mit sinnvollen Namen (Menschen gern als Strichmännchen, die App als Rechteck).
- 1,5 Punkte:
registrieren()synchron mit Antwort „gesperrt bis zur Einwilligung“. - 1,5 Punkte:
umEinwilligungBitten()synchron mit Antwort (Rückgabe des unterschriebenen Formulars). - 1 Punkt: Lesen und Unterschreiben als Selbstaufrufe der Mutter innerhalb ihres Ausführungsbalkens.
- 1,5 Punkte:
formularAbgeben(formular)asynchron (Aylin wartet nicht). - 1,5 Punkte:
einwilligungEintragen(aylin)synchron mit Antwort „gespeichert“. - 0,5 Punkte:
kontoFreischalten(aylin)als Selbstaufruf der App. - 1,5 Punkte:
sendePush(…)asynchron von der App an Aylin. - 1 Punkt: richtige zeitliche Reihenfolge.
Hinweis: Im Analyse-Diagramm dürfen die Nachrichten auch umgangssprachlich beschriftet sein („Einwilligung erbitten“, „Formular abgeben“). Entscheidend sind Richtung, Art und Reihenfolge der Nachrichten.
b) Die Flurmonitore zeigen offene Fahrtangebote und Gesuche anonym an. Auf jedem Monitor läuft ein kleiner Player, der seine Daten selbst abruft. Oksana hat die zentrale Methode bereits in Pseudocode geschrieben. Die Klasse MonitorPlayer hat diese Attribute und Methoden:
MonitorPlayer
- monitorId: Integer
- laeuft: Boolean
- fehler: Integer
- server: MonitorServer
- anzeige: Bildschirm
- ticketsystem: Ticketsystem
+ starte(): void
- formatiereAnonym(eintraege: Eintrag[]): String
- warte(sekunden: Integer): void
Die Methode starte() kannst Du in vier Pseudocode-Notationen anzeigen; sie sind im Artikel Algorithmen mit Pseudocode dokumentieren beschrieben.
Prozedur starte()
fehler := 0
solange laeuft = true
eintraege: Eintrag[] := server.holeEintraege(monitorId)
wenn eintraege = null dann
fehler := fehler + 1
anzeige.zeigeOffline()
wenn fehler >= 5 dann
ticketsystem.meldeStoerung(monitorId) // asynchron
verlasse Schleife
Ende wenn
sonst
fehler := 0
text: string := formatiereAnonym(eintraege)
anzeige.zeige(text)
Ende wenn
wenn uhrzeit() >= "17:00" dann
anzeige.setzeHelligkeit(40)
Ende wenn
warte(60)
Ende solange
Ende starte
Modelliere die Methode starte() als UML-Sequenzdiagramm „sd Flurmonitor aktualisieren“ mit den Lebenslinien player :MonitorPlayer, :MonitorServer, anzeige :Bildschirm und :Ticketsystem. Der Aufruf von starte() kommt von außerhalb des Diagramms. Die Zuweisungen an fehler und die Abfrage der Uhrzeit musst Du nicht als Nachrichten darstellen. (12 Punkte)
Punkteverteilung (Vorschlag):
- 0,5 Punkte:
starte()als gefundene Nachricht (von außerhalb, z. B. ausgefüllter Punkt oder Rahmenrand). Ob Du sie synchron (mit Antwort am Ende) oder asynchron zeichnest, hängt davon ab, wie der Player gestartet wird: Ruft ihn das Startprogramm direkt auf, wartet es; startet es ihn in einem eigenen Thread, wartet es nicht. Beides wird anerkannt. - 1,5 Punkte:
loop-Fragment mit Bedingung ([laeuft == wahr], gern mit dem Hinweis „alle 60 s“). - 1 Punkt:
holeEintraege(monitorId)mit Antworteintraege. - 1,5 Punkte:
alt-Fragment mit[eintraege == null]und[else]. - 1 Punkt:
zeigeOffline()mit Antwort. - 1,5 Punkte:
break-Fragment direkt im Schleifenrumpf nach demalt-Fragment mit der Bedingung[eintraege == null und fehler >= 5]: Wird es ausgeführt, entfällt der Rest des Schleifenrumpfs, und die Schleife endet. Einbreakinnerhalb desalt-Operanden würde nach UML nur diesen Operanden beenden, nicht die Schleife. - 1 Punkt:
meldeStoerung(monitorId)asynchron. - 1 Punkt:
formatiereAnonym(eintraege)als Selbstaufruf mit Rückgabewerttext. - 1 Punkt:
zeige(text)mit Antwort. - 1 Punkt:
opt-Fragment mit[uhrzeit >= 17:00]. - 0,5 Punkte:
setzeHelligkeit(40)imopt-Fragment. - 0,5 Punkte:
warte(60)als Selbstaufruf am Ende des Schleifenrumpfs.
Hinweise: Statt break darf die Schleifenbedingung [laeuft == wahr und fehler < 5] lauten; dann muss meldeStoerung in einem opt-Fragment stehen (volle Punktzahl). Ein alt-Fragment mit leerem [else]-Zweig statt opt ist ebenfalls richtig.
c) Andrea Wolf hat festgelegt, dass Kennzeichen und Farbe des Fahrzeugs nur Mitfahrende sehen dürfen, deren Buchung für das Angebot bestätigt ist. Alle anderen sehen nur den Fahrzeugtyp und die Zahl der freien Plätze. Oksana setzt das mit dem Stellvertreter-Muster (Proxy) um. Die App kennt nur die Schnittstelle FahrzeugAuskunft; dahinter steckt ein FahrzeugProxy, der das echte Fahrzeug verwaltet:
public interface FahrzeugAuskunft {
Fahrzeugdaten getDaten(int nutzerId);
}
public class FahrzeugProxy implements FahrzeugAuskunft {
private final Fahrzeug fahrzeug; // das echte Objekt, implementiert ebenfalls FahrzeugAuskunft
private final Buchungsliste buchungen;
private final int angebotId;
// Konstruktor ausgelassen
@Override
public Fahrzeugdaten getDaten(int nutzerId) {
if (buchungen.istBestaetigt(nutzerId, angebotId)) {
return fahrzeug.getDaten(nutzerId);
}
return fahrzeug.getOeffentlicheDaten();
}
}Zeichne das Sequenzdiagramm für einen Aufruf von getDaten(nutzerId) durch die App mit beiden möglichen Verläufen. Verwende die Lebenslinien :App, proxy :FahrzeugProxy, :Buchungsliste und fz :Fahrzeug. (7 Punkte)
Punkteverteilung (Vorschlag):
- 1 Punkt:
getDaten(nutzerId)von der App an den Proxy. - 1 Punkt:
istBestaetigt(nutzerId, angebotId)an die Buchungsliste mit Rückgabewert. - 1,5 Punkte:
alt-Fragment mit Bedingung (z. B.[ok == true]) und[else]. - 1 Punkt: Weiterleitung
getDaten(nutzerId)anfzmit Antwort im ersten Operanden. - 1 Punkt:
getOeffentlicheDaten()anfzmit Antwort im zweiten Operanden. - 1 Punkt: Antworten des Proxys an die App in beiden Operanden.
- 0,5 Punkte: Ausführungsbalken (Proxy während des gesamten Aufrufs aktiv).
Hinweis: Die Prüfung steht im Code direkt in der if-Bedingung. Ein Selbstaufruf des Proxys wäre hier falsch, weil der Proxy keine eigene Methode für die Prüfung aufruft.
d) Andrea Wolf verlangt zusätzlich, dass jeder Abruf der vollständigen Fahrzeugdaten protokolliert wird. Oksana hat die Änderung zuerst im Sequenzdiagramm entworfen:
Passe die Methode getDaten aus c) so an, dass sie dem Entwurf entspricht. Das Protokoll bietet die Methode vermerke(nutzerId, angebotId). Begründe, an welchem Merkmal des Diagramms Du erkennst, wie Du den Aufruf umsetzen musst. (4 Punkte)
@Override
public Fahrzeugdaten getDaten(int nutzerId) {
if (buchungen.istBestaetigt(nutzerId, angebotId)) {
Fahrzeugdaten daten = fahrzeug.getDaten(nutzerId);
CompletableFuture.runAsync(() -> protokoll.vermerke(nutzerId, angebotId));
return daten;
}
return fahrzeug.getOeffentlicheDaten();
}Punkteverteilung (Vorschlag):
- 1 Punkt: Ergebnis von
fahrzeug.getDaten(nutzerId)zwischenspeichern, weil der Vermerk laut Diagramm nach der Weiterleitung und vor der Antwort an die App kommt. - 1 Punkt: Vermerk nur im Zweig mit bestätigter Buchung; der
else-Zweig bleibt unverändert. - 2 Punkte: Begründung:
vermerkeist als asynchrone Nachricht gezeichnet (offene Pfeilspitze, keine Antwort). Der Proxy wartet also nicht auf das Protokoll, sondern antwortet sofort der App. Im Code geschieht das z. B. mitCompletableFuture.runAsync(…), über eine Warteschlange oder einen eigenen Thread. Ein einfacher Methodenaufrufprotokoll.vermerke(…)wäre in Java synchron und erhält nur 1 Punkt für die Umsetzung, wenn die Begründung den Unterschied nennt.
Das Attribut protokoll (Typ Zugriffsprotokoll) muss im Proxy ergänzt werden.
e) Im Teamgespräch schlägt jemand vor, auf den Proxy zu verzichten: Die App soll selbst prüfen, ob die Buchung bestätigt ist, und dann je nach Ergebnis getDaten oder getOeffentlicheDaten direkt am Fahrzeug aufrufen. Bewerte diesen Vorschlag. (3 Punkte)
Der Vorschlag ist abzulehnen (1 Punkt für eine begründete Entscheidung), zum Beispiel weil:
- die App auf dem Gerät der Nutzenden läuft und manipuliert werden kann; eine Zugriffsregel des Datenschutzes muss auf dem Server durchgesetzt werden (1 Punkt),
- jeder weitere Client (Flurmonitor, Webseite) die Prüfung und die Protokollierung wiederholen müsste; beim Proxy steht die Regel an genau einer Stelle, und der Client sieht weiter nur
FahrzeugAuskunft(1 Punkt).
Ein Vorteil des Vorschlags wäre nur ein Aufruf weniger; das wiegt die Nachteile nicht auf.
Links und weitere Informationen
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: “Übungsaufgaben zum UML-Sequenzdiagramm” von oer-informatik.de (H. Stein), Lizenz: CC BY 4.0. Der Artikel wurde unter https://oer-informatik.de/uml-sequenzdiagramm-uebungsaufgaben veröffentlicht, die Quelltexte sind in weiterverarbeitbarer Form verfügbar im Repository unter https://gitlab.com/oer-informatik/uml/uml-diagramme. Erstellt mit KI-Assistenz; von mir umfassend redaktionell überarbeitet, geprüft und freigegeben. Stand: 29.10.2026.
[Kommentare zum Artikel lesen, schreiben] / [Artikel teilen] / [gitlab-Issue zum Artikel schreiben]
