Domain-driven Design

Blogeintrag:

Domain-driven Design

18 März 2017

Software ist selten Selbstzweck, sondern wird als nützliches Werkzeug in konkreten, abgegrenzten Aufgabenbereichen eingesetzt. Dieser spezifizierte Anwendungs- oder Problembereich wird als Anwenderdomäne bezeichnet. Diese Anwenderdomäne, auch Problemdomäne genannt, gibt durch ihre Begrenzung den Rahmen vor, in dem sich die durch eine Software zu bewältigenden Aufgaben befinden. Im Entwicklungsansatz des domain-driven Design wird versucht, einen Anwendungs- oder Fachbereich und die darin anfallenden Prozesse so akkurat wie möglich abzubilden, um diese Abbildung dann schließlich in ein Computerprogramm umsetzen zu können.


Vom Anwendungsbereich her denken – was ist domain-driven Design?

Das domain-driven Design, kurz DDD, ist ein Ansatz der Softwareentwicklung, der die Anwenderdomäne zum Orientierungspunkt des Funktionsdesigns einer Applikation macht. Der anvisierte Fachbereich, in dem die Software Anwendung finden soll, bestimmt in diesem Entwicklungskonzept maßgeblich deren Aufbau und Funktionalität. Ziel ist es, die Software so zu entwerfen, dass sie eine möglichst hohe Produktivität entfaltet. Dies darf nicht auf Benutzerfreundlichkeit oder Softwarestabilität reduziert oder damit gleichgesetzt werden (dies sind eher allgemeine Anforderungen an Software als Werkzeug). Zeil des DDD ist es, die Softwareentwicklung von Grund auf am Fachbereich zu orientieren.

Diese zuerst einmal trivial wirkende Herangehensweise stellt besondere Anforderungen an den Entwicklungsprozess einer Software. Dies betrifft sowohl die Entwickler, als auch die Architektur der Software. Im Einzelnen umfasst DDD neben der Kommunikation zwischen Softwareentwicklern und Domänenfachleuten auch die Entkopplung einer Anwenderschicht innerhalb des Modells der Software.

Die Anwenderschicht ist dabei eine der grundlegenden Komponenten innerhalb des Aufbaus der Software und für den Nutzer der eigentliche Grund diese überhaupt einzusetzen.

Der softwarearchitektonische Ansatz des DDD ist sowohl eine grundlegende Entwicklungseinstellung als auch ein Methodenbündel. Unter Domäne sind dabei alle Aspekte des Fachbereiches zu verstehen, dies bezieht sich auf die Fachlogik und Fachwissen eines Anwendungsfeldes. Fachlogik bezeichnet die Regeln für gültige Operationen und deren Verknüpfungen innerhalb des Fachbereiches. Das Domänenmodell stellt die Abstraktion dieser Aspekte dar. Dabei wird davon ausgegangen, dass der größte Teil der Komplexität der Softwareentwicklung in der Konstruktion des Domänenmodells liegt und nicht, wie eigentlich in der Softwareentwicklung zu erwarten, in der technischen Umsetzung.

Bekannt gemacht und propagiert wurde der Entwicklungsansatz des DDD durch den Autor Eric Evans in seinem Buch Domain-Driven Design: Tackling Complexity in the Heart of Software.


Modelle und Architekturen

Im Entwicklungsprozess hinreichend komplexer Applikationen wird mit Modellen gearbeitet. Ein Modell der Software ist vereinfacht als formalisiertes Ablaufdiagramm der Datenflüsse innerhalb des Programms und Interaktionen zwischen Software und Benutzer zu verstehen. Modelle stellen dabei immer einen, für den Anwendungsbereich relevanten Ausschnitt aus der Wirklichkeit dar, der zusätzlich so abgebildet wird, dass die jeweiligen extrahierten Sachverhalte durch Computer verarbeitbar sind. Das Modell einer Software stellt alle Interaktionen und Datenflüsse sowie die durch die Software verarbeiteten Datenstrukturen dar. Bekannt ist dieser Art der Modellbildung aus den Flussdiagrammen der Programmplanung. Diese werden so gestaltet, dass sie die Programmstruktur abbilden, die innerhalb der Software wirkt.

Unter die Modellbildung fallen aber auch die Architektur der Software. Die Architektur einer Software ist dabei dem Programmablaufplan übergeordnet und beschreibt die hierarchische Anordnung der funktionellen Komponenten innerhalb des Softwaresystems. Die Softwarearchitektur gibt somit die grundlegende Struktur der Software wieder und beschreibt die Merkmale ihrer Bestandteile sowie ihre Beziehungen zueinander. Die Definition der Komponenten erfolgt nach dem Prinzip der Zuständigkeiten, das heißt, jede dieser durch die Architektur unterschiedenen und beschriebenen Komponenten ist nur für eine einzige Aufgabe zuständig. Diese Komponenten können nun konzeptionell nach ihren Aufgaben und den Beziehungen zwischen ihnen, sogenannten Schichten (engl. Layers) zugeordnet werden. Verwandte oder stark zusammenhängende Elemente gehören einer gemeinsamen Schicht an. Dies kann im einfachsten Falle eine Eingabeschicht (in der sich alle Eingabeoperationen befinden), eine Verarbeitungsschicht (hier finden alle Datenverarbeitungsprozesse statt) und eine Ausgabe sein. Die Architektur einer Software beschreibt nicht deren detaillierte technische Umsetzung, sondern liefert ein abstraktes Organisationsmodell des Zusammenspiels einzelner Bausteine.

Dabei ist die Systemarchitektur, die sich in einem Diagramm darstellen lässt, zu unterscheiden von den bereits erwähnten Ablaufplan der Software. Während die Systemarchitektur funktionelle Aspekte einer Software beschreibt, also letztlich angibt, welche Interaktionen und Funktionen in der Anwendung vorkommen und ihre Wirkung festlegen, beschreibt ein Programmablaufdiagramm die Datenverarbeitungswege und Prozesse der Software. Die Softwarearchitektur beschreibt die existierenden Instanzen der Software, während das Ablaufdiagramm zeigt, was innerhalb dieser Instanzen abläuft.

Im Domain-driven Softwaredesign werden nun alle domänenspezifischen Aufgaben in einer einzigen Schicht zusammengefasst. Diese anwendungsspezifische Schicht enthält alle sich auf die Domäne beziehenden Komponenten, darunter fallen für diesen Bereich relevante Datenverarbeitungsprozesse wie selbstverständlich auch alle Routinen die für die Domänenlogik zuständig sind. Im DDD – Denken werden alle anderen Schichten gedanklich und konzeptionell um diese Schicht herum gruppiert.


Eine gemeinsame Sprache finden

Der fachspezifisch orientierte Ansatz der Softwareentwicklung zeichnet sich also dadurch aus, dass die Fachlogik der bedeutende Aspekt im Architekturmodell der Software ist. Deshalb kommen in der Entwicklung Fachleute und Softwareentwickler zusammen. Hierzu ist eine gemeinsame Sprache notwendig, um kommunizieren zu können. Diese Art der gemeinsamen Sprache dient als Schnittstelle zwischen Softwareentwicklern und Fachleuten, ist um den Fachbereich herum strukturiert und in allen Phasen und Bereichen der Softwareentwicklung gegenwärtig. Sie wird deshalb auch als ubiquitäre, das heißt, allgegenwärtige Sprache (ubiquitous Language) bezeichnet. Dabei handelt es sich nicht um eine Programmiersprache oder eine explizit informatische Modellsprache, sondern um eine Beschreibung der Beziehungen, Merkmale und Verarbeitungsprozesse des Fachbereiches in einer formalen, informatisch aufbereiteten Darstellung.

Mit Hilfe dieser ubiquitären Sprache wird das Domänenmodell konzipiert, das aus einer Zusammenstellung aller erwähnten Aspekte der Domäne besteht. Das Domänenmodell versucht, die Vorgänge des Fachbereiches adäquat abzubilden. Daraus resultiert in der Regel ein Geschäftsmodell. Ein wichtiges Element in der Konzeption des Domänenmodells ist seine semantische Anreicherung. Das Modell beinhaltet also nicht nur die formale Umsetzung einer Fachlogik, sondern zusätzlich noch Bedeutungszusammenhänge die in der Domäne auftreten. Nicht nur das „Wie“ des Vorgangs wird abgebildet, sondern auch das „Warum“. So entstehen nicht nur Abfolgen von verarbeitbaren Vorgängen, sondern diese werden durch ihre Bedeutung zu Ereignissen angereichert, die sich begründen und weiter analysieren lassen.

Diese semantische Anreicherung ist auch deshalb notwendig, da in komplexen Domänenvorgängen, wie beispielsweise einem Onlineeinkauf, unterschiedliche Merkmale von Objekten, im Falle des Einkaufs, eines Artikels, relevant werden können. So gibt es z. B. im Versandhandel verschiedene Abteilungen, die sich um die unterschiedlichen Phasen des Einkaufes, Präsentation des Artikels, Verpackung, Versand usw. kümmern und dem Begriff des Artikels damit auch jeweils anderes akzentuierte Bedeutungen zukommen lassen. Die Fachsprache spricht hier von Subdomains (Unterdomänen). Eine Domäne, ein Fachbereich wie der Versandhandel, lässt sich in verschiedene, ineinandergreifende Bereiche einteilen. Damit ein Artikel nicht mehrfach mit dem jeweiligen Bedeutungsschwerpunkt in jeder untergeordneten Domäne implementiert wird, müssen diese unterschiedlichen Bedeutungen komplett im Modellbegriff des Artikels enthalten sein.

Zuletzt ist es im ubiquitären Ansatz möglich, ein Datenobjekt mit einer Historie, also einer Serie von Änderungen zu versehen. Dies hilft auch, die Bedeutungsakzentuierungen, die ein Begriff in Vorgängen innerhalb der Domain erfährt, formal erfassen zu können.

Die ubiquitäre Sprache erfüllt damit zwei wichtige Funktionen. Sie macht es erstens möglich, dass sich Techniker und Domänenfachleute miteinander austauschen können und zweitens stellt sie sicher, dass die Inhalte von Vorgängen in den Domänen, wie Geschäftsprozesse, fachgerecht im Modell abgebildet werden.


Die Teile des Ganzen

Um ein domänenspezifisches Modell zu entwickeln, stehen fünf Grundbausteine zur Verfügung, die auf Objekten und Assoziationen beruhen. Objekte sind Bestandteile des Modells, die sich durch Identität, Eigenschaften oder einer Kombination aus beiden auszeichnen können.

Entitäten (Entities) sind Objekte, die nur über das Merkmal der Identität verfügen. Sie tragen keine Eigenschaften. Beispielsweise brauchen Nutzer eines Onlineangebotes nur durch ihre Identität, bestehend aus ihrem Benutzernamen und ihrem Passwort, voneinander unterschieden werden. Sie brauchen keine weiterführenden Eigenschaften zu haben. Entitäten haben auch eine Historie, die ihre Änderungen und ihren Durchlauf durch verschiedene Subdomains oder Anwendungsfelder wiedergibt. Dies kann z. B. eine Serie von Zugriffsrechten eines Benutzers auf einen Onlineservice betreffen. Entitäten sind auch die basalen „Träger“ der Domänenlogik. Um einen Vorgang innerhalb eines Fachbereiches durchführen zu können, muss eine Entität die Durchführungsregeln dafür bereitstellen. Entitäten stellen also die notwendigen Vorgänge zur Erledigung einer Aufgabe im Fachbereich zur Verfügung.

Das Komplement einer Entität im Domänenmodell ist das Werteobjekt (value object). Dieses Objekt hat keine Identität, dafür aber Eigenschaften. So hat beispielsweise die Funktion Wochentag, sofern sie nicht durch ein Datum ergänzt wird, keine Identität. Ein Montag kann irgendein Montag innerhalb der Zeitrechnung sein. Doch hat die Funktion Wochentag die Eigenschaften des jeweiligen Wochentages. Ebenso verhält es sich mit „morgens“ ohne weitere Bestimmung. Die Eigenschaft dieser Tageszeit, dass es Hell wird, ist ohne die Identität dieses „Objekts“ gegeben. Auch eine „Anzahl“ oder ein Währungsbetrag sind Beispiele für Wertobjekte. Sie sind nicht singulär „für sich selbst“ stehend, eine Anzahl oder ein Währungsbetrag beschreibt beliebige, dazu passende Objekte. Damit ist auch die wichtige Funktion der Value Objects genannt. Sie können den Identitäten Eigenschaften zuordnen. Ein zusammengesetztes Objekt mit Identität und Eigenschaften ist ein sogenanntes Aggregat.

Von hoher Bedeutung für das Konzept des Domänenmodells sind die Serviceobjekte (services). Sie fassen fachliche Funktionalitäten zusammen und operieren mit Identitäten, Wertobjekten oder Aggregaten davon. Sie stellen Anwendungsfälle wie Aufrufe einer durch eine Entität realisierte Funktion dar. Sie stellen gewissermaßen die notwendigen Objekte für den jeweiligen Anwendungsfall zusammen. Ein Anwendungsfall könne eine Bestellung in einem Onlineshop sein. Hier werden im Serviceobjekt „Bestellvorgang“ die Entitäten „Warenkorb“ und „Kunde“ mit jeweiligen damit verbundenen Wertobjekten aufgerufen.

Da es in einem Softwaremodell neben dem Domänenmodell noch weitere Schichten oder Instanzen gibt, deren Funktionen für die Ausführung eines Anwendungsfalls benötigt werden, muss eine Schnittstelle existieren, die zwischen Domänenschicht und anderen Schichten, wie beispielsweise einer Datenzugriffsschicht, vermittelt. Dies übernehmen die Repositories. Ein Repository lässt sich als ein Behälter vorstellen, der Inhalte wie Entities aufnehmen kann. Bei Repositories handelt es sich um ein Entwurfsmuster in der Softwarearchitektur. Entwurfsmuster sind bewährte Ansätze zur Lösung wiederkehrender Entwurfsprobleme innerhalb der Softwarearchitektur.

Kommunikation und Austausch findet nicht nur zwischen verschiedenen Schichten des Modells statt, sondern auch zwischen den Unterdomänen. Diesen Austausch übernehmen oft Domain Events, auch fachliche Ereignisse genannt. Domain Events registrieren die innerhalb der Domäne stattgefundenen Ereignisse und ermöglichen es, innerhalb der Domäne eine Reaktion darauf festzulegen. Durchläuft ein Artikel verschiedene Stationen des Verkaufsprozesses eines Onlineversandhandels, so kann jedes Ereignis, von der Betrachtung des Artikels bis zu seiner Auslieferung, in der Domäne registriert werden. Daraufhin können dem Kunden ähnliche Artikel zum Kauf vorgeschlagen werden. Die einzelnen Phasen in diesem Prozess werden zwischen den Subdomains als Domain Events weitergereicht.

Die Objekte des Domänenmodells können unterschiedlich zueinander in Beziehung stehen. Dies wird über die Assoziationen beschrieben. Diese Beziehungen können sowohl statisch, also feststehend zwischen zwei Objekten sein, aber auch dynamisch definiert sein, also wechselnde Objekte betreffen.


Fazit

Das domain-driven Design ist mehr eine Denk- und Entwicklungshaltung zur Softwaremodellierung als eine Sammlung von Methoden. Das zuerst einmal sehr simpel erscheinende Konzept erweist sich bei genauerer Beschäftigung als durchaus anspruchsvoll und zeigt oft frühzeitig Probleme auf, die ohne das Konzept der Domänenmodellierung erst im Entwicklungsvorgang auffallen würden. Die ubiquitäre Sprache ermöglicht es Fachleuten und IT-Entwicklern in einer einheitlichen und wohldefinierten Sprache sprechen zu können. Grundsätzlich ist die Haltung des DDD von der Zentrierung auf den Anwendungsbereich getragen. Dadurch findet auch eine gewisse Entkopplung von „allgemeinen“ Softwareeigenschaften statt. Dies hilft den Entwicklern umfangreicher Softwareprojekte, sich auf das Wesentliche zu konzentrieren. Dies ist aber nur möglich, wenn das DDD sinnvoll in eine allgemeine Systemarchitektur als eigene Domänenschicht eingebunden ist. Weiterhin wird so eine Portierung der Fachfunktionen einer Software auf Nachfolgeentwicklungen ermöglicht.

Bei Fragen können Sie gerne mit uns oder unseren Fachberatern Kontak aufnehmen.

Schreiben Sie uns an.