Microservices: Warum ein Domain-Model in die verkehrte Richtung führen kann

Microservices sind heute allgegenwärtig. Sie sind zwar klein, gleichen oftmals aber noch Komponenten aus der guten alten Enterprise-Zeit. Ist es wirklich sinnvoll, mehrere Services für dasselbe Geschäftsobjekt auf einer Datenbank zu haben?

Architektur/Methoden  –  37 Kommentare
Microservices: Warum ein Domain-Model in die verkehrte Richtung führen kann

Welche Anforderungen gibt es eigentlich an einen Microservice und was zeichnet ihn aus? Ist es wirklich sinnvoll, einen Schreib-, einen Lese- und einen Such-Service für dasselbe Geschäftsobjekt auf einer Datenbank zu haben? Der Artikel beleuchtet anhand von Beispielen aus den drei Domänen Einkauf, Bankdienstleistungen und Logistik verschiedene Ansätze, wie sich Microservices optimal schneiden lassen, und empfiehlt Vorgehensweisen in Abhängigkeit vom jeweiligen Kontext.

Wie Microservices zu schneiden sind und wie man dabei die Prinzipien des Domain-Driven Design anwenden kann, hat Lars Röwekamp im Beitrag zur Methodik "Der perfekte Microservice" bereits ausführlich beschrieben. Microservices sind demnach laufende Funktionen, die sich unabhängig voneinander produktiv schalten lassen. Sie sind über Schnittstellen lose gekoppelt und durch hohe Redundanz und Robustheit gekennzeichnet.

Sie richtig zu schneiden, erfordert einerseits umfassende Erfahrung und andererseits den Mut, Fehler zu machen und diese zu berichtigen. Eric Evans hat dafür mit seiner Methodik des Domain-driven Design schon 2003 die Weichen gestellt. Allerdings kommt dem DDD erst seit dem 2014 von Martin Fowler und Kollegen angestoßenen Aufkommen des Microservices-Prinzips entscheidende Bedeutung zu.

Zu welch unterschiedlichen Lösungsansätzen die Prinzipien von Microservices und Domain-driven Design in verschiedenen Domänen führen können, machen im Folgenden die drei Beispiele in den Domänen Einkauf, Bankdienstleistungen und Logistik deutlich.

Das Beispiel bezieht sich auf das Domänen-Modell eines typischen Einkaufprozesses. Unternehmen tauschen in solchen Prozessen Anfragen und Angebote aus. Im simpelsten Fall sind dies das einkaufende Unternehmen ("Buyer") und das liefernde Unternehmen ("Supplier"). Das einkaufende Unternehmen erstellt eine Ausschreibung ("Call of Bids") und lädt liefernde Unternehmen zu dieser Ausschreibung ein. Diese antworten auf die Ausschreibung in Form eines Gebots ("Bid"). Nach einer Evaluierung kann das einkaufende Unternehmen den Lieferanten und sein Gebot auswählen ("Awarded Bid") und beauftragen.

Domänenmodell eines beispielhaften Einkaufprozesses (Abb. 1)

Sollen in diesem Modell Domänengrenzen im Sinne eines Kontextes ("Bounded Context") gezogen werden, ergibt ein Teil die Stammdatendomäne ("Master Data Domain") und ein anderer Teil die Domäne der Lieferantenauswahl ("Sourcing Domain").

Beim Betrieb einer solchen Anwendung mit den Services "Master Data" und "Sourcing" wird schnell deutlich, dass unterschiedliche Schritte in der Lieferantenauswahl ganz unterschiedliche Anforderungen an die erforderlichen Ressourcen stellen.

Geschäftsprozessmodell eines beispielhaften Einkaufprozesses (Abb. 2)

Der Schritt "Erzeuge Angebot" ("Create Bid") unterscheidet sich deutlich von "Erzeuge Ausschreibung" ("Create Call of Bids") oder "Vergabe" ("Awarding"). Während bei den Schritten "Erzeuge Angebot" und "Vergabe" beziehungsweise "Prüfe Angebote" ("Evaluate Bids") in der Regel ein Einkäufer einen Prozess betreut, greifen im Schritt "Erzeuge Angebot" viele Lieferanten auf das System zu. Auch die Schritte "Erzeuge Ausschreibung" und "Prüfe Angebote" beziehungsweise "Vergabe" unterscheiden sich hinsichtlich der Notwendigkeit der Zugriffe auf Stammdaten ("Master Data Domain") deutlich. Daher ist es sinnvoll, auch hier eine Kontextgrenze einzuführen. Nach dieser Analyse ergeben sich die Domänen Stammdaten ("Master Data Domain"), Ausschreibung ("Call of Bids Domain"), Angebote ("Bidding Domain") und Vergabe ("Awarding Domain").

Das Beispiel zeigt, dass Unterschiede in der Benutzung der einzelnen Geschäftsobjekte (in diesem Fall Gebote und Ausschreibungen) große Unterschiede auftreten können, die sich aus dem statischen Modell nicht ergeben. Daher sind auch dynamische Modelle nötig.

Vereinfachtes Domänenmodell von Kreditkarten-Transaktionen (Abb. 3)

Vom Händler ("Merchant") initiierte Kreditkartentransaktionen nimmt ein Payment-Service-Provider (PSP) entgegen und verarbeitet sie. Die Verarbeitung beinhaltet die Weiterleitung an die Kreditkartenorganisationen und die Erstellung von Auszahlungsinformationen für die Akquisebank ("Acquiring Bank"). Der Payment-Service-Provider hingegen stellt seine Dienstleistung dem Händler direkt in Rechnung. Dazu zieht der PSP in der Regel die Transaktionsanzahlen als Rechnungsbasis heran.

Das Domänenmodell bildet diese Zusammenhänge ab. Die Transaktionen "Authorization" und "Capture" werden verarbeitet und aggregiert. Die Aggregation enthält sowohl Transaktionsanzahlen als auch Transaktionswerte. Die Aggregationen für die Anzahlen finden sich in den Rechnungen des PSPs wieder, während die Werte der Akquise-Bank für Auszahlungen zur Verfügung stehen müssen.

In diesem Beispiel ergeben sich die Domänen Stammdaten ("Master Data Domain"), Transaktionen ("Transaction Domain") und Aggregation ("Aggregation Domain"). Da Transaktionsverarbeitung und Aggregation schon getrennt sind, sollten im Betrieb wenig Probleme auftreten – die Last in der Transaktionsverarbeitung ist wesentlich höher als die Last in der Aggregationsverwendung.

Allerdings könnten sich organisatorische Probleme ergeben, da die Rechnungserstellung für den PSP und die Erstellung von Auszahlungsfiles für unterschiedliche Organisationen vorzunehmen sind. Dies wird aber erst im Geschäftsprozessmodell deutlich.

Geschäftsprozessmodell einer Transaktionsverarbeitung (Abb. 4)

Der letzte Schritt "Erzeuge Überweisung" ("Create Transfer") benötigt die Aggregationen auf Wertebasis. Die Überweisung selbst nimmt dann aber nicht mehr der PSP vor, sondern die Akquisebank ("Acquiring Bank"). Daher sind in jedem Fall Schnittstellen nötig und es entsteht eine Kontextgrenze. Diese ist im Geschäftsprozess selbst begründet und nicht, wie im vorigen Beispiel gezeigt, in der Verwendung der Applikation.

Erschwerend kommt hinzu, dass die Stammdatendomäne bei der bloßen Ansicht der Geschäftsobjekte losgelöst erscheint. Auch im Geschäftsprozess ist sie nicht unbedingt offensichtlich. Das Aufsetzen von Händlern ist ein entkoppelter Prozess, wodurch Stammdaten in den Einzeldomänen selbst zu behandeln sind. Das führt zu hohem Aufwand und unnötig inkonsistenten Daten. Um dies zu vermeiden, empfiehlt es sich, sowohl das Domänenmodell als auch das Geschäftsprozessmodell hinsichtlich der Verwendung von Stammdaten zu untersuchen und diese in das Kontextmodell und in die Kontextübersicht ("Context Map") einzubeziehen.

Domänenmodell einer Logistikanwendung (Abb. 5)

Das Domänenmodell einer Logistikanwendung sieht auf den ersten Blick sehr einfach aus. Eine Flotte von Fahrzeugen und Fahrern fährt Touren, wobei diese später in entsprechenden Aggregaten ausgewertet werden können. Daraus ergeben sich die Stammdatendomäne ("Master Data Domain"), die Tourendomäne ("Tour Domain") und die Aggregationsdomäne ("Aggregation Domain").

Geschäftsprozess einer Logistikanwendung (Abb. 6)

Der entsprechende Geschäftsprozess sieht schon etwas komplexer aus. Es ergeben sich für die Tourdomäne die Subdomänen: Fahrerzuordnung ("Assignment Domain") und Monitoring ("Monitoring Domain"), während sich die Aggregationsdomäne in die Domäne Tourenbewertung ("Grading Domain") und Bericht ("Reporting Domain") spaltet. Im Grunde sind diese Unterscheidungen aber willkürlich und hängen davon ab, wie die entsprechende Software bei den Kunden positioniert und vermarktet wird. Unterschiedliche Domänen ergeben sich hier nicht aus technischen oder Verwendungsfragen, sondern daraus, wie eine Software und ihre Leistungsmerkmale vermarktet werden sollen. Domänengrenzen sind durchaus sinnvoll, wenn unterschiedliche Kunden diese Domänen in unterschiedlichen Zusammensetzungen verwenden.