Читать книгу Vom Monolithen zu Microservices - Sam Newman - Страница 28

Implementierungskopplung

Оглавление

Die Implementierungskopplung ist meist die schädlichste Form der Kopplung, aber zum Glück lässt sie sich häufig am einfachsten verringern. Bei der Implementierungskopplung wird A mit B in Bezug darauf gekoppelt, wie B implementiert ist – ändert sich die Implementierung von B, ändert sich auch A.

Die Implementierungsdetails sind hier oft durch die Entwickler frei gewählt. Es gibt viele Wege, ein Problem zu lösen – wir entscheiden uns für einen, ändern aber eventuell später unsere Meinung. Wenn wir das tun, wollen wir die Anwender nicht stören (Sie erinnern sich: unabhängige Deploybarkeit).

Ein klassisches und häufig vorkommendes Beispiel der Implementierungskopplung ist das gemeinsame Verwenden einer Datenbank. In Abbildung 1-9 enthält unser Order-Service einen Datensatz mit allen Bestellungen des Systems. Der Recommendation-Service schlägt unseren Kunden abhängig von den bisherigen Bestellungen Artikel vor, die ihnen vielleicht gefallen könnten. Aktuell greift der Recommendation-Service auf die Daten direkt in der Datenbank zu.

Abbildung 1-9: Der Recommendation-Service greift direkt auf die Daten zu, die im Order-Service gespeichert sind.

Recommendations benötigen Informationen über die bisherigen Bestellungen. Bis zu einem gewissen Grad ist das eine unvermeidbare Domänenkopplung, auf die wir gleich eingehen werden. Aber in dieser speziellen Situation sind wir an ein spezifisches Schema, einen SQL-Dialekt und vielleicht sogar an den Inhalt der Zeilen gekoppelt. Ändert der Order-Service den Namen einer Spalte, teilt die Tabelle »Customer Order« auf oder tut sonst irgendetwas, enthält er konzeptionell immer noch Order-Informationen, aber wir verhindern, dass der Recommendation-Service diese Informationen abrufen kann. Besser ist es, dieses Implementierungsdetail zu verbergen (siehe Abbildung 1-10) – jetzt greift der Recommendation-Service auf die benötigten Informationen über einen API-Aufruf zu.

Abbildung 1-10: Der Recommendation-Service greift auf die Order-Informationen nun über eine API zu, die die internen Implementierungsdetails verbirgt.

Wir könnten den Order-Service auch als ein Dataset in Form einer Datenbank veröffentlichen lassen, was für den Bulk-Zugriff von Konsumenten gedacht wäre (siehe Abbildung 1-11). Solange der Order-Service die Daten passend veröffentlichen kann, sind jegliche Änderungen innerhalb des Order-Service für Konsumenten unsichtbar, da der öffentliche Vertrag eingehalten wird. Das ermöglicht auch ein Verbessern des Datenmodells, das für die Konsumenten genutzt wird, um es an ihre Bedürfnisse anzupassen. Wir werden solche Muster detaillierter in Kapitel 3 und 4 behandeln.

In beiden Varianten kommt Information Hiding zum Einsatz. Das Verbergen einer Datenbank hinter einer wohldefinierten Serviceschnittstelle erlaubt dem Service, den Scope dessen zu beschränken, was preisgegeben wird, und wir können dadurch die Repräsentation der Daten anpassen.

Abbildung 1-11: Der Recommendation-Service greift auf die Order-Informationen nun über eine bereitgestellte Datenbank zu, die anders als die interne Datenbank strukturiert ist.

Ein weiterer nützlicher Trick ist bei der Definition einer Serviceschnittstelle ein »Outside-in«-Denken – entwerfen Sie die Serviceschnittstelle aus Sicht des Servicekonsumenten, dann überlegen Sie sich, wie Sie diesen Servicevertrag implementieren. Der alternative Ansatz (dem ich leider allzu häufig begegnet bin) geht genau umgekehrt vor. Das Team, das an dem Service arbeitet, nimmt ein Datenmodell oder ein anderes internes Implementierungsdetail, und dann überlegt es sich, dieses nach außen bereitzustellen.

Beim »Outside-in«-Denken fragen Sie sie stattdessen zuerst: »Was brauchen meine Servicekonsumenten?« Und ich meine nicht, dass Sie sich selbst fragen, was Ihre Konsumenten benötigen – Sie fragen tatsächlich diejenigen, die Ihren Service aufrufen werden!

Behandeln Sie die Serviceschnittstellen, die Ihr Microservice bereitstellt, wie eine Benutzeroberfläche. Nutzen Sie »Outside-in«-Denken, um das Schnittstellendesign zusammen mit denjenigen zu entwerfen, die Ihren Service verwenden werden.

Stellen Sie sich Ihren Servicevertrag mit der Außenwelt wie eine Benutzeroberfläche vor. Beim Entwerfen einer Benutzeroberfläche fragen Sie die Anwender, was sie haben wollen, und iterieren zusammen mit ihnen über das Design. Sie sollten Ihren Servicevertrag auf die gleiche Art und Weise formen. Damit erhalten Sie nicht nur einen Service, der von Ihren Konsumenten leichter zu nutzen ist, es hilft auch dabei, eine gewisse Trennung zwischen dem externen Vertrag und der internen Implementierung herzustellen.

Vom Monolithen zu Microservices

Подняться наверх