Dieser Post setzt den zwölften Teil fort.
Architekturmodelle wachsen — und mit ihnen die Komplexität der Abhängigkeiten.
bausteinsicht graph analysiert den Beziehungsgraphen und macht Probleme sichtbar, die im Diagramm schwer zu erkennen sind.
Was ist eine Graph-Analyse?
Das Architekturmodell ist mathematisch gesehen ein gerichteter Graph: Elemente sind Knoten, Beziehungen sind Kanten. Graph-Analyse-Algorithmen beantworten Fragen wie:
Gibt es Zyklen? (A → B → C → A)
Welche Elemente sind am stärksten vernetzt?
Ist der Graph ein DAG (Directed Acyclic Graph)?
Welche Komponenten bilden stark gekoppelte Cluster?
bausteinsicht graph
bausteinsicht graph --model architecture.jsoncAusgabe:
Relationship Graph Analysis =========================== Summary ------- Elements: 12 Relationships: 14 Max Dependency Depth: 4 Graph Type: DAG (acyclic) No cycles detected (valid DAG) Strongly Connected Components: 3 -------- Component 1 (CYCLE): [shop.api, authservice, shop.frontend] Centrality Metrics (top 5 by out-degree): Element | In-Degree | Out-Degree | Betweenness | Closeness ---------------------- | --------- | ---------- | ----------- | --------- shop.api | 2 | 5 | 8.40 | 0.67 authservice | 3 | 2 | 4.20 | 0.58 shop.frontend | 1 | 3 | 3.10 | 0.52
Nur Zyklen anzeigen
bausteinsicht graph --model architecture.jsonc --cycles-onlySchneller Check für CI: gibt es überhaupt Zyklen?
Zentralitätsmetriken anzeigen
bausteinsicht graph --model architecture.jsonc --centralityZeigt für jedes Element:
| Metrik | Bedeutung |
|---|---|
In-Degree | Anzahl eingehender Verbindungen — hohe Werte: viele Abhängige |
Out-Degree | Anzahl ausgehender Verbindungen — hohe Werte: viele Abhängigkeiten |
Betweenness | Wie oft liegt das Element auf dem kürzesten Pfad zwischen zwei anderen — hohe Werte: kritischer Engpass |
Closeness | Wie nahe ist das Element an allen anderen — hohe Werte: zentrale Position im Graph |
Report in Datei schreiben
bausteinsicht graph --model architecture.jsonc --centrality \
--output docs/graph-report.txtJSON-Ausgabe
bausteinsicht graph --model architecture.jsonc --format json{
"element_count": 12,
"relationship_count": 14,
"max_depth": 4,
"is_dag_valid": false,
"cycles": [
{
"length": 3,
"elements": ["shop.api", "authservice", "shop.frontend"]
}
],
"components": [
{
"id": 0,
"elements": ["shop.api", "authservice", "shop.frontend"],
"is_cycle": true
}
],
"centrality": [
{
"id": "shop.api",
"in_degree": 2,
"out_degree": 5,
"betweenness": 8.4,
"closeness": 0.67
}
]
}Zyklen in der Architektur
Ein Zyklus (A → B → C → A) in der Architektur bedeutet:
Deployment-Abhängigkeiten sind zirkulär — keines der beteiligten Systeme lässt sich unabhängig deployen
Testbarkeit leidet — Komponenten können nicht isoliert getestet werden
Versteckte Kopplung — die Systeme können nicht unabhängig weiterentwickelt werden
Zirkuläre Abhängigkeiten lassen sich auch als no-circular-dependency-Constraint definieren (→ Teil 8) und automatisch in der CI prüfen. bausteinsicht graph gibt zusätzlich die konkreten Zyklen aus — nützlich zur Analyse welche Elemente betroffen sind. |
Zyklus auflösen
Typische Strategien:
Dependency Inversion: gemeinsames Interface/Abstraktion einführen
Event-basierte Entkopplung: direkte Aufrufe durch Events ersetzen
Neue Schicht einziehen: gemeinsam genutzte Logik in ein separates Element auslagern
Zentralität als Architektur-Signal
Hohes Out-Degree + hohe Betweenness = potentieller Monolith oder God Object. Ein Element das viele andere kennt und auf vielen Pfaden liegt, ist ein Architekturrisiko:
Änderungen dort brechen viele andere Komponenten
Testen wird komplex
Deployment blockiert andere
| Die Zentralitätswerte lassen sich gut mit dem Overlay-Feature kombinieren (→ Teil 12): Betweenness-Werte als Metriken-JSON exportieren und als Heatmap visualisieren. |
CI-Integration
- name: Check for architectural cycles
run: |
bausteinsicht graph --model architecture.jsonc --cycles-only --format json \
| jq 'if .cycles | length > 0 then error("cycles detected") else . end'Alternativ über den no-circular-dependency-Constraint (einfacher, kein jq nötig):
- name: Lint architecture
run: bausteinsicht lint # schlägt fehl wenn NO-CYCLES-Constraint verletztBeispiel-Modell
Das Beispiel für diesen Teil (REST API als zentraler Hub mit hohem Out-Degree) liegt unter teil_13.jsonc.
So sieht das Ergebnis in draw.io aus (bausteinsicht sync):
Das draw.io-File dafür findest du hier: teil_13.drawio
Generierte PNG-Dateien via bausteinsicht export --image-format png:


Generierte PlantUML-Diagramme via bausteinsicht export-diagram:
Was als nächstes kommt
Teil 14: Auto-Layout — Diagramme automatisch hierarchisch anordnen
Teil 15: Templates — Eigene visuelle Stile für Element-Typen definieren
Offizielle Dokumentation: User Manual · Tutorial auf doctoolchain.org