Domain-driven Design (DDD) ist eine Herangehensweise an die Modellierung komplexer Software. Die Modellierung der Software wird dabei maßgeblich von den umzusetzenden Fachlichkeiten der Anwendungsdomäne beeinflusst. Der Begriff „Domain-driven Design“ wurde 2003 von Eric Evans in seinem gleichnamigen Buch geprägt.

Beschreibung Domain-driven Design ist nicht nur eine Technik oder Methode. Es ist vielmehr eine Denkweise und Priorisierung zur Steigerung der Produktivität von Softwareprojekten im Umfeld komplexer fachlicher Zusammenhänge.Definition von DDD lt. dddcommunity.org Domain-driven Design basiert auf folgenden zwei Annahmen: Der Schwerpunkt des Softwaredesigns liegt auf der Fachlichkeit und der Fachlogik. Der Entwurf komplexer fachlicher Zusammenhänge sollte auf einem Modell der Anwendungsdomäne, dem Domänenmodell, basieren.

Domain-driven Design ist an keinen bestimmten Softwareentwicklungsprozess gebunden, orientiert sich aber an agiler Softwareentwicklung. Insbesondere setzt es iterative Softwareentwicklung und eine enge Zusammenarbeit zwischen Entwicklern und Fachexperten voraus.

mini|450px|Schichtenarchitektur

Der Sinn jeder Software ist es, die Aufgabenstellungen einer bestimmten Anwendungsdomäne zu unterstützen. Um dies erfolgreich leisten zu können, muss die Software zur Fachlichkeit der Anwendungsdomäne passen, für die sie bestimmt ist. Domain-driven Design ermöglicht dies, indem die Software grundlegende Konzepte und Elemente der Anwendungsdomäne sowie deren Beziehungen modelliert.

Die Architektur ist geprägt durch die Existenz einer expliziten Geschäftslogikschicht. Diese Schicht soll die Domänen-Klassen von anderen Funktionen des Systems entkoppeln und möglichst leicht erkennbar machen. Verschiedene Architekturstile können eingesetzt werden, um die Geschäftslogikschicht einzubetten. Dazu zählen die Schichtenarchitektur und die hexagonale Architektur.hexagonale Architektur

Die Klassen des Domänenmodells enthalten im Domain-driven Design sowohl die Daten als auch die gesamte Funktionalität der umzusetzenden Fachlichkeit, also die gesamte Fachlogik. Reine Datenklassen nur mit Zugriffsmethoden aber ohne fachliche Funktionalität gelten als Code-Smell. Ein auf Datenklassen aufbauendes Domänenmodell wird anämisch genannt und gilt demzufolge als Antipattern, da es ein Domänenmodell ohne Fachlogik beschreibt.Anemic Domain Model

Domain-driven Design steht in Kontrast zum weniger komplexen Entwicklungsmuster Smart UI. Bei Anwendung von Smart UI wird die Anwendungslogik direkt in die Benutzeroberfläche integriert. Dadurch kann keine dezidierte Schicht für Anwendungslogik entstehen, die von verschiedenen Komponenten wieder verwendet werden kann.

Ubiquitäre Sprache Domain-driven Design basiert auf einer Reihe von Konzepten, welche bei der Modellierung – aber auch anderen Tätigkeiten der Softwareentwicklung – berücksichtigt werden sollten. Das Hauptaugenmerk hierbei fällt auf die Einführung einer ubiquitären (allgemein verwendeten, allgegenwärtigen, ubiquitous) Sprache, welche in allen Bereichen der Softwareerstellung verwendet werden sollte. Eine Sprache für die Beschreibung der Fachlichkeit, der Elemente des Domänenmodells, der Klassen und Methoden etc. Sie wird definiert als:

Domain-driven Design ist selbst unabhängig von Programmiersprachen, Werkzeugen und Frameworks. Dennoch gibt es eine Reihe von Werkzeugen, Frameworks, Leitfäden und Vorgehensmodellen, die Unterstützung für die Realisierung spezifischer DDD-Patterns anbieten oder die Herangehensweise von DDD organisieren.

Bestandteile des Domänenmodells mini|Domänenmodell

Domain-driven Design unterscheidet die folgenden Bestandteile des Domänenmodells: Entitäten (Entities, reference objects) Objekte des Modells, welche nicht durch ihre Eigenschaften, sondern durch ihre Identität definiert werden. Beispielsweise wird eine Person meist als Entität abgebildet. Eine Person bleibt somit dieselbe Person, wenn sich ihre Eigenschaften ändern; und sie unterscheidet sich von einer anderen Person, auch wenn diese dieselben Eigenschaften hat. Entitäten werden oft mit Hilfe von eindeutigen Identifikatoren modelliert. Wertobjekte (value objects) Objekte des Modelles, welche keine konzeptionelle Identität haben oder benötigen und somit allein durch ihre Eigenschaften definiert werden. Wertobjekte werden üblicherweise als unveränderliche Objekte (immutable objects) modelliert, damit sind sie wiederverwendbar (vgl. Flyweight) und verteilbar. Aggregate (aggregates) Aggregate sind Zusammenfassungen von Entitäten und Wertobjekten und deren Assoziationen untereinander zu einer gemeinsamen transaktionalen Einheit. Aggregate definieren genau eine Entität als einzigen Zugriff auf das gesamte Aggregat. Alle anderen Entitäten und Wertobjekte dürfen von außerhalb nicht statisch referenziert werden. Damit wird garantiert, dass alle Invarianten des Aggregats und der einzelnen Bestandteile des Aggregats sichergestellt werden können. Assoziationen (associations) Assoziationen sind, wie bei UML definiert, Beziehungen zwischen zwei oder mehr Objekten des Domänenmodells. Hier werden nicht nur statische, durch Referenzen definierte Beziehungen betrachtet, sondern auch dynamische Beziehungen, die beispielsweise erst durch die Abarbeitung von SQL-Abfragen entstehen. Serviceobjekte (services) Bei Domain-driven Design werden Funktionalitäten, welche ein wichtiges Konzept der Fachlichkeit darstellen und konzeptionell zu mehreren Objekten des Domänenmodells gehören, als eigenständige Serviceobjekte modelliert. Serviceobjekte sind üblicherweise zustandslose (engl. stateless) und daher wiederverwendbare Klassen ohne Assoziationen, mit Methoden, die den angebotenen Funktionalitäten entsprechen. Diese Methoden bekommen die Wertobjekte und Entitäten übergeben, die zur Abarbeitung der Funktionalität notwendig sind. Fachliche Ereignisse (domain events) Fachliche Ereignisse sind Objekte, welche komplexe, sich unter Umständen dynamisch ändernde, Aktionen des Domänenmodells beschreiben, die ein oder mehrere Aktionen oder Änderungen in den Fachobjekten bewirken. Fachliche Ereignisse ermöglichen auch die Modellierung verteilter Systeme. Die einzelnen Subsysteme kommunizieren ausschließlich über fachliche Ereignisse, damit werden sie stark entkoppelt und das gesamte System somit wartbarer und skalierbarer. Module (modules, packages) Module teilen das Domänenmodell in fachliche (nicht technische) Bestandteile. Sie sind gekennzeichnet durch starke innere Kohäsion und geringe Kopplung zwischen den Modulen.

Darüber hinaus kennt Domain-driven Design noch zwei weitere Bestandteile des Domänenmodells – Factories und Repositorys. Diese implementieren zwar selbst nicht Fachlichkeit, sind aber dennoch Bestandteil des Domänenmodells, da sie für den Lebenszyklus der Fachobjekte wichtige Funktionalität bereitstellen.

Fabriken (factories) Fabriken dienen dazu, die Erzeugung von Fachobjekten in spezielle Fabrik-Objekte auszulagern. Dies ist sinnvoll, wenn entweder die Erzeugung komplex ist (und beispielsweise Assoziationen benötigt, die das Fachobjekt selbst nicht mehr benötigt) oder die spezifische Erzeugung der Fachobjekte zur Laufzeit ausgetauscht werden können soll. Fabriken werden üblicherweise durch erzeugende Entwurfsmuster wie abstrakte Fabrik, Fabrikmethode oder Erbauer umgesetzt. Repositorys Repositorys abstrahieren die Persistierung und Suche von Fachobjekten. Mittels Repositorys werden die technische Infrastruktur sowie alle Zugriffsmechanismen auf diese von der Geschäftslogikschicht getrennt. Für alle Fachobjekte, welche über die Infrastruktur-Schicht geladen werden, wird eine Repository-Klasse bereitgestellt, welche die verwendeten Lade- und Suchtechnologien nach außen abkapselt. Die Repositorys selbst sind Teil des Domänenmodells und somit Teil der Geschäftslogikschicht. Sie greifen als einzige auf die Objekte der Infrastruktur-Schicht zu, welche meist mittels der Entwurfsmuster Data Access Objects, Query Objects oder Metadata Mapping Layers umgesetzt werden.

Die Namen der diesen Mustern entsprechenden Klassen der Geschäftslogikschicht sind Teile der ubiquitären Sprache und sollten entsprechend benannt werden. Eine Änderung des Namens eines Fachobjektes durch Refactoring entspricht somit einer Änderung der Fachlichkeit der Applikation.

Weitere Techniken Domain-driven Design beschreibt und empfiehlt eine Reihe weiterer Techniken und Herangehensweisen für die Umsetzung des Domänenmodells:

Architekturtechniken Evolvierende Struktur (evolving order) geht davon aus, dass große Strukturen im Domänenmodell idealerweise erst mit der Zeit entstehen beziehungsweise sich über die Zeit entwickeln. Große Strukturen sollten möglichst einfach und mit möglichst wenigen Ausnahmen umgesetzt sein. Systemmetapher (system metaphor) ist ein Konzept aus Extreme Programming, welche die Kommunikation zwischen allen Beteiligten erleichtert, indem es das System mittels einer Metapher, einer inhaltlich ähnlichen, für alle Seiten verständlichen Alltagsgeschichte beschreibt. Diese sollte möglichst gut passen und zur Stärkung der ubiquitären Sprache verwendet werden. Verantwortlichkeitsschichten (responsibility layers) ist die Aufteilung des Domänenmodells in Schichten gemäß Verantwortlichkeiten. Domain-driven Design schlägt folgende Schichten vor: Entscheidungsschicht, Regelschicht, Zusagen, Arbeitsabläufe, Potential. Wissenslevel (knowledge level) beschreibt das explizite Wissen über das Domänenmodell. Es ist in Situationen notwendig, wo die Abhängigkeiten und Rollen zwischen den Entitäten situationsbedingt variieren. Das Wissenslevel sollte diese Abhängigkeiten und Rollen von außen anpassbar enthalten, damit das Domänenmodell weiterhin konkret und ohne unnötige Abhängigkeiten bleiben kann. Erweiterungsframeworks (pluggable component framework) ist die Überlegung, verschiedene Systeme über ein Komponentenframework miteinander zu verbinden.

Designtechniken Intentionen beschreibende Schnittstellen (intention-revealing interfaces) bezeichnen Schnittstellen von Klassen und Komponenten, welche es den Entwicklern ermöglichen, ebendiese zu verwenden, ohne deren Sourcecode studieren zu müssen. Damit wird sowohl bei Verwendung als auch bei der Wartung dieser Klassen und Komponenten sichergestellt, dass diese gemäß deren Intentionen erfolgt. Nebeneffektfreie Funktionen (side-effect-free functions) sind Methoden, welche keinen Einfluss auf den Zustand eines Moduls haben. Diese sind einfacher zu testen und sollten somit bevorzugt werden. Sie sollten daher den Großteil der Applikationslogik enthalten. Den Zustand verändernde Methoden – sogenannte command Methoden – sollten von ihnen getrennt werden, möglichst einfach gehalten werden und keine Klassen des Domänenmodells retournieren. Assertions dienen im Domain-driven Design dazu, Nebeneffekte von aufgerufenen Methoden sichtbar zu machen, ohne deren Sourcecode studieren zu müssen. Diese – dem Design by contract nahe – Vorgangsweise führt dazu, dass Entwickler die Auswirkungen der verwendeten Methoden verstehen können, und somit erst Datenkapselung richtig eingesetzt werden kann. Eigenständige Klassen (standalone classes) sind Klassen, welche keine expliziten oder impliziten Abhängigkeiten zu anderen Klassen haben. Sie sind einfacher zu verstehen und sollten somit durch Eliminierung aller unnötigen Abhängigkeiten angestrebt werden. Konzeptionelle Konturen (conceptual contours) beschreibt die Konzepte, welche der Struktur eines Designs zugrunde liegen. Diese sollten durch sukzessive Refactorings an die stabilen Aspekte der Fachlichkeit angepasst werden. Damit steigt die Wahrscheinlichkeit, dass zukünftige Änderungen mit dem bestehenden Design leichter umgesetzt werden können.