Magazin

08. Nov. 2022

Domain Driven Design als Best Practice

Talk zum Thema „Best Practices für die Datenmodellierung von Microservices“
Managing Consultant

Autor:in

Marcus Franz

20221108_DomainDrivenDesign

DOMAIN-DRIVEN DESIGN ALS BEST-PRACTICE FÜR DATENMODELLIERUNG VON MICROSERVICES

Die JUG Augsburg hatte uns eingeladen, am 25. Oktober einen Talk zum Thema „Best Practices für die Datenmodellierung von Microservices“ zu halten.

Wir haben unseren Vortrag zweigeteilt:

  • Im ersten Teil betrachten wir zunächst Nutzen und Kosten einer Microservices-Architektur.
  • Der zweite Teil baut darauf auf und zeigt, wie wir Domain-Driven Design als Best-Practice im Umgang mit Microservice-Architekturen einsetzen können.

Unsere Folien finden sich auf Speakerdeck hier und auf Youtube gibt’s einen Video-Mitschnitt unseres Remote-Talks, den die JUG dankenswerterweise bereitgestellt hat.

Monolith oder Microservices?

Für diese Frage haben wir das Spinnennetzdiagramm von Abbildung 1 für eine vergleichende Architekturbewertung entwickelt. Damit werden Einflussgrößen herausgearbeitet, die für oder gegen den Microservice-Einsatz sprechen.

Wann lohnen sich Microservices?

Zunächst muss das Umfeld die organisatorischen und fachlichen Voraussetzungen für erfolgreiche Microservice-Architekturen erfüllen. Das Produktivitätsdiagramm von Martin Fowler und das Cynefin-Framework von Dave Snowden verdeutlichen den grundsätzlichen Unterschied zwischen komplexen und komplizierten Rahmenbedingungen. Die Erkenntnisse von William Deming und Melvin Conway zeigen uns, wie wir der Dynamik komplexer Situationen begegnen können. Zunehmende Komplexität bedeutet abnehmende Planbarkeit, und Autonomie ist die passende Antwort im Umgang mit komplexen Situationen. Lose gekoppelte Microservice-Architekturen können uns dabei helfen.

Welche Konsequenzen hat der Einsatz von Microservices?

Allerdings stößt uns die Microservice-Architektur mit Macht in die schwierige Welt verteilter Systeme. Dort kämpfen wir mit um Größenordnungen höheren Latenzen, zusätzlich notwendigen Strategien zur Fehlerbehandlung und somit mit einem deutlich schwierigeren Betrieb.

Voraussetzung für den Serviceschnitt ist aber auch eine gute fachliche Strukturierung. Das ist auch bei monolithischen Anwendungen schwierig genug. Simon Brown spitzt das sehr schön zu: „If you can’t build a modular monolith, what makes you think microservices is the answer?” Hier ist der fachliche Schnitt entscheidend, zu dem uns Domain-Driven Design verhilft.

Aber auch die Konsistenzanforderung in einer hochgradig verteilten Microservice-Architektur müssen wir bedenken: Können wir dem Anwender noch die erforderlich (vielleicht manchmal auch nur gewohnte) strenge Konsistenz bieten oder ist nicht stattdessen „Eventual Consistency“ die bessere Wahl?

Domain-Driven Design to the rescue!

Entscheiden wir uns für eine Microservice-Architektur, dann benötigen wir solide Modellierungspraktiken, wie sie Domain-Driven Design bietet. Domain-Driven Design (DDD) setzt mit seinem Entwurfsansatz den Fokus auf die Fachlichkeit und stellt uns hierfür eine Vielzahl Werkzeugen bereit, um die Fachlichkeit zu ergründen, unser System entsprechend zu schneiden und auf Code-Ebene zu implementieren. Dabei ist DDD kein junger Ansatz in der IT-Welt, ist doch Eric Evans Buch zu diesem Thema bereits im Jahr 2003 erschienen. Mit der Entstehung von Microservice-Architekturen bekam Domain-Driven Design aber frischen Wind unter den Segeln und ist seitdem in der IT-Welt omnipräsent.

Das Strategische Design von DDD

Im Großen, auf der Ebene der Anwendungslandschaft, hilft uns das Strategische Design aus dem DDD bei der Planung und der Analyse unserer verschiedenen Microservices. In einer Microservice-Architektur akzeptieren wir, dass jede Subdomäne ihr eigenes Domänenmodell, mit ggf. eigener Datenhoheit und Lebenszyklus, hat (siehe Abbildung 2). Schließlich hat jede Subdomäne ihre eigenen Problemstellungen, die es in Form eines oder einiger weniger Microservice zu lösen gilt. Um den Fluss der Domänenmodelle zu visualisieren, gibt uns DDD die Context Map an die Hand. Diese stellt uns eine Vielzahl an Mustern bereit, um die Beziehungen zwischen den einzelnen Microservices klar zu bestimmen und Probleme frühzeitig zu erkennen.

Das Taktische Design von DDD

Auch auf „kleiner“ Ebene, der Modellierung von Strukturen innerhalb eines Microservices, gibt uns DDD in Form seines Taktischen Designs eine Reihe von hilfreichen Ansätzen, um der Komplexität Herr zu werden:

  • Zum einen ist die Trennung von fachlichen und technischen Belangen, beispielsweise durch die Implementierung einer Onion-Architektur, fundamental verankert im DDD, was die Komplexität schon einmal vehement reduziert.
  • Zum anderen wird das Domänenmodel primär mittels dreier Muster implementiert. Während die Muster Entity und Value Object den meisten von uns ein Begriff sein dürfte, sieht es mit dem Aggregate vermutlich anders aus. Um die Komplexität innerhalb eines Microservices weiter zu reduzieren, wollen wir Entitäten mit ihrem eigenen Lebenszyklus und ihrer zu Grunde liegenden Fachlichkeit isoliert betrachten. Dies ist aber nicht immer möglich, da es fachlich motivierte Konsistenzgrenzen geben kann, die sich über mehrere Entities spannen: Genau diese Konsistenzgrenzen muss ein Aggregate umfassen. Die Herausforderung ist somit, Aggregates so klein wie möglich und so groß wie nötig zu modellieren.

Bleibt abschließend die Frage, ob wir wirklich Flexibilität und Wachstum in dem Maß wie Netflix oder REWE oder andere bekannte Big Player benötigen, die ihre Anwendungslandschaft heute strategisch in Form von Microservices umsetzen.

Doch selbst wenn wir uns – aus guten Gründen – gegen eine Microservice-Architektur entscheiden: Niemand hindert uns daran, einen guten Modulithen mit Hilfe von Domain-Driven Design zu bauen, im Gegenteil!

PS: Wer mehr zu unserem Verständnis von Microservices lesen will, dem empfehlen wir unsere Artikelserie bei Informatik 

(Autorenteam: Marcus Franz, Martin Lehmann und Dr. Renato Vinga-Martins)