This article is also available in English

Domain-driven Design teilt große Systeme in Bounded Contexts auf, von denen jeder ein eigenes Domänenmodell hat, um einen Teil der Fachlichkeit weitgehend unabhängig zu erbringen. In einem System für eine Bibliothek könnte es einen Bounded Context für das Ausleihen von Büchern und einen anderen für die Suche geben. Das eine Domänenmodell hätte dann die Informationen für die Leihe wie die Anzahl der Exemplare eines Buchs. Beim Domänenmodell für die Suche spielt die Anzahl keine Rolle, dafür sind Autor oder Titel wichtige Informationen.

Beziehungen zwischen Bounded Contexts

Relation and Kollaboration
Relation and Kollaboration

Domain-driven Design bietet Ansätze, um das benötigte Integrieren der Bounded Contexts durchzuführen (Abb. oben). Am Anfang steht die Analyse, in welcher Beziehung Bounded Contexts zueinander stehen. Die Arten der Beziehung sind folgende:

  • Free bedeutet, dass die Arbeit an einem Bounded Context wenig Auswirkungen auf die Arbeit an anderen Bounded Contexts hat.

  • Bei Upstream-Downstream ist der Erfolg des Teams, das den Bounded Context im Downstream bearbeitet, von dem Team abhängig, das den im Upstream in Arbeit hat.

  • Mutually dependent bedeutet, dass die Teams beide Systeme nur zusammen erfolgreich liefern können.

Welche Beziehung vorliegt, lässt sich fast immer durch die Analyse der Bounded Contexts ermitteln. Es ist also meistens keine Designentscheidung, sondern ergibt sich aus der Aufteilung.

Zurück zum Beispiel der Bibliothek: Deren Besucher suchen zunächst Bücher und leihen sie anschließend aus. Bei „Leihe” und „Suche” kommt Free somit nicht in Frage, da es eine Möglichkeit geben muss, gefundene Bücher auszuleihen. Daher haben die beiden Bounded Contexts eine Beziehung.

Der Erfolg der „Leihe” ist wahrscheinlich gegeben, wenn sich Bücher ausleihen lassen. Der Erfolg der „Suche” hingegen bedeutet vermutlich, dass das Finden der Bücher erfolgreich ist. Besucher können ein Buch nur leihen, wenn sie es vorher gefunden haben. „Leihe” ist damit Downstream zu „Suche” und umgekehrt „Suche” Upstream zu „Leihe”.

Mutually Dependent ist die Beziehung nicht: Zum einen geht sie nur in eine Richtung und ist daher nicht gegenseitig (mutually) und zum anderen gibt es in der „Suche” und „Leihe” genügend Bereiche und Features, die sich unabhängig voneinander entwickeln lassen. Die Ergänzung der Suche um neue Kriterien hat beispielsweise keine Auswirkungen auf die Leihe.

Primär schlagen sich die Beziehungen in der Organisation und Koordination zwischen den Teams nieder und nicht in den Softwareartefakten. Dennoch sind es zusätzlich Ergebnisse der Relationen auf Softwareebene: Zwei Bounded Contexts mit einer Schnittstelle können kaum Free sein.

Auf der Organisationsebene sind die Beziehungen ein direktes Ergebnis der Softwareartefakte. Wenn ein Team die Verantwortung für einen Downstream Bounded Context übernimmt, bekommt es die passende Downstream-Rolle. Es ist genau genommen nicht das Team selber, das die Beziehung hat, sondern der Bounded Context gibt die Beziehung an das Team weiter.

Kollaborationen: Organisation designen

Die oben genannten Beziehungen ergeben sich aus der Aufteilung in Bounded Contexts: „Leihe” ist unabdingbar Downstream von „Suche”. Das hat jedoch Nachteile, da das Verleihen von Büchern die Kernaufgabe einer Bücherei ist. Wenn andere Bereiche die zentrale Aufgabe negativ beeinflussen können, sind Gegenmaßnahmen angebracht, um die Prioritäten in dem Projekt richtig setzen zu können.

Die Upstream-Downstream-Beziehung lässt sich nicht wegdiskutieren, da sie objektiv vorhanden ist. Dennoch existieren unterschiedliche Wege, auf das Verhältnis Upstream-Downstream in der Organisation zu reagieren:

  • Customer-Supplier-Kollaboration
  • Conformist-Kollaboration
  • Anticorruption Layer
  • Open Host-Service

Bei einer Customer-Supplier-Kollaboration kann das Downstream-Team beim Upstream-Team Features einfordern, die letzteres im Rahmen seiner Möglichkeiten umsetzt. Bei dieser Art der Zusammenarbeit könnte „Leihe” bei der „Suche” neue Features anfordern. Damit hat „Leihe” tatsächlich eine höhere Priorität als „Suche”.

Anders bei der Conformist-Kollaboration: In dem Fall übernimmt das Downstream-Team das Datenmodell des Upstream-Teams und hat kein Mitspracherecht. Das erleichtert zwar die Integration, liefert aber das Downstream-Team dem Upstream-Team aus. Die Entscheidung zwischen Customer-Supplier und Conformist ist eine Architekturentscheidung. Sie hängt von der Priorisierung ab: Ist das Downstream-Team politisch mächtig oder bearbeitet ein wichtiges Thema, bekommt es eher eine Customer-Rolle. Sonst findet es sich vielleicht in einer Conformist-Rolle wieder.

Somit lässt sich die Upstream-Downstream-Beziehung mit einer Architekturentscheidung an den Stellen kompensieren, an denen es sinnvoll erscheint. Teams könnten die „Leihe” in eine Conformist-Rolle zwingen, wenn die Priorisierung nicht hoch genug ist.

Eine weitere Option ist der Anticorruption Layer: Ähnlich wie bei Conformist kann das Downstream-Team nicht in die Belange des Upstream-Teams eingreifen, hat jedoch in dem eigenen System eine Schicht eingezogen, durch die es sich von dem Domänenmodell des Upstream-Teams entkoppelt. Auf der Ebene der Zusammenarbeit entspricht das dem Conformist, aber es kommt eine weitere Schicht zur Übersetzung der Modelle beim Downstream Bounded Context hinzu.

Bei einem Open-Host-Service gibt es mehrere Downstream-Teams, die gemeinsam eine Schnittstelle des Upstream-Teams nutzen. Als Vorschrift für die Interaktion gilt: Das Upstream-Team ist dafür zuständig, die Schnittstelle weiterzuentwickeln. Anforderungen der Downstream-Teams können in die Weiterentwicklung einfließen, aber das Upstream-Team kann Anforderungen ablehnen und stattdessen einem Downstream-Team eine eigene Schnittstelle anbieten.

Voneinander abhängig

Analog zu den unterschiedlichen Ansätzen für Upstream-Downstream-Relation lässt sich auf Organisationsebene auf Beziehungen, die Mutually Dependent sind unterschiedlichen reagieren:

  • Partnership
  • Big Ball of Mud

Bei einer Mutually-Dependent-Beziehung kommt fast ausschließlich eine Partnership für die Integration in Frage. Der Begriff hört sich zunächst positiv an, steht aber für eine äußerst enge Abstimmung, die typischerweise zu erheblichen Reibungsverlusten führt.

Ein anderes Vorgehen für den Mutually-Dependent-Fall ist der sogenannte Big Ball of Mud, der allerdings kein geschickter Umgang mit wechselseitig abhängigen Teams ist. Der Begriff bezeichnet ein System, das mehrere Bounded Contexts umfasst, aber dermaßen schlecht strukturiert ist, dass praktisch überhaupt keine Struktur zu erkennen ist.

Aufgrund der schlechten Struktur existieren viele Abhängigkeiten. Daraus folgt, dass sich Teams, die gemeinsam an einem Big Ball of Mud arbeiten, eng koordinieren müssen und daher Mutually Dependent sind. Kaum ein Team entscheidet sich bewusst für einen Big Ball of Mud, sondern er entsteht, wenn eine sinnvolle Strukturierung des Systems nicht angegangen wird.

Die Free-Beziehung führt zu vollständiger Unabhängigkeit und daher zu keiner Zusammenarbeit. Daher erscheint es kaum sinnvoll, überhaupt eine Beziehung zwischen Free und einer Kollaboration zu diskutieren.

Dennoch gibt es die Separate-Way-Kollaboration: Wenn Teams zwei Bounded Contexts zwar integrieren können, der Aufwand dafür aber in keinem vernünftigen Verhältnis zum Nutzen steht, können sie sich eine Integration sparen. Voraussichtlich kaum genutzte Schnittstellen kosten gegebenenfalls in der Implementierung mehr Geld, als sie später an Ersparnis einbringen. Durch die Auflösung sind die Teams, die an den beiden Bounded Contexts arbeiten, in einer Free-Beziehung.

Weitere Modelle für die Zusammenarbeit

Darüber hinaus existieren Kollaborationen, die nicht unbedingt Beziehungen beeinflussen:

  • Bei einem Shared Kernel teilen sich die Bounded Contexts den Code, die Akzeptanztests und die Datenbank. Änderungen am Shared Kernel erfordern eine Koordination. Um eine ausreichende Unabhängigkeit der Teams zu erreichen, sollte der Shared Kernel klein sein, um eine Mutually-Depend-Beziehung zu verhindern. Upstream-Downstream ergibt sich ebenfalls nicht zwingend, da die beiden Teams gemeinsam an dem Shared Kernel arbeiten sollen.

  • Eine Published Language ist ein gemeinsames Datenmodell, das nur zur Kommunikation dient. Es kann sich um einen öffentlich publizierten Standard handeln oder um ein in einem Wiki erklärtes Format. Offensichtlich haben die Bounded Contexts dabei eine Beziehung und müssen sich abstimmen, aber ähnlich wie bei Shared Kernel ist die Beziehung nicht eng, weil sie nur ein Datenmodell für die Kommunikation betrifft. Änderungen am Modell lassen sich daher von Anpassungen am internen Modell entkoppeln.

Gute Beziehungen

Gerade für die Strukturierung großer Systeme ist Domain-driven Design nützlich. DDD beschreibt auf der einen Seite Beziehungen, die Teams eingehen, wenn sie sich um einzelne Bounded Contexts kümmern müssen. Da sich die Relationen aus der Aufteilung des Systems ergeben, lassen sie sich nicht direkt beeinflussen.

Daher schlägt DDD einige Kollaborationen vor, um mit den Beziehungen weitgehend gewinnbringend umzugehen. Die Begriffe „Beziehung“ und „Kollaboration“ finden sich übrigens nicht in der DDD-Literatur. Sie helfen aber, die beiden Mechanismen voneinander zu unterscheiden. Einen Überblick bietet die obenstehende Abbildung. Weitere Informationen finden sich bei Eric Evans.

TAGS

Kommentare