Playbook

Wie funktioniert DDD in großen Systemen? (Wie Funktioniert Ddd In Grossen Systemen)

Wie skaliert DDD in großen Systemen? Ein Entscheidungsleitfaden zu Bounded Contexts, Context Mapping, Conway's Law, modularen Monolithen, Microservice-Grenzen…

Bounded contexts and context mapping for a large domain-driven system

Zuerst die falsche Frage loslassen

Am ersten Tag gab es ein einziges Book-Modell. Dann brauchte Sales einen Preis, Shipping ein Lieferfenster und Marketing Kampagnendaten. Sechs Monate später war dieselbe Klasse ein Objekt, das niemand mehr vollständig verstand. Das Problem war nicht das wachsende Buch, sondern unterschiedliche Geschäftsabsichten in einem Modell.

Ein großes System in Microservices zu teilen bedeutet nicht, DDD anzuwenden. Zuerst muss klar sein, welche Geschäftsbereiche unterschiedliche Sprache, Entscheidungen und Änderungsrhythmen haben. Andernfalls wird aus einem Monolithen nur ein teurerer Distributed Monolith.

Ein Modell → soll jeden Bedarf tragen → Model Tension

Sales Context → Preis und Kundenkredit
Shipping Context → Lieferadresse und Paket
Catalog Context → Titel, ISBN und Metadaten

Die Frage dieses Kapitels lautet: Wie können Modelle derselben Geschäftswelt sprechen, ohne einander zu verunreinigen?

Begriffe bei der ersten Verwendung

📦 Bounded Context
Eine explizite Grenze, in der Modell, Sprache und Regeln konsistent bleiben.

📦 Context Mapping
Die bewusste Definition der Daten-, Macht- und Vertragsbeziehung zwischen zwei Contexts.

📦 Upstream / Downstream
Der Anbieter eines Modells oder Vertrags ist Upstream; sein abhängiger Verbraucher Downstream.

📦 Anti-Corruption Layer (ACL)
Eine Übersetzungsschicht, die verhindert, dass ein externes Modell in die eigene Domain eindringt.

Conway's Law einfach gesagt: Software spiegelt mit der Zeit wider, wie eine Organisation kommuniziert. Ein Bounded Context ist kein Microservice; er kann zuerst als eigene Sprach-, Ownership- und Code-Grenze in einem modularen Monolithen leben.

Das große Bild

                         Unternehmen
                            │
       ┌────────────────────┼────────────────────┐
       │                    │                    │
    Catalog              Sales                Shipping
       │                    │                    │
     Book               Customer             Recipient
       │                    │                    │
       └──────── OrderConfirmed event ────────┘
                            │
                         Outbox
                            │
                          Broker
                            │
                     Delivery projection

Das Diagramm beschreibt keine vorgeschriebene Zahl physischer Services. Es zeigt, wo Sprache, Ownership und Veränderung leben.

Warum scheitert die Suche nach einem einzig wahren Modell?

Im Katalog ist ein Buch Titel, Autor und ISBN. Beim Verleihen ist es ein physisches Exemplar im Regal. Im Verkauf ist es SKU und Preis. Alles in einer Book-Klasse zu vereinen ist keine Wiederverwendung, sondern verbindet unterschiedliche Absichten. Dasselbe gilt für Customer: Sales braucht Kredit und Rechnungsdaten, Shipping Adresse und Lieferpräferenz.

❌ Unified Customer
creditLimit + invoiceAddress + deliveryWindow + marketingConsent + ...

✓ Sales.Customer
creditLimit + billingProfile

✓ Shipping.Recipient
deliveryAddress + deliveryWindow

Das Problem ist nicht die Zahl der Objekte. Ein Modell wird von unterschiedlichen Teams aus unterschiedlichen Gründen geändert. Mit k betroffenen Contexts sind die Änderungskosten mindestens O(k); Tests und Abstimmung wachsen schneller, wenn Abhängigkeiten zunehmen.

Bounded Context: Grenze zuerst in Geschäftssprache ziehen

Folgen Sie nicht technischen Layern oder Datenbanktabellen. Achten Sie auf diese Signale:

  1. Bedeutet dasselbe Wort in Meetings unterschiedliche Dinge?
  2. Vermehren sich Sonderfälle wie if (shipping) und if (sales)?
  3. Warten Teams für eine Änderung wiederholt aufeinander?
  4. Sind Owner, Erfolgsmaß oder Änderungsrhythmus eines Felds unklar?

Conway's Law ist hier eine Warnung: Systemgrenzen spiegeln oft die Kommunikation der Organisation. Wenn ein Team unabhängig entscheiden soll, sollten Modell- und Deployment-Grenze soweit praktikabel unabhängig sein. Das ist eine Ownership-Entscheidung, kein technisches Ziel.

Im Monolithen beginnen; Microservices als Ergebnis sehen

Ein modularer Monolith ist der risikoärmste Weg, einen Bounded Context zu validieren. Jeder Context besitzt Application/Domain/Infrastructure-Komponenten, Datenzugriff und expliziten Vertrag, ohne schon die Betriebskosten verteilter Aufrufe zu tragen.

Catalog module ── published contract ──► Sales module
Sales module   ── domain event ─────────► Shipping module

Wechseln Sie erst zu einem Microservice, wenn unabhängiges Scaling, Deployments, Sicherheitsgrenzen oder echte Teamautonomie nachgewiesen nötig sind. Bounded Context = Microservice ist die typische Gleichung hinter vorzeitiger Verteilung.

Context Mapping: Integration darf nicht zufällig sein

Die Beziehung zwischen Contexts bestimmen Machtbalance und Risiko der Model-Verunreinigung, nicht ein Endpoint.

Situation Strategie Warum
Legacy-Modell ist chaotisch ACL Verhindert, dass externe Sprache in die Domain dringt
Viele Consumers Open Host Service + Published Language Teilt versionierten Vertrag statt internem Modell
Kein Einfluss auf sauberen Upstream Conformist Vermeidet unnötige Übersetzung
Kleiner stabiler gemeinsamer Teil Shared Kernel, letzte Wahl Akzeptiert bewusst Koordinationskosten

Ein ACL kann CUST_TIER=7 eines Legacy-ERP in DeliveryEligibility innerhalb von Shipping übersetzen. Der ERP-Begriff betritt die Shipping-Domain nicht. Der zusätzliche Code hält den Einflussradius an einem Übersetzungspunkt.

Events, Outbox und Eventual Consistency

Ein Context sollte nicht die Datenbank eines anderen lesen. Bestätigt Sales eine Bestellung, kann es OrderConfirmed veröffentlichen; Shipping baut daraus seine Lieferansicht. Events verbieten synchrone Aufrufe nicht, reduzieren aber zeitliche Kopplung unabhängiger Abläufe.

Sales transaction
  → Order speichern
  → OrderConfirmed in Outbox schreiben
  → Commit

Relay → Broker → Shipping consumer → Delivery projection

Outbox ist nötig, weil Broker und Datenbank keine gemeinsame ACID Transaction haben. Existiert die Bestellung, existiert auch ein zu veröffentlichendes Event; der Relay kann retryen. Consumers müssen wegen normaler Duplikate idempotent bleiben. Eventual Consistency ist kein Fehler, sondern ein sichtbares Zeitfenster, das das Produkt akzeptieren muss.

Die Kosten dieses Designs

Context-Grenzen brauchen mehr Verträge, Observability, Versionierung und Teamdisziplin. Jeder Consumer ergänzt mehr als O(1) Code: Dashboards, Alarme, Retries, Ownership und Integrationstests folgen. Die beste Grenze erzeugt nicht die meisten Services, sondern senkt tatsächlich die Änderungskosten.

Zuordnungen, die falsche Sicherheit erzeugen

❌ Bounded Context = Microservice
✓ Zuerst ist es eine Sprach-, Ownership- und Modellgrenze.

❌ Ein Modell = Konsistenz
✓ Jeder Context kann sein eigenes konsistentes Modell besitzen.

❌ Shared Kernel = Wiederverwendung
✓ Es bedeutet gemeinsame Änderung und Koordinationskosten.

❌ REST Call = Integrationsstrategie
✓ Vertrag, Ownership und Fehlerverhalten bilden die Strategie.

❌ Eventual Consistency = Fehler
✓ Richtig gestaltet ist sie ein bewusster Trade-off unabhängiger Abläufe.

Checkliste für Strategic Design

  1. Wo beginnt dasselbe Wort unterschiedliche Dinge zu bedeuten?
  2. Hat jeder Context klare Sprache, Owner und Erfolgsmaß?
  3. Kann die Grenze zuerst im modularen Monolithen validiert werden?
  4. Dringt ein Upstream-Modell direkt in die Domain ein und braucht es ACL? In ERP → ACL → Shipping sollte etwa CUST_TIER=7 zu Shippings DeliveryEligibility werden.
  5. Ist der gemeinsame Vertrag versioniert und abwärtskompatibel?
  6. Was passiert, wenn eine Bestellung committed ist und der Broker ausfällt? Outbox schreibt Datensatz und Event in eine lokale Transaction; ein Relay retryt sicher, sobald der Broker zurück ist.
  7. Gibt es Produkt- und Betriebsentscheidungen für Lag, Duplikate und Replay?

Der Code wächst nicht nur um wenige Zeilen: Monitoring, Alarme, Retries und operative Ownership kommen hinzu. Codewachstum kann wie O(1) aussehen, doch Betriebskosten wachsen nicht linear. Messen Sie unabhängige Veränderbarkeit und Fehlerisolation, nicht die Service-Anzahl.

Was im Gedächtnis bleiben sollte

  1. Große Systeme haben kein einzig wahres Modell; jeder Bounded Context trägt seine eigene Geschäftsrealität.
  2. Ein Microservice ist nicht der Beginn einer strategischen Grenze, sondern kann ihr physisches Ergebnis sein.
  3. Context Mapping macht Vertrag, Macht und Model-Schutz sichtbar.
  4. Events und Outbox transportieren Veränderung sicher zwischen unabhängigen Contexts.

Eine Architekturgrenze beginnt nicht dort, wo Code liegt, sondern dort, wo eine Entscheidung in einer Sprache unter einem Owner getroffen wird.

Das letzte Kapitel betrachtet DDD in Production: Event Storming, Legacy-Migration, Anti-Corruption Layers und sicheren Wandel.

FAQ

Häufige Fragen

Was ist Bounded Context?

Eine explizite Grenze, in der Modell, Sprache und Regeln konsistent bleiben.

Was ist Context Mapping?

Die bewusste Definition der Daten-, Macht- und Vertragsbeziehung zwischen zwei Contexts.

Stimmt es, dass „Bounded Context = Microservice“?

Zuerst ist es eine Sprach-, Ownership- und Modellgrenze.

Was legt dieser Teil fest?

Die Frage dieses Kapitels lautet: Wie können Modelle derselben Geschäftswelt sprechen, ohne einander zu verunreinigen? Große Systeme haben kein einzig wahres Modell; jeder Bounded Context trägt seine eigene Geschäftsrealität. Am ersten Tag gab es ein einziges `Book`-Modell. Dann brauchte Sales einen Preis, Shipping ein Lieferfenster und Marketing Kampagnendaten. Sechs Monate später war dieselbe Klasse ein Objekt, das niemand mehr vollständig verstand. Das Problem war nicht das wachsende Buch, sondern unterschiedliche Geschäftsabsichten in einem Modell.

Gelernte Engineering-Prinzipien

  • Ein Bounded Context ist zuerst eine Grenze von Geschäftssprache und Ownership, nicht zwingend ein Microservice.
  • Context Mapping schützt die Domain bewusst vor externen Modellen.
  • Events und Outbox transportieren Veränderung sicher und beobachtbar zwischen unabhängigen Contexts.

Weiterlesen

Weiterlesen

Verwandte Beitrage

Verwandte Beitrage

Verwandte Beitrage

Paylaş