Microservices und stabile Interfaces
Microservices sind ein beliebtes Tool, um komplexe Domänen zu zerteilen. Doch am Ende des Tages macht die Entscheidung des übermäßigen Einsatzes – in manchen Fällen – dann mehr Kopfweh als Nutzen. Vor Kurzem ist mir dabei folgendes Beispiel im Zuge einer Diskussion in den Sinn gekommen:
Schauen wir uns einen Teil eines Webshops an:
- Order Management mit der Aufgabe den Bestellvorgang abzuwickeln
- Pay Service mit der Aufgabe der Bezahlung
Neben fachlichen Aspekten, die für das Schneiden wichtig sind, welche Eigenschaft sind noch wichtig? Stabile Interfaces. Schaut man sich diese an, so merkt man, dass diese relativ einfach sind und eigentlich über die Zeit hinweg stabil sein sollten: Pay Service: Input Parameter: Geldbetrag
Was lässt sich aus den Input Parameter ableiten:
- Wenn man sich initial hinsetzt und den Flow im System am Papier durchspielt, so wird man ein recht gutes Ergebnis haben, was die Qualität und Stabilität der API anbelangt. Ja – man kann immer Gegenbeispiele finden, wie unter anderem die API des TM-Forums , welche eine durchaus komplexe API hat, da Produkte meist im Zusammenhang mit anderen Produkten betrachtet werden und auch kundenspezifische Eigenschaften zu einem Endpreis führen – aber auch hier, sind die APIs relativ stabil (die APIs von 5 Jahren erkennt man noch immer – auch wenn sie sich im Detail vermutlich geändert haben).
- Teams können den Input recht gut simulieren und können autonom entwickeln
Im Kontrast: Wenn man in jedem Sprint die API nachbessern muss, so ist der Schnitt wahrscheinlich nicht optimal gelaufen. Ebenfalls ist der fachliche Schnitt ein wichtiges Kriterium. Führt eine Stakeholderanforderung jedes Mal dazu, dass mehrere Microservices angegriffen werden müssen, so ist vermutlich auch falsch geschnitten worden.
Eine weitere Art des „Schnitts“ ist der Grund der Skalierbarkeit - aber es ist eben kein echter Schnitt. Schaut man sich z.B. das 4+1 View-Model (der C4) an so sieht man:
- In der „logischen“ Ansicht können die Komponenten in einem Service verweilen
- Im Deployment-View aber u.U. getrennt deployed werden, weil man skalieren möchte. Fachlich hat sich aber nichts geändert – auch teamtechnisch (Ownership) nicht
Ein weiteres Interessantes Thema ist die Kommunikation zwischen Microservices. Hier gibt es keine One-Fits-All Lösung. Zu sagen, dass asynchrone Kommunikation IMMER das Beste ist, halte ich für ein Gerücht. Ein interessantes Gegenbeispiel hatte ich vor Kurzem: Schaut man sich die Theorie zu Komponenten an, so kommt auch der Term „Connector“ einem unter. Dieser sagt aber auch, dass z.B. SQL eine Art der Kommunikation darstellt.
Und so kann man z.B. Stammdaten auch per SQL View anbieten, wenn sie auf der gleichen Datenbankinstanz liegen. Der Konsument kann die Queries beliebig gestalten. Im Kontrast zur asynchronen Kommunikation: bei jeder Änderung der Stammdatenstruktur muss man u.U. eine Topic-Migration in Betracht ziehen und der Consumer muss eine eigene Datenhaltung haben, wo er die Stammdaten so speichert, wie er sich braucht.