DDD beginnt nicht mit einem `domain`-Ordner
Eric Evans beschreibt DDD als Sammlung von Mustern und Definitionen für die Arbeit mit Domänenmodellen. Martin Fowler betont die Modellierung komplexer Domänen und eine gemeinsame Sprache zwischen Entwicklern und Domänenexperten. [1][2][4]
Eine Struktur wie `domain/application/infrastructure` macht eine Anwendung daher noch nicht zu DDD. Auch perfekt benannte Ordner können nur DTOs und prozedurale Logik enthalten. Strategisches DDD ist zudem ohne kanonische Schichtenstruktur möglich.
Strategisches und taktisches DDD arbeiten auf unterschiedlichen Ebenen
Strategisches DDD zerlegt größere Domänen in Subdomains und Bounded Contexts und beschreibt deren Beziehungen. Microsoft ordnet Domain Analysis genau diesem Schritt zu, während Fowler Bounded Context als zentrales strategisches Muster bezeichnet. [3][7]
Taktisches DDD arbeitet innerhalb eines konkreten Kontexts und umfasst unter anderem Entities, Value Objects, Aggregates und Domain Services. Microsoft trennt strategische Analyse ausdrücklich von taktischer Modellierung. [8]
Im Frontend ist es oft sinnvoll, mit strategischem Design zu beginnen und erst danach zu entscheiden, ob ein Kontext ein reichhaltiges taktisches Modell braucht.
Ein Bounded Context ist keine technische Schicht
Fowler beschreibt einen Bounded Context als Grenze, innerhalb derer ein Modell konsistent bleibt und Begriffe eindeutig sind. Dasselbe Konzept, etwa `Customer` oder `Product`, kann in verschiedenen Kontexten unterschiedliche Bedeutungen haben. [3]
Für Frontend-Architektur folgt daraus: `frontend`, `backend`, `React app`, `route` oder `micro-frontend` sind nicht automatisch Bounded Contexts. Kontextgrenzen entstehen aus Domänenmodell und Sprache, nicht aus Technologie. Frontend-DDD-Praktiker weisen auf dieselbe Gefahr hin. [15][16]
Wann DDD im Frontend sinnvoll ist
| Signal | Richtung | Warum |
|---|---|---|
| Viele wechselnde Geschäftsregeln | DDD | Ein Domain-Modell verhindert verstreute Regelimplementierung |
| Dieselben Begriffe bedeuten in Produktbereichen Unterschiedliches | DDD | Bounded Contexts erlauben mehrere konsistente Modelle |
| Mehrere Teams und Domänenexperten arbeiten zusammen | DDD | Ubiquitous Language reduziert Mehrdeutigkeit |
| Einfaches CRUD und Formulare | Einfachere Modularität | Der Aufwand taktischen DDD kann den Nutzen übersteigen |
| Frontend spiegelt hauptsächlich ein API | Einfachere Modularität | Wenig eigene Domänenlogik zu modellieren |
| Kleine Anwendung mit einer konsistenten Domäne | Einfachere Modularität | Zusätzliche Grenzen und Schichten bringen eventuell wenig Wert |
Das stärkste Signal sind komplexe und häufig wechselnde Geschäftsregeln auf Client-Seite: Konfiguratoren, mehrstufige Prozesse, Pricing, Berechtigungen, Zustandsübergänge, Workflows oder unterschiedliche Modelle derselben Begriffe in verschiedenen Produktbereichen.
DDD ist auch wertvoll, wenn mehrere Teams an einem großen Produkt arbeiten und dieselben Wörter in verschiedenen Bereichen etwas anderes bedeuten. Bounded Contexts wurden genau für mehrere kohärente Modelle und Teams entwickelt. [3]
DDD Crew empfiehlt, zuerst die Domäne zu verstehen, strategisch wichtige Subdomains zu identifizieren, danach Verantwortlichkeiten von Bounded Contexts zu definieren und erst anschließend das Modell zu codieren. [10]
Wann DDD zu Overengineering wird
Wenn das Frontend hauptsächlich Daten lädt, rendert, Formulare bearbeitet und einfache CRUD-Kommandos sendet, ohne nennenswerte Geschäftslogik im Client, löst vollständiges taktisches DDD meist kein echtes Problem.
Microsoft weist ausdrücklich darauf hin, dass für einen einfachen CRUD-Kontext ein anämisches Datenmodell ausreichen kann und komplexere DDD-Muster den Aufwand nicht immer rechtfertigen. Ein reichhaltigeres Modell lohnt sich eher bei vielen wechselnden Geschäftsregeln. [9]
Dasselbe Prinzip gilt im Frontend: Die Architektur sollte zur Domänenkomplexität passen und nicht zur technischen Ambition des Teams.
Ubiquitous Language sollte auch im UI-Code sichtbar sein
Ubiquitous Language ist eine gemeinsame, präzise Sprache von Entwicklern und Domänenexperten auf Basis des Modells. Fowler betont, dass sie mit wachsendem Domänenverständnis weiterentwickelt werden soll. [4]
Im Frontend sollten Namen von Use Cases, Aktionen, Typen, Modulen, Screens und Zuständen daher Geschäftsvokabular verwenden, sobald sie Domänenverhalten ausdrücken.
Wenn das Fachgebiet `approveApplication` sagt, der Code aber überall `setFlag2` oder `handleData` verwendet, verliert der Code seine Funktion als ausführbare Darstellung der Domänensprache.
Große Frontends nach Domänen statt nur nach Dateitypen organisieren
Fowler erklärt, dass `view/model/data` als oberste Struktur bei kleineren Systemen funktionieren kann. Mit wachsender Anwendung sollten Top-Level-Module jedoch häufig domänenorientiert werden und ihre eigenen internen Schichten enthalten. [5]
Die aktuelle Nx-Dokumentation zeigt eine ähnliche Richtung: Ordner können Domain-Ownership-Grenzen bilden, während Libraries innerhalb einer Domäne als `feature`, `ui`, `data-access` und `util` klassifiziert werden. [12]
Eine praktische Struktur kann daher `libs/orders/...`, `libs/billing/...` und `libs/identity/...` verwenden statt eines globalen Baums aus `components/`, `services/` und `models/`.
Präsentationsverhalten von Domänenverhalten trennen
Fowler beschreibt die Trennung von Präsentation, Domänenlogik und Datenzugriff als wirksame Modularisierung. UI-Code ist oft schwerer zu testen, weshalb Domänenlogik außerhalb der Präsentation Vorteile bringt. [5][6]
Eine Frontend-Komponente sollte primär rendern, UI-Ereignisse behandeln und Operationen delegieren. Regeln wie Stornierbarkeit einer Bestellung, Rabattberechnung oder gültige Zustandsübergänge sollten einen expliziten Ort außerhalb von JSX, Templates oder Komponentenklassen haben.
Präsentationslogik bleibt natürlich erlaubt. View-Validierung, Sichtbarkeit, lokaler Fokus oder Animation sind etwas anderes als Geschäftsregeln.
Praktische Schichten innerhalb eines Frontend-Kontexts
| Schicht | Verantwortung | Beispiele |
|---|---|---|
| presentation / ui | Rendering und UI-Verhalten | components, routes, view state |
| application | Koordination von Use Cases | commands, use cases, orchestration |
| domain | Domänenregeln, Begriffe und Invarianten | entities, value objects, policies |
| infrastructure / data-access | Technische Integrationen | HTTP, storage, SDKs, mappers |
DDD schreibt keine bestimmte Ordnerstruktur vor. Die Trennung in `presentation`, `application`, `domain` und `infrastructure` ist eine praktische Interpretation der Verantwortungsseparation, keine formale Vorgabe von Evans. [1][5]
Die Domain-Schicht kann frameworkunabhängige Regeln, Begriffe und Verhalten enthalten; application koordiniert Use Cases; infrastructure adaptiert HTTP, Storage und externe SDKs; presentation enthält Komponenten, Routing und reinen UI-State.
API-Modell und Frontend-Domain-Modell müssen nicht identisch sein
Ein Bounded Context kann ein eigenes Modell eines Begriffs besitzen, und verschiedene Kontexte können zwischen Repräsentationen abbilden. Fowler nennt `Customer` und `Product` als typische Beispiele für Begriffe mit kontextabhängiger Bedeutung. [3]
Ein Backend-DTO muss deshalb nicht direkt bis in jede Komponente reichen. Mapper oder Adapter können den Transportvertrag in das Modell des jeweiligen Frontend-Kontexts überführen.
Diese Grenze ist besonders wertvoll bei gemeinsam genutzten, historischen oder unabhängig evolvierenden APIs. Für einen trivialen CRUD-Endpunkt kann eine zusätzliche Mapping-Schicht überflüssig sein.
Entities, Value Objects und Aggregates selektiv einsetzen
DDD unterscheidet unter anderem Entities, Value Objects, Services und Aggregates. Fowler nennt sie als Teil des Evans-Vokabulars, Microsoft beschreibt Aggregate als taktisches Muster zur Wahrung der Modellkonsistenz. [2][8]
Ein Frontend sollte das Backend-Modell nicht 1:1 kopieren, nur um dieselben Klassen zu besitzen. Ein Value Object ist sinnvoll für `Money`, `DateRange` oder `Email`, wenn es echte Invarianten schützt. Ein Aggregate ist sinnvoll, wenn der Client tatsächlich Konsistenzregeln eines Modells gewährleisten muss.
Ist ein Typ nur Datenstruktur für eine Tabelle, ist ein einfacher TypeScript-Typ oft besser als Entity, Factory, Repository und Service Layer.
UI-State ist nicht dasselbe wie Domain-State
React behandelt State-Organisation als Designproblem und empfiehlt, redundanten oder duplizierten State zu vermeiden. Das ist nützliche technische Anleitung, aber Reducer, Stores oder Signals erzeugen noch kein Domain-Modell. [14]
State wie `isModalOpen`, aktiver Tab oder Scrollposition gehört zur Präsentation. Ein Bestell-Lebenszyklus, erlaubte Prozessübergänge oder Konfigurationsregeln können dagegen Teil des Domain-Modells sein.
Die Trennung verhindert globale Stores, die Serverdaten, Geschäftsverhalten und UI-Details unstrukturiert vermischen.
Grenzen müssen durchgesetzt und nicht nur dokumentiert werden
Nx erlaubt Project Tags und deklarative Dependency Constraints, etwa um Imports zwischen Scopes oder Library-Typen zu blockieren. `@nx/enforce-module-boundaries` kann Imports während des Lintings prüfen. [11]
Nx unterstützt mehrere Tag-Dimensionen, sodass `scope`, Library-Typ, Stabilität oder Client/Server-Aspekte getrennt modelliert werden können. [13]
Für DDD im Frontend können Architekturentscheidungen damit zu CI-Regeln werden: `billing` importiert keine `identity`-Interna, `ui` hängt nicht von `data-access` ab und `domain` bleibt frameworkunabhängig.
Frontend und Backend können eine Domäne teilen, ohne dass ihre Modelle identisch sind
Ein Bounded Context begrenzt Modell und Sprache und sollte daher nicht automatisch entlang der Netzwerkgrenze zwischen Browser und Server gezogen werden. Praktische Frontend-DDD-Quellen betonen, dass Kontexte technische Schichten übergreifen und gemeinsam von Frontend und Backend umgesetzt werden können. [15][16]
Die Client-Repräsentation darf sich trotzdem von der Server-Repräsentation unterscheiden, weil Interaktion, lokaler State und Präsentation andere Anforderungen stellen. Wichtig sind erhaltene Semantik und explizites Mapping statt Klassenduplikation.
Auch ein Micro-Frontend sollte nicht allein deshalb entstehen, weil ein Bounded Context existiert. Domain-Grenze und Deployable-Grenze sind verschiedene Entscheidungen.
Testbarkeit ist ein starkes Argument für isolierte Domänenlogik
Fowler nennt Testbarkeit als Vorteil der Trennung von Präsentation und Domäne. Logik außerhalb der UI kann ohne Rendering von Komponenten und ohne Abhängigkeit von Oberflächendetails getestet werden. [5][6]
Im Frontend ermöglicht das schnelle Tests von Regeln, Value Objects, Use Cases und Zustandsübergängen als normales TypeScript oder JavaScript. Komponententests bleiben wichtig, müssen aber nicht der einzige Ort für Geschäftsregeln sein.
Ein Warnsignal ist, wenn jede Änderung einer Geschäftsregel das Mounten einer kompletten Komponente und Mocks für Router, Store, HTTP und Browser-APIs erfordert.
DDD ohne Big Rewrite in ein bestehendes Frontend einführen
DDD Crew empfiehlt einen iterativen Prozess: Domäne verstehen, wichtige Subdomains erkennen, Verantwortlichkeiten von Bounded Contexts definieren und anschließend das Modell codieren. [10]
In einem bestehenden Frontend ist es sicherer, einen problematischen Geschäftsbereich auszuwählen, dessen Sprache und Grenze festzulegen, Präsentation von Regeln zu trennen, eine öffentliche Modul-API zu definieren und erst danach weitere Features zu migrieren.
Nicht die gesamte Anwendung muss umgebaut werden. DDD kann dort eingesetzt werden, wo Geschäftskomplexität den Modellierungsaufwand rechtfertigt, während einfache Bereiche schlanke Feature Modules bleiben.
- Mit einem Geschäftsproblem beginnen, nicht mit Ordnern.
- Begriffe, Regeln und mehrdeutige Konzepte identifizieren.
- Einen Bounded Context und seinen öffentlichen Vertrag definieren.
- Domänenregeln von Komponenten und Transport-DTOs trennen.
- Nur taktische Muster hinzufügen, die konkrete Komplexität lösen.
- Grenzen als Lint- oder CI-Regeln festhalten.
- Abhängigkeiten, Zyklen, Regressionen und Kosten projektübergreifender Änderungen messen.
- Einfache CRUD-Bereiche nicht nur für architektonische Symmetrie migrieren.

