Von Christian Leinweber

Voraussichtliche Lesedauer: 7 Minuten

Techblog

„Domain Driven“ im Projekt-Alltag

„Hast Du schon mal in einem DDD-Projekt mitgemacht?“ Über Domain Driven Design reden alle. Aber hatten wir den Fokus auf die Domäne in der Individual-Software-Entwicklung nicht schon immer? Ich denke: Nein, hinter DDD steht mehr als sich nur gewissenhaft mit der Kundendomäne zu beschäftigen. DDD ist ein Vorgehensmodell. Es vereint eine Reihe von Techniken, die…

Techblog

„Hast Du schon mal in einem DDD-Projekt mitgemacht?“

Über Domain Driven Design reden alle. Aber hatten wir den Fokus auf die Domäne in der Individual-Software-Entwicklung nicht schon immer?

Ich denke: Nein, hinter DDD steht mehr als sich nur gewissenhaft mit der Kundendomäne zu beschäftigen. DDD ist ein Vorgehensmodell. Es vereint eine Reihe von Techniken, die helfen, die Prozesse in den Vordergrund der Modellierung zu stellen. Darüber hinaus gibt es mehrere Implementierungsmodelle, die sehr gut mit den Ideen von DDD harmonieren. Golo Roden hat das sehr anschaulich in unserem Blog beschrieben.

Allerdings treffe ich oft auf die Wahrnehmung, dass DDD nur funktioniert, wenn ein Projekt speziell von vorne bis hinten auf DDD mit allen seinen Facetten ausgelegt ist.

Ich denke, wir brauchen kein sortenreines DDD-Projekt, damit uns die Grundüberlegungen weiterbringen. Die einzelnen Konzepte dahinter helfen uns auch in anderen Projekten. Hierzu ein paar Bespiele.

Entities vs. Value Objects

Zum Beispiel gibt es in den meisten Projekten Entities und Value Objects. Laut DDD haben Entities einen eindeutigen Identifier und Value Objects werden über ihren Inhalt eindeutig. Jetzt könnte man meinen, das sei nur Code-Semantik. Mir und meinem Team hat das geholfen, einen Unterschied zu verstehen: Es ist für Entitäten notwendig, teamübergreifend die Identifier in allen Systemen als eine Art übergreifenden Referenzwert zu kennen. Zusätzlich ist es extrem wichtig festzulegen, in welchen Systemen die Datenhoheit für die jeweiligen Entitäten liegt. Bei Value Objects war das keine Notwendigkeit. Viele Systeme haben Adressdaten verwaltet, es musste aber nicht ein System für die Datenhoheit über die Adresse geben. Die globale Adresstabelle war damit Geschichte. Anders bei der Entität „Kunde“: Hier haben verschiedene Systeme zwar Aspekte des Kunden verwaltet, aber trotzdem referenzierten alle Systeme den gleichen Kunden über seinen Identifier.

Aggregate

In einem Refactoring-Projekt ging es darum, Systeme unterschiedlicher Teams stärker zu separieren, da eine gemeinsame Datenbasis zu Lasten der Teamperformanz ging. Allen war bewusst, dass wir die Systeme zwar technisch trennen konnten, die Geschäftsprozesse aber weiterhin systemübergreifend fließen. Es mussten also Ereignisse aus verschiedenen Systemen geteilt werden. Wir kamen schnell zur Einsicht, dass wir „Events” der Systeme identifizieren müssen, die dann „Commands” in anderen Systemen auslösen. Die Commands beziehen sich dann auf „Irgendwas”. DDD half uns dabei zu verstehen, dass das „Irgendwas“ Aggregate sind und wir genau an den Stellen Probleme hatten, wo wir uns wenige Gedanken über sinnvolle Aggregate gemacht haben.

In einem Projekt mit Message-basierten Microservices empfängt jeder Service seine Eingangsdaten über Queues, persistiert dies, führt anschließend seinen Anwendungsfall aus und schickt das Ergebnis weiter. Jeder Service stellt die persistierten Daten über REST-Endpunkte bereit. Laut DDD sind Aggregate “Zusammenfassungen von Entitäten und Wertobjekten und deren Assoziationen untereinander zu einer gemeinsamen transaktionalen Einheit.” (zitiert nach Wikipedia). Was erst einmal theoretisch klingt, hat uns bewogen, noch einmal die Vorgehensweise zu überdenken. Da sich Microservices auch bei uns an Aggregaten orientieren, sollten die Services in unserer Architektur auch den berechneten Anwendungsfall selber persistieren und das nicht ausschließlich an andere Services delegieren. Das hat wiederum den Kontext der Services gefestigt und unter anderen auch die Nachvollziehbarkeit erhöht.

CRUD oder nicht-CRUD

Auch in einem Softwareprojekt, in dem viel mit CRUD und Grids gearbeitet wird, können wir als Team fragen, was Events und Commands für unser CRUD-lastige Projekt bedeuten. Es lohnt sich, eine Eventstorming-Session einzulegen, auch wenn es kein Greenfield-Projekt ist. Die Erkenntnisse hieraus helfen sicherlich an einigen Stellen, die Fachlichkeit im System sichtbarer zu machen.

Bounded Context und Co.

In länger laufenden Projekten kann man sich in Hinblick auf Kundenkommunikation noch mal hinterfragen. In DDD wird der Begriff Bounded Context verwendet, um Kontextgrenzen zwischen Teamzuordnung, Verwendungszweck oder auch Datenbank-Schemata deutlich zu machen. Wenn es immer wieder Missverständnisse im Sprachgebrauch gibt, könnte man hinterfragen, ob es mehr als „einen” Bounded Context gibt. Wenn ja, kann man sich pro Bounded Context auf eine Ubiquitous Language einigen und gegebenenfalls ein Glossar führen. Das funktioniert übrigens unabhängig davon, ob man im Projekt DDD-Ansätze verfolgt.

Aus eigener Erfahrung kann ich sagen, dass die Differenzierung durch Sprache auch geholfen hat, große, scheinbar nicht teilbare Entitäten kleiner zu schneiden. In dem oben erwähnten Refactoring-Projekt ließ sich so die These überwinden, dass die Entität „Kunde“ sich über alle Systeme erstreckt und nicht teilbar ist. Nur durch die Sprache wurde deutlich, dass wir beim Kunden mal vom Vertragspartner und mal vom Debitor geredet haben, je nach Sichtweise. Und schon war die Trennung klar. Anschließend brauchte es nur noch ein Mapping.

Strategisches Design

Aber nicht nur auf Entwicklungsebene bietet DDD eine wertvolle Hilfestellung. Die Einteilung in Core-, Support– und Generic-Subdomains adressiert im Kontext von DDD oft einen System-Scope. Doch auch auf einer höheren Landschaftsebene ist eine Bewertung durchaus wertvoll: Durch welche Systeme erziele ich eigentlich konkret einen Mehrwert, der mein Unternehmen von Mitbewerbern abgrenzt? Welche Systeme wirken hier nur unterstützend, bilden für sich allein genommen also keinen direkten Mehrwert? Welche Systeme müssen einfach da sein und sind in jedem Unternehmen zu finden, haben aber mit dem Kerngeschäft selbst nichts zu tun? Diese Bewertung ist durchaus wertvoll.

Das mag in der Konsequenz bedeuteten, dass in der Kerndomäne durch Individual-Entwicklung der maximale Nutzen zu erzielen ist und entsprechend Zeit und Geld investiert wird. Auf diese Systeme sollte klar der Fokus liegen. Bei Support-Domänen muss nicht immer alles auf dem neusten technologischen Stand sein, und es darf hier gerne auch mal mit CRUD gearbeitet werden; dennoch macht Eigenentwicklung oft Sinn, da diese meine Systeme in der Kerndomäne schneller zum Laufen bringen. Bei generischen Systemen macht Individualsoftware eher keinen Sinn. Und hier liegt aus meiner Sicht der entscheidende Punkt für die Entscheidung, ab wann sich DDD lohnt. Die Frage ist nicht, ob es sich lohnt, sondern für die Systeme welcher Domäne.

Fazit

Die Beschäftigung mit DDD hat Potenzial für Augenöffner. Trotzdem sollte man DDD nicht als ganzheitliche Methodik auf einen Sockel stellen – wie jedes andere Vorgehensmodell auch. Es hilft schon, die Hintergründe der einzelnen Aspekte zu verstehen und sich darüber Gedanken machen, wie die Idee dahinter im eigenen Projekt helfen kann!


Über den Autor

Von Christian Leinweber

Principal IT Architect

Christian Leinweber ist Principal-IT-Architekt bei MaibornWolff mit langjähriger Erfahrung für Architekturen verteilter Systeme. Zusammen mit seinem Team entwickelt er Cloud-Native-Applications für eine Vielzahl verschiedener Kunden.