Vielgescholten und selten genutzt: Domain-Driven Design und modellgetriebene Softwareentwicklung

6. März 2013

div class=”articleAbstract”>

Enterprise-Softwareprojekte sind häufig komplex, bestehen aus mehreren Schichten und/oder Komponenten und müssen über einen längeren Zeitraum hinweg gewartet, angepasst oder erweitert werden. Um trotz dieser Komplexität die Übersicht zu behalten, die Architektur über mehrere Granularitätsstufen hinweg zu entwickeln und Änderungen systematisch zu planen, können Softwaremodelle gute Dienste leisten. Dies gilt nicht nur für neu zu entwickelnde Softwaresysteme, sondern auch für die Weiterentwicklung bereits bestehender. Als Standardsprache für die Modellierung objektorientierter Softwaresysteme hat sich UML durchgesetzt, allerdings kann hierfür je nach Anforderung auch jede andere Modellierungssprache verwendet werden.

Ein modellgetriebener Ansatz ist der des Domain-Driven Designs (DDD), bei dem das sogenannte Domain Model im Mittelpunkt steht. Dies konzentriert sich vorrangig auf die Abbildung komplexer Fachlogik auf der Grundlage bestehender Fachanforderungen. Fachlogik wird zusammen mit den benötigten Daten in Entities gekapselt und verlässt den Kern der Anwendung nicht.
In der Praxis werden allerdings zunehmend Softwarearchitekturen eingesetzt, bei denen Fachlogik ausschließlich auf separaten Servicelayern gehalten und Objekte zu reinen Datencontainern degradiert werden. Dieser Ansatz wird auch als anämisches Domain Model [3] bezeichnet.

In diesem Beitrag werde ich zunächst auf die Grundlagen des Domain-Driven Design eingehen. Im Zuge dessen werde ich bestehende Vorurteile analysieren und versuchen, Missverständnisse rund um die Verwendung von Domain Models auszuräumen.

Hinweis: Ich konzentriere mich hier vorwiegend auf die Entwicklung von Softwaresystemen, bei denen komplexe und schnell veränderliche Fachanforderungen abgebildet werden müssen. Dies ist in Enterprise-Softwareprojekten häufig der Fall. Allerdings ist das Domain Model nicht das einzige Mittel der Wahl. Es ist z. B. abzugrenzen gegen das Smart UI Pattern [1], das einen daten- und UI-zentrischen Ansatz verfolgt. Die im Projekt tatsächlich verwendeten Architekturtypen sollten sich stets nach den Fachanforderungen und dem Kontext richten, in dem sie zum Einsatz kommen. Ein “One Architecture Fits All”-Ansatz ist weder angebracht noch wird er in diesem Beitrag propagiert.

Modellgetrieben und Domain-Driven – Was heißt das?

Modellgetriebene Softwareentwicklung (MDD) und Domain-Driven Design (DDD) verwende ich hier bewusst in einem Satz, da sie untrennbar miteinander verbunden sind. Während MDD den Fokus auf die automatisierte Generierung von Code aus formalen Modellen setzt, geht DDD einen Schritt weiter. Es ist eine Technik und Denkweise, die sich auf die Fachlogik einer Anwendung konzentriert und hierfür ein Modell als gemeinsame, allumfassende Sprache im Entwicklungsprozess einsetzt. Sie verwendet als zentrale Architektur das Domain Model. Beide Ansätze lassen sich deshalb sehr gut miteinander verbinden. DDD wurde durch Eric Evans [1] in seinem Buch ausführlich beschrieben. Er definiert es wie folgt:

Every software program relates to some activity or interest of its user. That subject area to which the user applies the program is the domain. […] A domain model is a rigorously organized and selective abstraction of [the domain expert’s] knowledge. [1]

DDD erfordert also, dass Entwickler Zugang zu Experten des Fachbereichs und/oder deren Wissen haben und Designentscheidungen auf der Grundlage dieses Wissens und in Kombination mit gängigen Enterprise Design Patterns fällen. Für diesen Zweck definiert DDD zusätzlich zum Domain Model eine Reihe von Bausteinen, die im Wesentlichen der Abstraktion und Abgrenzung des Modells nach außen dienen [1].

Eine mehrschichtige Architektur isoliert das Domain Model, das auf dem Domain Layer, dem Herzen des Systems, angesiedelt ist (siehe Abbildung 1 unten). Daneben existieren mindestens drei weitere Schichten, nämlich

  1. Der Infrastructure Layer, der technische Funktionalität für die Kommunikation der Schichten untereinander bereitstellt, z. B. für das Persistieren von Entities, das Versenden von Nachrichten, und so weiter.
  2. Der Application Layer, der externen Nutzern den Zugriff auf die im Domain Model gekapselte Fachfunktionalität bereitstellt. Diese Schicht enthält selbst keine Businesslogik, sondern dient lediglich der Delegation und Koordination von Aufgaben an den darunter liegenden Domain Layer.
  3. Und schließlich der Presentation Layer, der Nutzern Informationen anzeigt und deren Anweisungen entgegennimmt.

Zentrale Artefakte des Domain Models sind ferner

  • Entities, d. h. über ihren gesamten Lebenszyklus eindeutig identifizierbare Objekte [1], die sowohl Daten als auch Fachlogik enthalten [2]. Sie repräsentieren modellierte Fachaspekte und sollten primär auf der Grundlage konkreter Fachlogik erstellt werden.
  • Dem gegenüber stehen sogenannte Value Objects, die keine Identität, sondern lediglich beschreibende Funktion haben.
  • In der Regel soll Fachlogik nur in dazugehörigen Entitäten gekapselt werden. Es gibt jedoch Fälle, in denen Logik nicht eindeutig einer Entität zugeordnet werden kann; dann kommen Domain Services zum Einsatz. Diese sind zustandslos und sollten generell nicht dazu missbraucht werden, Fachlogik kategorisch aus Entities auszulagern. Dies ist in der Praxis häufig der Fall und führt im Ergebnis zum anämischen Domain Model.
  • Entities und Value Objects werden sinnvoll Modulen zugeordnet, die eine bestimmte Funktionalität kapseln und untereinander mittels Verwendung von Dependency Injection und anderen Entwurfsmustern entkoppelt werden.
  • Entities assoziieren andere Entities, so dass häufig Cluster abhängiger Objekte entstehen. Diese werden Aggregates genannt, wobei Wurzelentities den Zugriff auf die darunterliegenden Strukturen steuern.
  • Je komplexer die Struktur assoziierter Entities und Aggregate, desto schwieriger wird deren Erstellung und Initialisierung. Für diesen Zweck werden daher Factories eingesetzt, die das Wissen über die regelrechte Erzeugung von Entitäten und Aggregaten kapseln.
  • Erstellte Entity-Instanzen werden zudem in Repositories vorgehalten, auf die zentral zugegriffen werden kann. Existierende O/R-Tools machen von diesem Pattern reichlich Gebrauch.

Neben der Verwendung dieser Bausteine ist das Entwicklerteam gehalten, Subsysteme, Module, Schichten und Frameworks von Drittanbietern grundsätzlich voneinander zu entkoppeln, hierfür kommen Enterprise Design Patterns [2] (Adapter, Proxies, Anti-Corruption Layer, etc.) und Dependency Injection zum Einsatz.

Komponentenübersicht von DDD-Architekturbausteinen und deren Verwendung

Abbildung 1: Komponentenübersicht von DDD-Architekturbausteinen

Fazit

DDD ist ein mächtiges Werkzeug, um die Anforderungen komplexer Enterprise-Softwaresysteme zu realisieren und über deren Lebenszyklus hinweg auf Änderungen flexibel zu reagieren. Es eignet sich insbesondere für die Abbildung schnell veränderliche Fachprozesse, da diese im Herz der Software, dem Domain Layer, angesiedelt sind.

DDD ist eine Denkweise und Entwurfsmethode zugleich. Das Modell wird hierbei als gemeinsame Sprache in den Mittelpunkt gestellt. In Kombination mit modellgetriebener Softwareentwicklung und durch Verwendung geeigneter Tools können komplexe Fachzusammenhänge schnell in skalierbaren Architekturen und Quellcode überführt werden.

Wer mehr über die Grundlagen von DDD erfahren möchte, der sei an die Domain-Driven Design Community und diverse andere Internetquellen verwiesen.

Referenzen

[1] Evans, Eric: Domain-Driven Design – Tackling Complexity in the Heart of Software, Addison-Wesley 2004

[2] Fowler, Martin: Patterns of Enterprise Application Architecture, Addison-Wesley 2003

[3] Fowler, Martin: Anemic Domain Model, Online-Publikation, http://www.martinfowler.com/bliki/AnemicDomainModel.html, Stand: 4. Februar 2013

[4] Fowler, Martin: Domain Event, Online-Publikation, http://www.martinfowler.com/eaaDev/DomainEvent.html, Stand: 4. Februar 2013

[5] Dahan, Udi: Domain Events – Salvation, Online-Publikation, http://www.udidahan.com/2009/06/14/domain-events-salvation/, Stand: 4. Februar 2013