Playbook
DDD- Software nach dem Geschäft statt nach der Datenbank gestalten (Ddd Software Nach Dem Geschaeft Nicht Nach Der Datenbank Gestalten)
Was ist Domain-Driven Design? Ein Leitfaden zu den Grenzen datengetriebenen Designs, zur Kraft einer gemeinsamen Sprache und dazu, wann sich DDD wirklich lohnt.
Eine Domain, wachsende Entscheidungen
Behalten Sie in diesem Kapitel ein einzelnes E-Commerce-Bestellsystem im Blick. Im ersten Jahr ist Order ein einfacher Datensatz mit ausgewählten Produkten und Gesamtbetrag. CRUD reicht aus.
Jahr 1 → Bestellung erstellen, listen, ändern
Jahr 2 → Kampagnen und Rabatte
Jahr 3 → Retouren und Teilzahlungen
Jahr 4 → Raten, Bestandsreservierung und Versand
Jahr 5 → Fraud Control und länderspezifische Steuern
Jede neue Anforderung fügt Order nicht nur ein Feld, sondern eine Entscheidung hinzu. Eine Domain ist kein Softwareproblem, sondern das Geschäftsproblem, das gelöst werden soll: Bestellung sicher annehmen, bepreisen, bezahlen, retournieren und liefern.
Zuerst das Problem: Warum verliert Code die Sprache des Geschäfts?
Am Anfang sind Produkte oft einfach: Tabelle zeichnen, Endpoint bauen, Datensatz speichern. Das ist nicht falsch. Wenn jedoch Preisfindung, Retouren, Risiko, Lieferung und Berechtigungen wachsen, liegt der Wert eines Systems nicht mehr in seinen Tabellen, sondern in der Korrektheit seiner Entscheidungen.
Datenbank → Tabelle → CRUD → Service Layer → verstreute Geschäftsregeln
Geschäft → Gemeinsame Sprache → Domain Model → Code → sichtbare Entscheidungen
DDD lehnt Technologie nicht ab. Es verschiebt den Startpunkt des Designs: weg vom Schema, hin zur Bedeutung der Arbeit.
Begriffe bei der ersten Verwendung
📦 Domain
Der Geschäftsbereich, den ein System löst: etwa Bestellung, Kredit oder Versicherung.
📦 Domain Model
Die Repräsentation von Geschäftsregeln, Begriffen und Zustandsübergängen im Code.
📦 Ubiquitous Language
Dieselbe Bezeichnung für denselben Begriff bei Domain Experts, Produkt und Engineering.
📦 Core Domain
Der Geschäftsbereich, der das Produkt differenziert und die höchste Entscheidungskomplexität trägt.
PlaceOrder trägt eine fachliche Absicht, nicht nur einen technischen Aufruf. Bei Erfolg wird OrderPlaced zu einer Geschäftstatsache. Wenn Namen die Sprache der Arbeit nicht tragen, braucht jedes Feature eine neue Übersetzung.
Warum zerbricht dieselbe Bestellung über verschiedene Schichten hinweg?
Wenn Produkt „bevorzugter Kunde“ sagt und Engineering nur Status = 1 sieht, wurde ein Begriff in zwei Sprachen geteilt. Welcher Bedeutung folgt die nächste Kampagnenregel? Ubiquitous Language reduziert diese Mehrdeutigkeit, bevor Implementierung beginnt.
Auch order.Status = Paid ist für sich kein sicheres Verhalten:
order.Status = Paid
↓
Ist Zahlung wirklich bestätigt? → unbekannt
Ist Bestand reserviert? → unbekannt
Kann die Bestellung schon storniert sein? → unbekannt
order.ConfirmPayment(payment)
↓
prüft Zahlungsnachweis
wendet Geschäftsregeln an
lehnt ungültige Übergänge ab
Es geht nicht darum, Setter zu verbieten. Es geht darum, einer Geschäftsregel genau einen Owner zu geben. Auch Teamgröße verändert die Wirtschaftlichkeit: In einer kurzlebigen App mit ein oder zwei Personen gewinnt CRUD; in einem Produkt, das mehr als zehn Personen über Jahre weiterentwickeln, zahlen sich gemeinsame Sprache und explizite Ownership schneller aus.
Warum CRUD lange hervorragend funktioniert
Wenn ein Team klein ist, das Produkt klar begrenzt und Regeln wenige sind, ist Controller → Service → Repository → Database schnell und verständlich. Für einfache Admin-Screens, kurzlebige Prototypen und Datenerfassung ist diese Einfachheit ein echter Vorteil. DDD ist keine Ideologie gegen CRUD.
Der Bruch entsteht nicht durch mehr Zeilen in einer Tabelle. Er entsteht, wenn ein Modell unterschiedliche fachliche Absichten gleichzeitig darstellen muss. Ein Order dient plötzlich Promotion, Steuer, Rabatt, Retoure, Bestandsreservierung, Versand und Risikokontrolle.
Database-first
OrderRow → status = 2 → UpdateOrderStatus()
Business-first
Order → ConfirmPayment() → ReserveInventory() → StartFulfilment()
Der erste Ansatz verändert Daten; der zweite macht eine Geschäftsentscheidung sichtbar. Das Problem ist nicht kurze oder lange Codezeilen. Das Problem ist ein Modell, das verbirgt, warum das Geschäft handelt.
Ubiquitous Language: die Übersetzungssteuer entfernen
Wenn ein Domain Expert „bevorzugter Kunde“ sagt und der Code UserStatus = 1 enthält, besitzt das System zwei konkurrierende Realitäten. Diese Lücke erzeugt Missverständnisse, dupliziert Regeln über Services hinweg und macht Meetings zu wiederkehrenden Übersetzungssitzungen.
❌ InsertNewSchoolYear()
✓ OpenNewSchoolYear()
❌ UserStatus = 1
✓ customer.MarkAsPreferred()
❌ OrderRow
✓ LoanApplication / Order / Subscription
Eine gemeinsame Sprache ersetzt nicht jeden technischen Namen durch einen Geschäftsbegriff. Das Modell muss nur genau genug sein, um die Entscheidungen seines Kontexts zu erklären. Wie eine Karte die für eine Reise relevanten Dinge zeigt, repräsentiert ein Domain Model die Entscheidungen, die zählen.
Das anämische Modell: Objekte als Daten, Verhalten als Prozedur
Ein anämisches Domain Model entsteht, wenn Services auf Entities mit vielen Public Settern arbeiten. OrderService, PricingService, DiscountService und ShipmentService tragen dann schrittweise dieselben Regeln an unterschiedlichen Stellen. Das Objekt transportiert Daten, sein Verhalten lebt außerhalb.
❌ order.Status = Paid
❌ order.Total = -10
✓ order.ConfirmPayment(payment)
✓ order.ApplyDiscount(discount)
Ein reiches Modell bedeutet nicht, alles in eine Entity zu legen. Es bedeutet, Regeln, die nie verletzt werden dürfen, bei dem Verhalten zu halten, das sie schützen kann. Eine Bestellung darf etwa nicht versandt werden, bevor die Zahlung bestätigt ist. Diese Regel braucht genau einen Owner.
Kosten von DDD und der passende Kontext
DDD verlangt Analyse, Workshops zur gemeinsamen Sprache, bewusste Benennung und Teamdisziplin. Bei einfacher Datenerfassung zahlt sich diese Investition nicht aus. Die Entscheidung muss aus Domain-Komplexität und Veränderungsrate folgen, nicht aus technischem Enthusiasmus.
| Signal | CRUD ist meist besser | DDD ist eine sinnvolle Investition |
|---|---|---|
| Geschäftsregeln | Wenige und stabil | Mehrschichtig, kritisch, veränderlich |
| Produktlebensdauer | Kurzer Prototyp | Langlebiges Produkt |
| Kosten eines Fehlers | Gering | Finanziell oder operativ hoch |
| Sprache im Team | Eindeutig | Ein Begriff hat mehrere Bedeutungen |
Mit wachsender Regelanzahl steigen Änderungskosten selten linear. Wird eine Regel in k Services dupliziert, kostet eine Änderung mindestens O(k); interagieren Regeln, wachsen Testszenarien schneller. DDD entfernt diese Kosten nicht magisch, aber es macht Owner und Grenzen sichtbar.
Der erste Schritt: Sprache beobachten, nicht alles neu schreiben
- Wählen Sie den Workflow, in dem Fehler am teuersten sind.
- Notieren Sie Verben und Substantive der Domain Experts.
- Klären Sie widersprüchliche Begriffe innerhalb eines Kontexts.
- Modellieren Sie neues Verhalten als Geschäftsabsicht, nicht als Feld-Update.
- Bündeln Sie nur das Verhalten, das ungültige Zustände an dieser Grenze verhindert.
Datenbank, Framework und API sind dabei Adapter; sie besitzen nicht die Domain-Entscheidung.
Zuordnungen, die falsche Sicherheit erzeugen
❌ DDD = Layered Architecture
✓ DDD = Disziplin zum Modellieren eines komplexen Geschäftsbereichs
❌ DDD = viele Interfaces
✓ DDD = den richtigen Owner für Entscheidungen und Regeln finden
❌ Jedes Projekt braucht DDD
✓ Die Investition zahlt sich in komplexen, veränderlichen Domains aus
❌ Aggregate = Entity-Gruppe
✓ Aggregate = Transaction Boundary zum Schutz von Konsistenz
❌ Repository = eines für jede Tabelle
✓ Repositorys sind für fachlich sinnvolle Aggregate Roots da
Entscheidungs-Checkliste
- Welche verletzte Regel verursacht den teuersten Geschäftsfehler?
- Nutzen Domain Experts und Code dasselbe Wort für denselben Begriff?
- Ist ein Zustandswechsel
status = 2oder ein aussagekräftiges Geschäftsverhalten? - Hat eine Regel einen Owner oder ist sie über Services dupliziert?
- Ist diese Domain komplex genug, damit sich Analyseaufwand langfristig auszahlt?
Wenn diese Fragen keine klaren Antworten haben, beginnen Sie nicht mit Entities oder Frameworks. Klären Sie zuerst Problem, Sprache und Grenze.
Was im Gedächtnis bleiben sollte
- DDD ist nicht gegen Datenbanken; es akzeptiert, dass Geschäftsregeln wertvoller sind als gespeicherte Daten.
- Ubiquitous Language sind keine Meeting-Notizen, sondern der Vertrag für Code, APIs und Entscheidungen.
- Anämische Modelle verteilen Verhalten in Services und vergrößern das Risiko ungültiger Zustände.
- DDD passt nicht zu jedem Projekt; es zahlt sich aus, wenn Komplexität und Veränderung Kosten erzeugen.
Der Wert von Software liegt nicht darin, Daten zu speichern, sondern richtige Geschäftsentscheidungen über Zeit zu bewahren.
Im nächsten Kapitel übersetzen wir diese Denkweise in Code: Value Objects, Entities und Aggregate-Grenzen.
Vor den taktischen Patterns
Wo leben diese Geschäftsentscheidungen im Code? Taktische DDD-Patterns wie Value Objects, Entities und Aggregates beantworten diese Frage. Sie sind jedoch nicht der Startpunkt, sondern Werkzeuge, um die hier geklärte Sprache, Regeln und Grenzen zu schützen.
FAQ
Häufige Fragen
Was ist Domain?
Der Geschäftsbereich, den ein System löst: etwa Bestellung, Kredit oder Versicherung.
Was ist Domain Model?
Die Repräsentation von Geschäftsregeln, Begriffen und Zustandsübergängen im Code.
Stimmt es, dass „DDD = Layered Architecture“?
DDD = Disziplin zum Modellieren eines komplexen Geschäftsbereichs
Gelernte Engineering-Prinzipien
- Design sollte mit Geschäftsentscheidungen und gemeinsamer Sprache beginnen, nicht mit Tabellen.
- Verhalten gehört an die Domain-Grenze, an der es ungültige Zustände verhindern kann.
- Eine DDD-Investition muss durch Veränderungsrate, Fehlerkosten und Domain-Komplexität begründet sein.
Weiterlesen
Weiterlesen
Verwandte Beitrage
DDD im Code: Entity, Value Object und Aggregate
Wie funktionieren taktische DDD-Patterns? Value Objects, Entities, Aggregates, Domain Services, Application Services und Repository-Grenzen am Beispiel…
Verwandte Beitrage
Von CRUD (Create, Read, Update, Delete) zu CQRS (Command Query Responsibility Segregation): Das Problem ist nicht der Code, sondern das Modell
Was ist CQRS, worin liegt der Unterschied zu CRUD und wann sollte CQRS eingesetzt werden? Ein Leitfaden dazu, warum ein Modell in großen Systemen nicht…
Verwandte Beitrage
Von Schichten zu Features: Warum entstand Vertical Slice?
Warum verlangsamt eine Schichtenarchitektur Veränderung, wenn ein System wächst? Ein Architekturleitfaden zu Vertical Slice als Entscheidung über Feature…