Читать книгу Vom Monolithen zu Microservices - Sam Newman - Страница 10
Modellierung rund um eine Businessdomäne
ОглавлениеEs ist teuer, eine Änderung über eine Prozessgrenze hinweg vorzunehmen. Müssen Sie zwei Services anpassen, um ein Feature bereitzustellen, und das Deployen dieser zwei Änderungen orchestrieren, ist das mehr Arbeit, als die gleiche Änderung in einem einzelnen Service vorzunehmen (oder einem Monolithen). Daraus folgt, dass wir Wege finden wollen, auf denen sichergestellt ist, dass wir serviceübergreifende Änderungen so selten wie möglich vornehmen.
Mit dem gleichen Ansatz wie dem in Building Microservices nutzt dieses Buch eine Beispieldomäne und eine Beispielfirma, um bestimmte Konzepte deutlich zu machen, bei denen ich keine realen Vorkommnisse erzählen kann. Die fragliche Firma ist Music Corp – eine große internationale Organisation, die es irgendwie schafft, im Geschäft zu bleiben, obwohl sie sich fast vollständig darauf konzentriert, CDs zu verkaufen.
Wir haben uns dazu entschieden, Music Corp trotz aller Widerstände ins 21. Jahrhundert zu befördern, und dazu gehört auch, die bestehende Systemarchitektur unter die Lupe zu nehmen. In Abbildung 1-1 sehen wir eine einfache Architektur mit drei Schichten. Wir haben eine webbasierte Benutzeroberfläche, eine Businessschicht (einen Business Layer) in Form eines monolithischen Backends und die Datenablage in einer klassischen Datenbank. Diese Schichten gehören – wie das so üblich ist – verschiedenen Teams.
Abbildung 1-1: Die Systeme von Music Corp als klassische Architektur mit drei Schichten
Wir wollen eine einfache Änderung an unserer Funktionalität vornehmen: Unsere Kunden sollen ihr bevorzugtes Musikgenre angeben können. Für diese Änderung müssen wir die Benutzeroberfläche anpassen, um das Genre auswählen zu können, der Backend-Service muss dafür sorgen, dass das Genre im UI erscheinen und die Werte geändert werden können, und die Datenbank muss diese Änderung übernehmen. All diese Anpassungen müssen von den einzelnen Teams gemanagt werden (siehe Abbildung 1-2), und das Ganze muss in der richtigen Reihenfolge geschehen.
Diese Architektur ist gar nicht schlecht. Alle Architekturen sind schließlich auf bestimmte Ziele hin optimiert. Die Drei-Schichten-Architektur ist so verbreitet, weil sie universell ist – jeder hat schon davon gehört. Ein Grund für das häufige Auftreten dieses Patterns ist, dass viele eine Architektur wählen, die ihnen an anderer Stelle bereits begegnet ist. Aber ich denke, der Hauptgrund liegt darin, dass das Muster darauf basiert, wie wir unsere Teams organisieren.
Das mittlerweile berühmte Gesetz von Conway besagt:
Organisationen, die Systeme entwerfen, […] sind gezwungen, Entwürfe zu erstellen, die die Kommunikationsstrukturen dieser Organisationen abbilden.
– Melvin Conway, How Do Committees Invent?
Die Drei-Schichten-Architektur ist ein gutes Beispiel dafür. In der Vergangenheit haben IT-Organisationen ihre Mitarbeiter*innen anhand ihre Kernkompetenz gruppiert: Datenbankadministratoren befanden sich in einem Team mit anderen Datenbankadministratoren, Java-Entwickler zusammen mit anderen Java-Entwicklern, und Frontend-Entwickler (die heutzutage so exotische Dinge wie JavaScript und die Entwicklung nativer Mobile-Apps beherrschen) steckten wieder in einem anderen Team. Wir bringen die Leute anhand ihrer Kernkompetenz zusammen, daher erzeugen wir auch IT-Produkte, die zu diesen Teams passen.
Abbildung 1-2: Eine Änderung über alle drei Schichten ist aufwendiger.
Das erklärt, warum diese Architektur so verbreitet ist. Sie ist nicht schlecht, sondern nur entlang bestimmter Kräfte optimiert – so wie wir traditionell die Leute nach ihren Kenntnissen gruppiert haben. Aber die Kräfte haben sich geändert. Unsere Ansprüche rund um unsere Software haben sich geändert. Wir fassen die Menschen jetzt in fähigkeitsübergreifenden Teams zusammen, um Übergaben und Silos zu reduzieren. Wir wollen Software schneller als je zuvor ausliefern. Das bringt uns dazu, beim Organisieren unserer Teams andere Entscheidungen zu treffen, womit wir auch unsere Systeme anders aufteilen.
Änderungen an der Funktionalität sind meist Änderungen an der Businessfunktionalität. Aber in Abbildung 1-1 ist unsere Businessfunktionalität ineffektiv über alle drei Schichten verteilt, was die Wahrscheinlichkeit erhöht, dass eine Änderung an der Funktionalität schichtübergreifend erfolgen muss. Das ist eine Architektur, in der wir einen engen Zusammenhang verwandter Technologien, aber nur einen losen Zusammenhang der Businessfunktionalität haben. Wollen wir Änderungen vereinfachen, müssen wir das Gruppieren unseres Codes verändern – wir wählen einen engen Zusammenhang der Businessfunktionalität statt der Technologien. Jeder Service kann dann eventuell aus einer Mischung dieser drei Schichten bestehen, aber das ist Sache der lokalen Serviceimplementierung.
Vergleichen wir das mit einer potenziellen alternativen Architektur, die Sie in Abbildung 1-3 sehen. Wir haben einen dedizierten Customer-Service, der ein UI bereitstellt, auf dem die Kunden ihre Informationen aktualisieren können. Der Status des Kunden wird ebenfalls innerhalb dieses Service gespeichert. Die Wahl eines Lieblingsgenres ist mit einem bestimmten Kunden verbunden, daher ist diese Änderung deutlich lokaler. In Abbildung 1-3 sehen Sie auch, dass die Liste der verfügbaren Genres von einem Catalog-Service geholt wird, der vermutlich in der einen oder anderen Form schon vorhanden ist. Ebenfalls zu finden ist dort ein neuer Recommendation-Service, der unser Lieblingsgenre abruft – etwas, das sich leicht in einem Folge-Release umsetzen ließe.
Abbildung 1-3: Ein dedizierter Customer-Service kann es deutlich erleichtern, das bevorzugte Musikgenre eines Kunden zu erfassen.
In solch einer Situation kapselt unser Customer-Service eine dünne Scheibe jeder der drei Schichten – er besitzt ein bisschen UI, ein bisschen Anwendungslogik und ein bisschen Datenablage –, aber diese Schichten sind alle in dem einen Service gekapselt.
Unsere Businessdomäne wird die treibende Kraft unserer Systemarchitektur, wodurch Änderungen hoffentlich einfacher umgesetzt werden können und es uns leichter fällt, unsere Teams rund um unsere Businessdomäne zu organisieren. Das ist so wichtig, dass wir vor dem Ende dieses Kapitels erneut das Konzept des Modellierens von Software rund um eine Domäne betrachten wollen, damit ich ein paar Ideen zum Domain-Driven Design aufzeigen kann, die unser Denken über unsere Microservices-Architektur beeinflussen.