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.jsonc

Ausgabe:

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-only

Schneller Check für CI: gibt es überhaupt Zyklen?

Zentralitätsmetriken anzeigen

bausteinsicht graph --model architecture.jsonc --centrality

Zeigt für jedes Element:

MetrikBedeutung

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.txt

JSON-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 verletzt

Beispiel-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:

context
graph

Generierte PlantUML-Diagramme via bausteinsicht export-diagram:

Diagram
Diagram

Was als nächstes kommt

Offizielle Dokumentation: User Manual · Tutorial auf doctoolchain.org