Dieser Post setzt den dritten Teil fort. Das Alleinstellungsmerkmal von Bausteinsicht ist die bidirektionale Synchronisation: Änderungen im JSONC-Modell landen im draw.io-Diagramm — und Änderungen im Diagramm landen im Modell. Wie das funktioniert, erklärt dieser Post.
Das Problem: Zwei Repräsentationen, eine Wahrheit
Architekturdiagramme haben ein fundamentales Problem: entweder ist der Code die Quelle der Wahrheit und das Diagramm wird automatisch generiert (gut für Konsistenz, schlecht für visuelle Kontrolle), oder das Diagramm ist die Quelle und wird manuell gepflegt (gut für Aussehen, schlecht für Konsistenz).
Bausteinsicht löst das durch echte Bidirektionalität: Modell und Diagramm sind gleichwertig. Der Sync-Algorithmus erkennt, welche Seite sich geändert hat, und überträgt die Änderung zur anderen Seite.
Die .bausteinsicht-sync State-Datei
Die Grundlage des Sync-Algorithmus ist die .bausteinsicht-sync-Datei.
Sie enthält einen Snapshot des Zustands nach dem letzten erfolgreichen Sync:
{
"timestamp": "2025-06-11T09:00:00Z",
"model_hash": "sha256:a1b2c3...",
"drawio_hash": "sha256:d4e5f6...",
"elements": {
"onlineshop.frontend": {
"title": "Web Frontend",
"technology": "React",
"kind": "container"
}
},
"relationships": [
{ "from": "customer", "to": "onlineshop", "label": "uses", "kind": "uses" }
],
"rendered_elements": {
"onlineshop.frontend": true,
"onlineshop.api": true
}
}Diese State-Datei ist der Dreiwegs-Vergleich: sync vergleicht den aktuellen Zustand von Modell und Diagramm jeweils mit dem letzten bekannten Zustand — und erkennt dadurch auf welcher Seite sich etwas verändert hat.
Die .bausteinsicht-sync-Datei gehört ins Git-Repository neben architecture.jsonc. Sie ist der einzige Weg, wie Bausteinsicht Konflikte von legitimen Änderungen unterscheidet. |
Der Sync-Zyklus
bausteinsicht sync führt jeden Lauf als atomaren Fünf-Schritte-Zyklus aus:
1. DetectChanges → ChangeSet (was hat sich auf welcher Seite geändert?)
2. ResolveConflicts → conflicting fields aufgelöst (Modell gewinnt)
3. ApplyForward → Modell-Änderungen → draw.io übertragen
4. ApplyReverse → draw.io-Änderungen → Modell übertragen
5. SaveState → .bausteinsicht-sync aktualisierenDer gesamte Zyklus ist eine pure Funktion ohne Seiteneffekte — alle I/O findet davor und danach statt. Das macht den Algorithmus testbar und deterministisch.
Forward-Sync: Modell → draw.io
Der Forward-Sync übernimmt alle Modelländerungen ins Diagramm.
Neue Elemente
Neue Elemente erscheinen mit einem roten gestrichelten Rahmen als visueller Marker:
strokeColor=#FF0000;dashed=1;Der rote Rahmen signalisiert: „Dieses Element wurde gerade hinzugefügt — positioniere es."
Sobald das Element manuell verschoben wurde und sync erneut läuft, verschwindet der rote Rahmen.
Positionen werden beibehalten
Bausteinsicht merkt sich die gesetzten Positionen im Diagramm. Bei jedem Forward-Sync werden nur Titel, Beschreibung, Technologie und Stile aktualisiert — nicht die Position. Manuell arrangierte Layouts bleiben erhalten.
Tag-Stile werden angewendet
Wenn ein Element Tags hat, die in specification.tags mit style-Attributen definiert sind, werden diese Stile auf das draw.io-Element angewendet:
"specification": {
"tags": [
{ "id": "external", "style": { "fillColor": "#f5f5f5", "fontColor": "#666666" } }
]
},
"model": {
"paymentprovider": {
"kind": "system",
"title": "Payment Provider",
"tags": ["external"]
}
}Status-Badges
Elements mit status-Feld erhalten automatisch einen farbigen Badge im Diagramm:
| Status | Farbe | Bedeutung |
|---|---|---|
| Gelb | Geplant |
| Blau | Im Entwurf |
| Orange | In Entwicklung |
| Grün | Produktiv |
| Rot | Veraltet |
| Grau | Eingestellt |
Reverse-Sync: draw.io → Modell
Der Reverse-Sync überträgt Änderungen aus dem Diagramm zurück ins JSONC-Modell.
Was wird zurückgeschrieben?
Folgende Änderungen im Diagramm landen im Modell:
| draw.io Aktion | Effekt im Modell |
|---|---|
Element umbenennen (Doppelklick → neuer Titel) |
|
Technologie-Label ändern |
|
Neues Element in eine Container-Box ziehen | Neues Element wird als |
Element aus dem Diagramm löschen | Element wird aus dem Modell entfernt |
Verbindung zwischen zwei Elementen ziehen | Neue Relationship wird im |
Verbindungspfeil umdrehen |
|
Verbindung löschen | Relationship wird aus dem Modell entfernt |
Relationship Lifting
Ein wichtiges Konzept: Relationship Lifting. Wenn in draw.io eine Verbindung zwischen zwei Elementen gezogen wird, die in der Modell-Hierarchie auf verschiedenen Ebenen liegen, „hebt" Bausteinsicht die Verbindung automatisch auf die passende Hierarchieebene an.
Beispiel: Das Diagramm zeigt shop.frontend und shop.api (beide Container-Kinder von shop).
Man zieht eine Verbindung von frontend zu api — genau diese Beziehung landet im Modell:
"relationships": [
{ "from": "shop.frontend", "to": "shop.api", "label": "API calls" }
]Zieht man dagegen eine Verbindung von customer (Top-Level-Actor) zu shop.api (verschachtelter Container), wird sie korrekt als customer → shop.api angelegt — ohne manuelle Korrektur der IDs.
Konflikterkennung und -auflösung
Ein Konflikt entsteht wenn dasselbe Feld auf beiden Seiten gleichzeitig geändert wurde — also seit dem letzten sync.
Wann passiert das?
Typisches Szenario: Du änderst title im JSONC-Modell und jemand anderes ändert gleichzeitig denselben Titel direkt im draw.io-Diagramm — ohne vorher zu synchronisieren.
Auflösung: Modell gewinnt
Bausteinsicht verwendet eine einfache und vorhersehbare Strategie: das Modell gewinnt immer.
Conflict detected for element "shop.frontend":
Field: title
Model value: "Web App"
draw.io value: "Frontend Application"
Last sync: "Web Frontend"
→ Keeping model value. Edit draw.io manually if needed.Der Konflikt wird als Warning ausgegeben — die Änderung im Modell wird übernommen, die draw.io-Änderung wird verworfen.
Diese Strategie ist bewusst einfach gehalten. Das JSONC-Modell ist die primäre Quelle der Wahrheit — draw.io ist ein View darauf.
Praktisches Beispiel: Vollständiger Sync-Zyklus
Ausgangssituation
architecture.jsonc und architecture.drawio sind synchron (letzter Sync vor 10 Minuten).
Schritt 1: Modell ändern
Im JSONC einen neuen Container hinzufügen:
"model": {
"shop": {
"kind": "system", "title": "Online Shop",
"children": {
"frontend": { "kind": "container", "title": "Web Frontend" },
"api": { "kind": "container", "title": "REST API" },
"cache": { "kind": "container", "title": "Redis Cache", "technology": "Redis" }
}
}
}Schritt 2: Im Diagramm den API-Titel ändern
architecture.drawio öffnen, Doppelklick auf „REST API", umbenennen zu „REST API v2", speichern.
Schritt 3: Sync ausführen
bausteinsicht syncAusgabe:
Forward (model → draw.io): 1 added, 0 updated, 0 deleted Reverse (draw.io → model): 0 added, 1 updated, 0 deleted
Ergebnis:
draw.io: Redis Cache erscheint mit rotem gestricheltem Rahmen in der Container View
architecture.jsonc:"title": "REST API v2"für den API-Container
Beide Seiten wurden in einem einzigen sync-Durchlauf aktualisiert.
Watch-Modus: Kontinuierliche Synchronisation
bausteinsicht watch überwacht beide Dateien mit einem Filesystem-Watcher und triggert den Sync-Zyklus automatisch bei jeder Änderung.
Das Resultat: Man kann gleichzeitig im Editor das Modell bearbeiten und in draw.io das Diagramm anpassen — der Watch-Prozess hält alles in Echtzeit synchron.
Im Watch-Modus empfiehlt sich git commit nach jedem abgeschlossenen Änderungsschritt. Der .bausteinsicht-sync State zeigt im git diff genau welche Elemente geändert wurden — ein nützliches Protokoll. |
Beispiel-Modell
Das Beispiel für diesen Teil ist als ausführbare JSONC-Datei unter teil_4.jsonc abgelegt und zeigt den Zustand nach einem vollständigen Sync-Zyklus (inkl. Reverse-Sync: "REST API v2").
So sieht das Ergebnis in draw.io aus (bausteinsicht sync):
Das draw.io-File dafür findest du hier: teil_4.drawio
Generierte PNG-Dateien via bausteinsicht export --image-format png:

Generierte PlantUML-Diagramme via bausteinsicht export-diagram:
Was als nächstes kommt
Teil 5: Multi-View — mehrere Diagrammperspektiven aus einem Modell
Teil 8: Validation & Linting — Architekturregeln mit
bausteinsicht lintdurchsetzen
Offizielle Dokumentation: User Manual · Tutorial auf doctoolchain.org