Modulgrenzen
Eine Modulgrenze kapselt Daten und Regeln einer fachlichen Verantwortung. Andere Module arbeiten über veröffentlichte Verträge mit ihr zusammen. Der Kern ist Information Hiding nach David Parnas: Ein Modul verbirgt die Entscheidungen, die sich wahrscheinlich ändern, hinter einem stabilen Vertrag.
- Öffentlicher VertragDie einzige Tür in das Modul.
- InternaRegeln und Daten bleiben verborgen.
- DurchsetzungEine Grenze gilt nur, wenn Verstöße auffallen.
Einordnung
Warum das wichtig ist
Ohne durchgesetzte Grenze greift jedes Modul auf die Daten jedes anderen zu. Regeln wie die Bestandsprüfung lassen sich dann umgehen, und Änderungen ziehen weite Kreise. Die Richtung von Abhängigkeiten behandelt Dependency Inversion.
Dieser Baustein erklärt Grenzen innerhalb einer Anwendung. Für Geltungsbereiche verschiedener Fachmodelle siehe Bounded Context.
Auf einen Blick · Modul mit öffentlichem Vertrag
Öffentliche Grenze des Lagermoduls
Im modularen Shop besitzt das Lagermodul Bestände und Reservierungen. Das Bestellmodul darf Bestand reservieren, jedoch keine Lagertabelle direkt ändern.
So liest du das Bild
- Öffentlicher Vertrag Der Kasten Lagervertrag im Bereich Lager · öffentlich.
- Interna Die Kästen Bestandsregeln und Lagerdaten im Bereich Lager · intern.
- Durchsetzung Die Tabelle: Stufen 1 bis 5, von Absprache bis eigener Dienst.
Diagramm als Text lesen
- Bestellung: fordert Reservierung an (Shop-Anwendung)
- Lagervertrag: reservieren, freigeben (Lager · öffentlich)
- Bestandsregeln: prüfen und ändern (Lager · intern)
- Lagerdaten: Bestand und Reservierung (Lager · intern)
- Bestellung → Lagervertrag: reservieren
- Lagervertrag → Bestandsregeln: Regel anwenden
- Bestandsregeln → Lagerdaten: Bestand ändern
Wie hart ist die Grenze?
| Stufe | So wird die Grenze gezogen | Schützt vor | Kostet |
|---|---|---|---|
| 1 · Absprache | Doku: Lagertabellen nicht direkt nutzen | nichts Verbindlichem | fast nichts |
| 2 · Sichtbarkeit | Interna sind im Code nicht öffentlich (Pakete, Module) | versehentlichen Aufrufen | wenig |
| 3 · Architekturtest | Build bricht bei Zugriff auf Lager-Interna (ArchUnit, Spring Modulith) | allen Code-Zugriffen | Pflege der Tests |
| 4 · Datenbankrechte | eigenes Schema, Bestellung ohne Rechte auf Lagertabellen | SQL-Zugriffen am Code vorbei | Schema-Verwaltung |
| 5 · Eigener Dienst | Lager läuft als getrennter Dienst | allem außer dem Vertrag | Betrieb, Netzwerk, verteilte Fehler |
Nutzen & Grenzen
Hilft, wenn
- Mehrere Teams oder Teile greifen auf gemeinsame interne Strukturen zu und benötigen eindeutigen Besitz.
- Interne Änderungen sollen Verbraucher möglichst selten zur Anpassung zwingen.
Grenzen
- Eine Grenze, die niemand durchsetzt, erodiert schleichend: Aus „nur kurz“ wird Dauerzustand (Architekturerosion). Wähle deshalb mindestens eine Stufe aus der Tabelle oben, die Verstöße sichtbar macht.
- Falsch gezogene Grenzen sind teuer. Zu fein geschnittene Module verursachen viel Vertragsarbeit, und eine spätere Verschiebung ist aufwendig. Starte lieber gröber und teile nach realen Änderungsmustern (Kohäsion).
In der Praxis
- Besitz und Verantwortung festlegen. Benenne Daten und Regeln, für die das Modul zuständig ist. Das Ergebnis ermöglicht eine klare Entscheidung, wer Änderungen daran freigibt.
- Öffentlichen Vertrag gestalten. Beschreibe fachliche Operationen, zulässige Eingaben und Fehlerzustände. Richte Abhängigkeiten an diesem Vertrag aus, wie es Dependency Inversion vorsieht.
- Zugriffe technisch durchsetzen. Begrenze direkte Nutzung interner Daten und teste den Vertrag aus Sicht der Verbraucher. Prüfe zugleich, ob die Grenze ausreichend Kohäsion besitzt.
- Vergleiche Wertstrom und Modulgrenze. Verfolge eine neue Lieferoption vom Kundenbedarf bis zur nutzbaren Shopfunktion. Prüfe gemeinsame Regeln, benötigtes Wissen und Übergaben; bündle zusammengehörige Verantwortung und mache nötige Abstimmung über Modulgrenzen sichtbar.
Ausführliche Erklärung lesen
Ein Modul besitzt eine definierte Verantwortung und kontrolliert, wie andere Bausteine seine Fähigkeiten nutzen. Sein Vertrag beschreibt erlaubte Operationen und Ergebnisse, während interne Datenstrukturen verborgen bleiben. Kopplung betrachtet Folgen über die Grenze; Dependency Inversion richtet Quellcodebeziehungen auf stabile Verträge aus.
Eine Grenze wirkt nur, wenn tatsächliche Zugriffe sie einhalten. Importregeln, Datenbankrechte und Vertragstests können Umgehungen sichtbar machen. Die Granularität folgt dem fachlichen Zusammenhang: Zu große Module verbergen unabhängige Verantwortungen; zu kleine erzeugen unnötige Übergaben und Abstimmung.
Ein unabhängiger Wertstrom (Independent Value Stream) führt von einem fachlichen Bedarf zu einem nutzbaren Ergebnis. Für den Modulzuschnitt helfen gemeinsame Begriffe, Regeln und Änderungsmuster: Gehören Preisberechnung und Zahlung wirklich zusammen, oder teilen sie nur den Oberbegriff „Geld“? Prüfe anschließend Teamzuständigkeit und kognitive Last. Team Topologies liefert dafür eine ergänzende organisatorische Perspektive.
Selbst prüfen
Teste dich in drei Stufen
AblesenIm Bild nachsehen
Welche Operationen bietet der Lagervertrag laut Bild an?
Lösung mit Begründung ansehen
Reservieren und freigeben.
AnwendenAuf eine neue Lage übertragen
Ein Entwickler greift per SQL direkt auf die Lagertabelle zu, der Architekturtest bleibt grün. Welche Stufe fehlt?
Lösung mit Begründung ansehen
Stufe 4, Datenbankrechte. Der Architekturtest prüft nur Code und sieht SQL-Zugriffe am Code vorbei nicht.
BewertenEine Alternative abwägen
Das Bestellmodul soll Reservierungen direkt in die Lagerdaten schreiben, um einen Aufruf zu sparen. Wie bewertest du das?
Lösung mit Begründung ansehen
Das spart einen Zwischenschritt. Dafür würden die Bestandsregeln umgangen und jede Änderung der Lagerdaten beträfe die Bestellung. Die Grenze schützt Regeln und Daten im Lager.
Vertiefen
Diese Bausteine führen die Gedanken dieser Seite weiter.
Quellen
- On the Criteria To Be Used in Decomposing Systems into Modules (öffnet in neuem Tab)Grundlagenpapier von David Parnas zu Information Hiding. Der Volltextzugang beim Verlag kann eingeschränkt sein.
- Spring Modulith · Fundamentals (öffnet in neuem Tab)Zeigt fachliche Module und überprüfbare Abhängigkeiten in einer Anwendung.
- ArchUnit (öffnet in neuem Tab)Bibliothek, mit der Architekturregeln als Test geprüft werden und der Build bei Verstößen bricht.
- Team Topologies · Key Concepts (öffnet in neuem Tab)Wertstromorientierte Teams, Zusammenarbeit und kognitive Last als Perspektiven auf Teamzuschnitt.