Domain-driven Design
Die Ansätze aus Domain-driven Design (DDD) fordern und fördern die Betrachtung eines Systems primär mit Fokus auf das Domänenmodell und die Geschäftslogik statt auf technische Aspekte. Dabei ist ein zentrales Ziel, aus der Zusammenarbeit von Entwicklern und Domänenexperten eine fachlich passende Zerlegung und Umsetzung der Gesamtfunktionalität zu erreichen.
DDD bietet strategische Muster wie Ubiquitous Language, Bounded Context oder Context Map, um die Fachlichkeit zu erfassen, in einzelne Komponenten zu zerlegen und diese wiederum miteinander zu integrieren. Gleichzeitig definiert DDD auch eine Reihe von taktischen Mustern wie Aggregates, Repositories, Domain Services und (in aktuellen Auslegungen meist auch) Domain Events, welche sich als Bausteine für die konkrete Umsetzung der Fachlichkeit innerhalb einer Applikation eignen.
Onion Architecture
Unter dem Begriff “Onion Architecture” hat Jeffrey Palermo vor zehn Jahren in einer Blog-Serie einen Ansatz für eine Applikationsarchitektur beschrieben, welche ebenfalls die Fachlichkeit ins Zentrum stellt, sogar bildlich gesprochen: Die Onion Architecture besteht aus einer je nach Definition unterschiedlicher Anzahl konzentrischer Ringe, welche jeweils bestimmte Aspekte der Applikationsarchitektur beheimaten.
Typischerweise werden Ringe für das Domänenmodell, für die Domänen- bzw. Applikationsservices sowie für die Infrastruktur unterschieden. Code in äusseren Ringen darf dabei auf Code in inneren Ringen zugreifen, aber nicht umgekehrt. Die Abhängigkeiten zeigen daher immer von aussen nach innen. Im Zentrum der “Zwiebel” liegt das Domänenmodell mit der Kern-Geschäftslogik. Im Unterschied zu einer klassischen Layered Architecture basiert somit “alles” auf diesem Domänenmodell, und nicht auf der Persistenzschicht mit ihren meist fachlich “blutleeren” Entitäten.
Ein Ziel der Onion Architecture ist eine klare Trennung zwischen fachlichem Code und der Infrastruktur. Eine Argumentation dabei ist, dass die Geschäftslogik im Vergleich zu den sich ständig verändernen Infrastrukturtechnologien und -Frameworks deutlich stabiler und langlebiger ist und daher als das tragfähige Fundament für eine nachhaltige Zukunft des Systems dienen soll. Eine weitere - und im Kontext von DDD vielleicht relevantere - Argumentation ist, die Fachlichkeit ohne Vermischung mit technischen Aspekten wie Transaktionen, Persistenz, Authentisierung oder Remoting abzubilden. Ähnliche Ziele verfolgen auch die Hexagonal Architecture von Alistair Cockburn oder die Screaming Architecture von Uncle Bob.
Drei Gute Gründe …
Nach dieser kurzen Einführung in DDD und die Onion Architecture sehe ich nun mindestens folgende Gründe, weshalb sich der Ansatz der Onion Architecture besonders gut für die Umsetzung von Bounded Contexts nach DDD eignet:
Technologiefreies Domänenmodell
Durch die Trennung von Infrastrukturaspekten und Geschäftslogik in der Onion Architecture wird das Domänenmodell weitestgehend frei von den oben erwähnten technischen Aspekten. Nebst der einfacheren Testbarkeit der Fachlogik erlaubt dies vor allem besser lesbaren fachlichen Code und weniger Verschmutzung der Ubiquitous Language durch technisch bedingte Konstrukte. Diese starke Unabhängigkeit von technischen Aspekten erlaubt zudem zwei weitere wichtige Dinge: Sie fördert die Umsetzung von fachlich reichhaltigen (statt eben “blutleeren”) Domänenobjekten, da im Domänenmodell weniger techologiebedingte Einschränkungen bestehen (z.B. keine Vorgaben an das Design eines Aggregates durch den Object Relational Mapper). Und sie erleichtert die Strukturierung des Codes (z.B. mittels Packages) im Domänenmodell nach fachlichen Kriterien, da technische Aspekte bereits ausgeklammert sind.Abbildung von Mustern aus DDD auf Ringe der Onion Architecture
Die erwähnten taktischen Muster aus DDD lassen sich eindeutig einem bestimmten Ring der Onion Architecture zuweisen (z.B. Aggregate und Schnittstellen für Repositories auf das Domänenmodell, Domain Services auf die Domänenservices, Implementationen von Repositories auf die Infrastruktur, usw.). Dies wiederum unterstützt ein gemeinsames Verständnis des Teams bei Diskussionen zum Design und der anschliessenden Umsetzung: Es ist nach der Diskussion klar, wo und wie ein im Design identifiziertes Muster konkret implementiert wird. Zudem lässt sich auch für verschiedene Konzepte aus den strategischen Mustern, welche sich in der Implementierung niederschlagen, ein passender Ring definieren (z.B. die Abbildung eines Anti-Corruption Layers in der Infrastruktur) oder den Grad der “Invasion” in innere Ringe der Zwiebel beschreiben (z.B. Verwendung der Domänenobjekte des Suppliers bei einem Konformisten wohl im Ring für Applikationsservices, aber nicht im Domänenmodell).Eine Zwiebel pro Bounded Context
Das Konzept einer Zwiebel eignet sich sehr gut für die Abbildung eines einzelnen Bounded Contexts, sofern der Domänenschnitt fachlich passend gewählt wird. Durch die Kapselung des Domänenmodells eines Bounded Contexts wird eine hohe Kohäsion innerhalb einer Zwiebel erreicht. Gleichzeitig kann die Kopplung zu Zwiebeln anderer Bounded Contexts technisch gering gehalten und vom Domänenmodell getrennt über den Infrastruktur-Ring realisiert werden. Die Integration kann dabei typischerweise asynchron erfolgen, da Eventual Consistency zwischen Bounded Contexts aus fachlicher Sicht oftmals gut verkraftet werden kann bzw. sogar der nicht-digitalen Realität entspricht.
Ausblick
Insbesondere die Abbildung von taktischen Mustern in der Onion Architecture lässt sich durch die Verwendung von Stereotypen sehr explizit und mit einer Reihe von zusätzlich positiven Nebeneffekten realisieren. Mehr dazu dann in einem zukünftigen Blog-Post.