User Flows in Ihrer Software-Architektur dokumentieren
Der Bug-Report sah einfach aus: "Checkout schlägt intermittierend fehl."
Wir hatten wunderschöne Architekturdiagramme. C4-Diagramme, die jeden Service, jede Datenbank, jede Integration zeigten. Aber als wir versuchten, die Reise eines Benutzers von "zum Warenkorb hinzufügen" bis "Bestellung bestätigt" nachzuverfolgen, konnte sich niemand auf die genaue Sequenz einigen. Welche Services waren involviert? In welcher Reihenfolge? Wo fand die Bestandsprüfung statt — vor oder nach der Zahlung?
Drei Ingenieure hatten drei verschiedene mentale Modelle. Unsere statischen Architekturdiagramme zeigten die Struktur, aber nicht das Verhalten. Wir konnten die Kästen und Pfeile sehen, aber wir konnten nicht sehen, wie ein Benutzer sich tatsächlich durch das System bewegte.
Da wurde mir klar, dass wir User Flows brauchten.
Was User Flows wirklich sind
Ein User Flow dokumentiert die Reise, die ein Benutzer durch Ihr System nimmt, um ein Ziel zu erreichen. Nicht die statische Struktur (dafür sind C4-Diagramme da), sondern die dynamische Sequenz:
- Benutzer macht X
- System antwortet mit Y
- Benutzer wählt Z
- Und so weiter...
Klingt offensichtlich, aber es ist überraschend selten, dass dies gut dokumentiert ist. Die meisten Teams haben Architekturdiagramme (Systemstruktur) und API-Dokumentation (Endpoint-Details), aber nichts dazwischen, das zeigt, wie diese Teile aus der Benutzerperspektive zusammenarbeiten.
Die Lücke zwischen Struktur und Verhalten
Hier ist eine vereinfachte Version unseres C4-Container-Diagramms zu dieser Zeit:
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Web App │────▶│ API │────▶│ Database │
└─────────────┘ └──────┬──────┘ └─────────────┘
│
┌──────▼──────┐
│ Payment │
│ Service │
└──────┬──────┘
│
┌──────▼──────┐
│ Stripe │
└─────────────┘
Das sagt Ihnen, dass die Komponenten existieren und wie sie verbunden sind. Aber es beantwortet nicht: Wenn ein Benutzer auscheckt, was passiert zuerst? Validiert die API den Bestand, bevor sie die Zahlung aufruft? Was passiert, wenn die Zahlung erfolgreich ist, aber der Bestand nicht mehr verfügbar ist?
Diese Fragen erfordern das Verständnis des Flows, nicht nur der Struktur.
Anatomie eines nützlichen User Flows
Im Laufe der Zeit habe ich ein Template entwickelt, das gut für die Dokumentation von Flows funktioniert:
1. Zielformulierung
Beginnen Sie damit, was der Benutzer zu erreichen versucht:
Ziel: Kauf von Artikeln im Warenkorb abschließen
Das hält den Flow fokussiert. Wenn Sie sich dabei ertappen, mehrere Ziele zu dokumentieren, trennen Sie sie in mehrere Flows.
2. Vorbedingungen
Was muss wahr sein, bevor dieser Flow beginnt?
- Benutzer ist eingeloggt
- Warenkorb enthält mindestens einen Artikel
- Artikel im Warenkorb sind auf Lager (zum Zeitpunkt des Seitenladens)
Das verhindert Verwirrung über den Anfangszustand und klärt Annahmen.
3. Der Happy Path
Dokumentieren Sie zuerst den erwarteten Erfolgspfad:
1. Benutzer klickt auf "Checkout"-Button
→ Web App zeigt Lieferadress-Formular
2. Benutzer gibt Lieferadresse ein, klickt "Weiter"
→ API validiert Adressformat
→ API berechnet Versandoptionen
→ Web App zeigt Versandart-Auswahl
3. Benutzer wählt Versandart, klickt "Weiter"
→ API validiert Versandart
→ Web App zeigt Zahlungsformular
4. Benutzer gibt Zahlungsdetails ein, klickt "Bestellung aufgeben"
→ API erstellt ausstehende Bestellung in Datenbank
→ API ruft Payment Service mit Bestelldetails auf
→ Payment Service ruft Stripe auf, um Karte zu belasten
→ Payment Service gibt Erfolg an API zurück
→ API markiert Bestellung als bestätigt
→ API löst Bestätigungs-E-Mail aus
→ Web App zeigt Bestellbestätigungs-Seite
5. Benutzer sieht Bestätigung mit Bestellnummer
Beachten Sie einige Dinge:
- Jeder Schritt enthält, was der Benutzer tut UND wie das System antwortet
- Wir spezifizieren, welche Komponenten jede Aktion handhaben
- Das Detailniveau reicht aus, um den Flow zu verstehen, ohne Code zu lesen
4. Fehlerpfade und Randfälle
Der Happy Path ist nur der Anfang. Der eigentliche Wert kommt vom Dokumentieren dessen, was passiert, wenn etwas schief geht:
Zahlung abgelehnt:
In Schritt 4, wenn Stripe payment_declined zurückgibt:
→ Payment Service gibt Fehler an API zurück
→ API markiert Bestellung NICHT als bestätigt
→ API löscht ausstehende Bestellung
→ Web App zeigt "Zahlung abgelehnt"-Nachricht
→ Benutzer kann mit anderer Zahlungsmethode erneut versuchen
Bestand hat sich geändert:
In Schritt 4, vor dem Erstellen der ausstehenden Bestellung:
→ API überprüft erneut Bestandsverfügbarkeit
→ Wenn Artikel jetzt nicht verfügbar:
→ API gibt inventory_error zurück
→ Web App zeigt "Artikel nicht mehr verfügbar" mit Link zum Warenkorb
→ Benutzer muss Artikel entfernen und Checkout neu starten
Netzwerk-Timeout:
In Schritt 4, wenn Payment Service nicht innerhalb von 30 Sekunden antwortet:
→ API versucht NICHT erneut (um doppelte Belastungen zu verhindern)
→ API gibt timeout_error zurück
→ Web App zeigt "Bitte überprüfen Sie Ihre E-Mail, um Bestellstatus zu bestätigen"
→ Background-Job überprüft Zahlungsstatus nach 5 Minuten
→ Wenn Zahlung erfolgreich: Bestellung als bestätigt markieren, E-Mail senden
→ Wenn Zahlung fehlgeschlagen: ausstehende Bestellung bereinigen
Diese Fehlerpfade sind, wo sich Bugs verstecken. Sie sind auch, wo die meiste Dokumentation aufhört, deshalb verstecken sich dort Bugs.
5. Technische Anmerkungen
Fügen Sie relevanten technischen Kontext hinzu:
Technische Anmerkungen:
- Bestandsprüfung und Zahlung sind NICHT atomar. Race Condition
möglich aber akzeptabel angesichts geringer Wahrscheinlichkeit und
manuellem Lösungsprozess.
- Stripe-Webhook bietet Backup-Bestätigung, wenn API-Antwort verloren geht.
- Ausstehende Bestellungen älter als 1 Stunde werden durch geplanten Job
bereinigt.
Flows mit Architektur verbinden
Hier wird es mächtig: User Flows mit Ihren C4-Diagrammen verknüpfen.
In Archyl können wir annotieren, welche Komponenten an jedem Schritt eines Flows beteiligt sind. Das erzeugt bidirektionale Nachverfolgbarkeit:
- Schauen Sie sich einen Flow an? Sehen Sie, welche Komponenten er berührt.
- Schauen Sie sich eine Komponente an? Sehen Sie, welche Flows durch sie gehen.
Als dieser Checkout-Bug kam, hätten wir:
- Den Checkout-Flow öffnen können
- Genau sehen, welche Services involviert waren
- Bis zum spezifischen fehlgeschlagenen Schritt zurückverfolgen
- Die Fehlerbehandlung an diesem Punkt verstehen
Stattdessen haben wir zwei Tage damit verbracht, wieder zu entdecken, wie unser eigenes System funktionierte.
Verschiedene Arten von Flows
Nicht alle Flows sind gleich. Wir kategorisieren sie:
User Flows
Benutzerinitiierte Sequenzen von der UI:
- Checkout-Flow
- Registrierungs-Flow
- Passwort-Zurücksetzungs-Flow
- Profil-Aktualisierungs-Flow
Diese beginnen mit einer Benutzeraktion und enden mit einem sichtbaren Ergebnis.
System Flows
Maschineninitiierte Sequenzen:
- Nächtlicher Abstimmungs-Job
- Webhook-Verarbeitung
- Event-Driven-Kaskaden
- Geplante Benachrichtigungen
Diese sind genauso wichtig, aber oft weniger dokumentiert, weil es keine UI zu sehen gibt.
Integrations-Flows
System-übergreifende Sequenzen:
- Drittanbieter-Bestellimport
- Zahlungsabwicklungs-Batches
- Datensynchronisation mit Partnern
Diese involvieren typischerweise Systeme außerhalb Ihrer Kontrolle und haben mehr potenzielle Fehlermodi.
Wie wir jetzt Flows dokumentieren
Nach diesem Checkout-Debugging-Fiasko haben wir einen Prozess etabliert:
Jedes größere Feature hat einen Flow
Wenn wir ein neues Feature bauen, dokumentieren wir den Flow, bevor wir Code schreiben. Das dient als Design-Dokument und bleibt als Dokumentation bestehen.
Das Format ist einfaches Markdown:
# Feature: Benutzer-Bewertungen
## Ziel
Benutzer gibt eine Bewertung für ein gekauftes Produkt ab
## Vorbedingungen
- Benutzer ist eingeloggt
- Benutzer hat das Produkt gekauft
- Produkt erlaubt Bewertungen
## Flow
1. Benutzer klickt "Bewertung schreiben" auf Produktseite
...
## Fehlerbehandlung
...
## Beteiligte Komponenten
- Web App
- API Gateway
- Review Service
- Product Service
- Notification Service
## Verwandte ADRs
- ADR-0023: Bewertungs-Moderationsstrategie
Flow-Review in PRs
Wenn ein PR einen dokumentierten Flow ändert, erfordern wir, dass die Flow-Dokumentation aktualisiert wird. PR-Templates enthalten: "Ändert diese Änderung irgendwelche User Flows? Wenn ja, aktualisieren Sie die Flow-Docs."
Vierteljährliches Flow-Audit
Jedes Quartal gehen wir kritische Flows als Team durch:
- Flow-Dokumentation öffnen
- Durch den tatsächlichen Code/System verfolgen
- Diskrepanzen identifizieren
- Dokumentation aktualisieren oder Bugs beheben
Das klingt wie Overhead, aber es hat echte Probleme gefunden. Zweimal haben wir entdeckt, dass Code-Änderungen dokumentiertes Verhalten gebrochen hatten, ohne dass jemand es bemerkte.
Häufige Fehler
Fehler 1: Zu viele Details
Ein Flow-Dokument sollte sich nicht wie Code lesen. Wenn Sie einzelne Datenbankabfragen dokumentieren, sind Sie auf dem falschen Level. Fokussieren Sie sich auf benutzersichtbare Schritte und Service-Level-Interaktionen.
Fehler 2: Nur Happy Paths dokumentieren
Der Happy Path ist einfach. Die Fehlerpfade sind, wo Bugs leben. Zwingen Sie sich zu antworten: "Was passiert, wenn dieser Schritt fehlschlägt?"
Fehler 3: Nach Änderungen nicht aktualisieren
Ein dokumentierter Flow, der nicht mit der Realität übereinstimmt, ist schlimmer als keine Dokumentation. Er erzeugt falsches Vertrauen und führt zu falschen Annahmen beim Debugging.
Fehler 4: Flows als statisch behandeln
User Flows entwickeln sich. Neue Features fügen Schritte hinzu. Optimierungen entfernen Schritte. A/B-Tests ändern Verhalten. Behandeln Sie Flows als lebende Dokumente, nicht als einmalige Artefakte.
Tools und Formate
Sie brauchen keine speziellen Tools für Flow-Dokumentation. Markdown in Ihrem Repository funktioniert gut. Was zählt, ist Konsistenz und Auffindbarkeit.
Allerdings können visuelle Flow-Diagramme für komplexe Sequenzen helfen. Tools wie Mermaid ermöglichen es, Diagramme als Code zu schreiben:
sequenceDiagram
participant U as Benutzer
participant W as Web App
participant A as API
participant P as Payment Service
participant S as Stripe
U->>W: Klick "Bestellung aufgeben"
W->>A: POST /orders
A->>A: Ausstehende Bestellung erstellen
A->>P: Zahlung verarbeiten
P->>S: Karte belasten
S-->>P: Erfolg
P-->>A: Zahlung bestätigt
A->>A: Bestellung als bestätigt markieren
A-->>W: Bestelldetails
W-->>U: Bestätigungsseite
Der Schlüssel ist Versionskontrolle. Flow-Diagramme in Figma oder Lucidchart neigen dazu, von der Realität abzuweichen, weil sie vom Entwicklungsprozess getrennt sind.
Fazit
Statische Architekturdiagramme sagen Ihnen, woraus Ihr System besteht. User Flows sagen Ihnen, wie es sich verhält. Sie brauchen beides.
Das nächste Mal, wenn Sie ein komplexes Problem über mehrere Services debuggen, fragen Sie sich: "Haben wir einen dokumentierten Flow dafür?" Wenn die Antwort nein ist, werden Sie Stunden damit verbringen zu rekonstruieren, wie die Teile zusammenpassen — Stunden, die mit einem einfachen Dokument hätten gespart werden können.
Beginnen Sie mit Ihrem kritischsten Flow. Für die meisten Systeme ist das wahrscheinlich Authentifizierung oder der Haupt-Konversionspfad (Checkout, Registrierung, Core-Aktion). Dokumentieren Sie den Happy Path, dann zwingen Sie sich, mindestens drei Fehlerfälle zu dokumentieren.
Ihr zukünftiges Ich — das um 2 Uhr morgens panisch debuggt — wird es Ihnen danken.
Mehr über Architekturdokumentation: Einführung in das C4-Modell | Architecture Decision Records | Warum Dokumentation wichtig ist