Lose Kopplung gilt in der Softwarearchitektur als Königsweg zu Wartbarkeit, Flexibilität und Skalierbarkeit – oft gleichgesetzt mit einer (Micro-)Service-basierten Architektur. Doch der Aufwand, den dieser Ansatz mit sich bringt, ist erheblich. Dieser Artikel beleuchtet, wann lose Kopplung zur Laufzeit wirklich notwendig ist – und warum in vielen Fällen ein gut strukturierter, modularer Monolith die sinnvollere Lösung darstellt.
Fragt man Softwarearchitekt:innen nach den wesentlichen Eigenschaften eines optimalen Softwaresystems, so werden wahrscheinlich neun von zehn mit „loosely coupled and highly cohesiv“ antworten. Dinge, die fachlich zusammengehören, landen in einem Modul. Die verschiedenen Module eines Systems selbst wiederum sind weitestgehend unabhängig voneinander. Was aber bedeutet in diesem Kontext „unabhängig“?
Loosely coupled, highly cohesiv gilt als die Erfolgsformel für modulare, wartbare Softwaresysteme. Innerhalb eines Moduls finden sich ausschließlich Bestandteile (z. B. Klassen oder Funktionen), die für einen einzigen, klar definierten Zweck verantwortlich zeichnen und eng miteinander verbunden sind. Dank konsequenter Umsetzung des Single-Responsibility-Prinzips bleiben Module in sich verständlich, überschaubar komplex und damit gut wartbar. Aufgrund des klaren fachlichen Fokus sowie der damit einhergehenden fachlichen Abgrenzung gegenüber anderen Modulen steigt zusätzlich die Chance auf Wiederverwendung.
Entwickle Schnittstellen, die einfach funktionieren
Power-Workshops zu API Design & Entwicklung (22. - 26. Juni 2026, München)
Untereinander weisen die verschiedenen Module des Gesamtsystems dagegen im Idealfall nur minimale Abhängigkeiten auf. Das gilt sowohl während der Entwicklung als auch zur Laufzeit. Der Vorteil liegt klar auf der Hand, denn so können die Module unabhängig voneinander implementiert, geändert, getestet und bereitgestellt werden.
„Unabhängig während der Entwicklung“ bedeutet in diesem Zusammenhang, dass es bei Änderungen oder Erweiterungen innerhalb eines Moduls nicht zu unerwarteten Problemen in anderen Teilen des Systems kommt. „Unabhängig zur Laufzeit“ bedeutet dagegen, dass die Module möglichst wenig miteinander kommunizieren (müssen) und der vorübergehende Ausfall eines Moduls nicht zwangsläufig auch zum Ausfall anderer Module führt.

Während lose Kopplung und hohe Kohäsion als die Bilderbuchlösung für modulare, wartbare Softwaresysteme gelten, führen alle anderen Kombinationen scheinbar zu weniger wünschenswerten Systemen (Abb. 1):
-
Eine enge Kopplung bei geringer Kohäsion führt zu einem monolithischen System, in dem die einzelnen Module keinen eindeutigen Zweck erfüllen, sondern parallel verschiedenen Zielen dienen. Gleichzeitig können einzelne Module ihre Arbeit nicht ohne das Zusammenspiel mit anderen Modulen verrichten. Dieses Konstrukt wird gerne auch als Big Ball of Mud bezeichnet.
-
Eine lose Kopplung bei geringer Kohäsion führt zu einem komplexen System, das sich zwar durch dedizierte Module auszeichnet, die aber keine klar voneinander getrennten Aufgaben haben. Das Resultat ist ein komplexes und gleichzeitig schlecht wartbares System.
-
Eine enge Kopplung bei hoher Kohäsion führt zu einem System, in dem Module zwar von den Aufgabenstellungen klar voneinander getrennt sind, untereinander aber starke Abhängigkeiten haben und so ohne einander nicht funktionieren können. Das muss nicht zwingend ein Problem darstellen, wie wir weiter unten sehen werden.
Licht und Schatten
So vorteilhaft ein lose gekoppeltes System auf den ersten Blick auch zu sein scheint, so komplex kann es im Zweifelsfall werden. Lose Kopplung bringt per Definition eine zusätzliche Abstraktion ins Spiel. Diese geht in der Regel mit einer erhöhten Komplexität und somit einem erhöhten Aufwand zur Umsetzungs- und Laufzeit einher.
Zur Kommunikation zwischen den Modulen müssen APIs wie z. B. REST, GraphQL oder gRPC designt, implementiert, getestet und versioniert bereitgestellt werden. Alternativ kann ein Event-basierter Ansatz gewählt werden. In diesem Fall gilt es, Event-Typen zu definieren, eine Event-Infrastruktur aufzusetzen und diese reliable zur Verfügung zu stellen. Beide Ansätze können beliebig komplex werden. Insbesondere dann, wenn die Module parallel in unterschiedlichen Versionen bereitgestellt werden und deren Kommunikation untereinander entsprechend in verschiedenen Permutationen getestet werden muss.
Zusätzlich müssen Resilience-Pattern implementiert werden, um so im Falle eines (kurzfristigen) Ausfalls eines Moduls nicht das ganze System lahmzulegen, sondern stattdessen bei einer fehlgeschlagenen Kommunikation von zwei oder mehr Modulen mittels doppelten Bodens einen sanften Fall zu ermöglichen. Und das, wenn irgend möglich, voll automatisiert.
Alles nur ein Mythos?
Nimmt man all diese Aspekte zusammen – und wir haben hier nur die Spitze des Eisbergs betrachtet –, stellt sich die Frage, ob lose Kopplung tatsächlich immer das Mittel der Wahl sein muss oder wir hier gegebenenfalls einem Mythos aufgesessen sind.
Der Mythos der losen Kopplung basiert auf dem Missverständnis, dass lose Kopplung automatisch zu einer einfacheren und wartbareren Softwarearchitektur führt. Wie eben gesehen, werden diese Ziele aber nicht ohne zusätzlichen Aufwand erreicht. Die eigentliche Frage, die man sich an dieser Stelle stellen muss, ist somit, ob und wann sich der zusätzliche Aufwand lohnt und wann eher nicht.
Die Antwort auf diese Frage ist nicht ganz so eindeutig, wie es auf den ersten Blick scheint. Denn zum Glück gibt es neben den beiden Extremen – Big Ball of Mud vs. lose gekoppeltes, stark verteiltes Softwaresystem auf Basis von (Mico-)Services – noch einige Alternativen. Dazu aber später mehr.
Wieviel Unabhängigkeit ist genug?
Gehen wir noch einmal einen Schritt zurück und stellen uns die folgende Frage: Was bewegt ein Team dazu, den Schritt weg von einem Monolithen hin zu einem lose gekoppelten, verteilten System zu gehen, wenn sie doch wissen, dass eben dieser Schritt mit erheblichem Aufwand verbunden ist? In der Regel erhoffen sich die Teams Lösungen für die folgenden typischen Problemfelder, die oftmals mit dem monolithischen Ansatz einhergehen: Umsetzungsstau aka Time-to-Market, mangelnde Robustheit, schlechte Releasequalität, hohe Umsetzungskosten, begrenzte Zukunftsfähigkeit, Probleme bei der Skalierung sowohl zur Laufzeit als auch in der Entwicklung.
Wenn man allerdings einen Blick hinter die Kulissen des Monolithen wirft, dann wird schnell klar, dass das eigentliche Problem nicht im Monolithen selbst liegt, sondern vielmehr in der Tatsache, dass dieser über Jahre hinweg historisch gewachsen ist und in dieser Zeit so einiges an technischen und architektonischen Schulden aufgebaut wurde.
Ursprünglich einmal als saubere modulare Architektur angedacht, findet sich in gewachsenen Monolithen häufig eine stark verwässerte Fachlichkeit. Diese spiegelt sich u. a. in der fehlenden Trennung von Zuständigkeiten sowie in ungewollten Abhängigkeiten innerhalb der Architektur wider.
Schafft man es, diese Abhängigkeiten sauber aufzulösen, ist schon einmal sehr viel erreicht und ein großer Teil der oben skizzierten Problemfelder gelöst. Das Resultat wäre ein modularer Monolith – neudeutsch auch gerne als Modulith bezeichnet (Abb. 2).

Stay tuned
Immer auf dem Laufenden bleiben! Alle News & Updates:
Wie erhält man Struktur?
Abhängigkeiten auflösen und dauerhaft saubere Strukturen schaffen – einfacher gesagt als getan. Wie bitte soll das funktionieren? Simon Brown, bekannter Softwarearchitekt und Erfinder der C4-Methode zur Visualisierung von Softwarearchitekturen, sagt dazu „Use encapsulation to minimise the number of potential dependencies“, sowie: „The surface area of your internal public APIs should match your architectural intent“ [1].
Das Problem mit diesem Ratschlag ist allerdings, dass unsere Architekturdiagramme und der dazu gehörige Code meist meilenweit auseinander liegen. Die Architektur sieht zwar eine saubere Trennung der Zuständigkeiten vor, der Code dagegen erlaubt es an vielen Stellen, diese Trennung mit einfachsten Mitteln auszuhebeln.
Ein Grund für dieses Phänomen, das George Fairbanks in seinem Buch „Just enough Software Architecture“ [2] auch passend als „The Code Gap“ bezeichnet hat, ist nicht selten in der verwendeten Programmiersprache zu finden. Die Möglichkeiten zur Einschränkung von Sichtbarkeiten und Zugriffen sind in den meisten Programmiersprachen deutlich zu grob und berücksichtigen das in unserem Fall benötigte Konstrukt eines Moduls nicht oder nur unzureichend.
Zur Einhaltung vorgegebener Architekturrichtlinien ist in vielen höheren Programmiersprachen somit leider kein Verlass auf den Compiler. Stattdessen ist man bei einer monolithischen Codebasis auf viel Disziplin, Codereviews oder externes Tooling angewiesen. Abhilfe können Frameworks – wie z. B. Java Modules oder Spring Modulith – schaffen, die bewusst zwischen public und published unterscheiden und so mittels Compiler den Check auf das Einhalten von Architekturrichtlinien bzgl. des Zugriffs auf das Innere eines Moduls erlauben (Abb. 3).

Deutlich mehr Kontrolle erhält man, wenn das monolithische Deployment-Artefakt (aka Monolith) bewusst aus verschiedenen Development-Artefakten zusammengebaut wird. In diesem Fall könnte jedes (fachliche) Modul in einem eigenen Artefakt verpackt werden. Durch ein dediziertes Dependency Management kann so die Sichtbarkeit der Module untereinander zur Compile-Zeit gezielt eingeschränkt werden.
Ein positiver Nebeneffekt dieses Ansatzes, der auch als Deployment-Monolith bezeichnet wird, ist die losgelöste Testbarkeit einzelner Artefakte. Lediglich die via Dependency-Management angegebenen Abhängigkeiten müssen für den Test via Runtime Classpath bereitgestellt werden.
Den eben beschriebenen Vorteilen steht eine erhöhte Komplexität zur Verwaltung der Dependencies entgegen. Diese Komplexität und der notwendige Testaufwand erhöhen sich noch einmal um ein Vielfaches, wenn die einzelnen Artefakte parallel in unterschiedlichen Versionen vorliegen können. Dieser Ansatz wird häufig gewählt, wenn das Resultat – der Monolith – für verschiedene Mandanten in unterschiedlichen Kombinationen und Releaseständen der Artefakte bereitgestellt und ausgeliefert werden soll.
Nie wieder (Micro-)Services?
Alle drei skizzierten Modularisierungsansätze – Scopes, Artefacts, Repos – resultieren in einem strukturierten Deployment-Monolithen aka Modulith und erfüllen damit bereits einen Großteil unserer Anforderungen an ein modulares und wartbares Softwaresystem.
Es stellt sich die Frage, wann denn dann überhaupt noch der Schritt hin zu einem wirklich lose gekoppelten System auf Basis losgelöster (Micro-)Services Sinn ergibt. Schließlich haben wir ja bereits gelernt, dass dieser Architekturansatz mit einer deutlich höheren Komplexität einhergeht und damit nur dann zur Anwendung kommen sollte, wenn die Vorteile den zu erwartenden Aufwand übersteigen.
Was wir mit den bisherigen Ansätzen noch nicht erreicht haben, ist, dass wir die einzelnen Module unabhängig voneinander bereitstellen, ersetzen und skalieren können – also eine Unabhängigkeit während des Deployments und zur Laufzeit. Wann immer genau dieser Anspruch an Flexibilität an unser System gestellt wird, ergibt der Schritt hin zu losgelösten (Micro-)Services Sinn. Das heißt aber im Umkehrschluss auch, dass wir in nahezu allen anderen Situationen mit einem der drei einfacheren Szenarien auskommen werden.
Fazit
Der Mythos „lose Kopplung“ suggeriert, dass ein wartbares Softwaresystem mit unabhängigen fachlichen Modulen nur mit Hilfe einer (Micro-)Service-basierten Architektur erreicht werden kann. Die beiden Begrifflichkeiten „lose Kopplung“ und „Unabhängigkeit der Module“ werden dabei synonym benutzt und in ihrer Verwendung wird nicht unterschieden, ob diese Unabhängigkeit nur zum Zeitpunkt der Entwicklung und des Testens oder auch zur Laufzeit notwendig ist.
Unabhängigkeit zur Entwicklungs- und Laufzeit lässt sich mit relativ einfachen Mitteln durch eine saubere Modularisierung des Systems via Scopes, Artefakte und Repos erreichen und auch nachhaltig sicherstellen.
Die Erfahrung aus der Praxis hat gezeigt, dass für viele Softwaresysteme eine zusätzliche Unabhängigkeit zur Laufzeit keine zwingende Notwendigkeit darstellt und damit der Aufwand diese zu erreichen und nachhaltig sicherzustellen in keiner gesunden Relation zum potenziellen Nutzen steht.
Der zusätzliche Schritt weg vom modularen Monolithen hin zu einer (Micro-)Service-basierten Architektur lohnt sich in der Regel nur dann, wenn tatsächlich ein Bedarf für eine Unabhängigkeit der Module eines Softwaresystems zur Laufzeit gegeben ist, zum Beispiel, um die Fachlichkeit der verschiedenen Module gezielt unterschiedlich zu skalieren.
Links & Literatur
[1] https://www.youtube.com/watch?v=5OjqD-ow8GE
[2] Fairbanks, George: „Just Enough Software Architecture: A Risk-Driven Approach“; Marshall & Brainerd, 2010
Author
🔍 Frequently Asked Questions (FAQ)
1. Was bedeutet lose Kopplung in der Softwarearchitektur?
Lose Kopplung beschreibt eine Architektur, bei der einzelne Module oder Komponenten möglichst unabhängig voneinander arbeiten. Änderungen an einem Modul sollen andere Teile des Systems nicht beeinflussen. Ziel ist eine bessere Wartbarkeit, Flexibilität und Skalierbarkeit von Softwaresystemen.
2. Was ist ein modularer Monolith beziehungsweise Modulith?
Ein modularer Monolith – oft auch Modulith genannt – ist ein Softwaresystem, das zwar als eine Anwendung deployt wird, intern aber klar in fachliche Module aufgeteilt ist. Dadurch bleibt die Architektur übersichtlich und wartbar, ohne die zusätzliche Komplexität einer Microservices-Architektur.
3. Wann sind Microservices sinnvoll?
Microservices sind besonders sinnvoll, wenn einzelne Teile eines Systems unabhängig voneinander skaliert, deployt oder betrieben werden müssen. Das betrifft häufig große Plattformen mit unterschiedlichen Lastprofilen oder Teams, die unabhängig voneinander entwickeln und veröffentlichen.
4. Welche Nachteile bringt eine Microservices-Architektur mit sich?
Microservices erhöhen die technische Komplexität deutlich. APIs, Event-Infrastrukturen, Monitoring, Resilience-Patterns und Versionsmanagement müssen zusätzlich umgesetzt und betrieben werden. Dadurch steigen Entwicklungs-, Test- und Betriebskosten.
5. Warum gelten modulare Monolithen oft als bessere Alternative?
Ein modularer Monolith kombiniert klare fachliche Trennung mit einer vergleichsweise einfachen Architektur. Viele Unternehmen erreichen damit bereits ausreichend Flexibilität und Wartbarkeit, ohne die zusätzlichen Herausforderungen verteilter Systeme in Kauf nehmen zu müssen.
6. Was ist der Unterschied zwischen lose Kopplung und hoher Kohäsion?
Lose Kopplung beschreibt geringe Abhängigkeiten zwischen Modulen. Hohe Kohäsion bedeutet dagegen, dass zusammengehörige Funktionen innerhalb eines Moduls gebündelt werden. Beide Prinzipien gelten als zentrale Grundlage moderner Softwarearchitektur.
7. Wie lassen sich Monolithen langfristig wartbar halten?
Wartbare Monolithen entstehen durch konsequente Modularisierung, klare Zuständigkeiten und kontrollierte Abhängigkeiten. Technologien wie Java Modules oder Spring Modulith helfen dabei, Architekturrichtlinien technisch abzusichern und saubere Strukturen dauerhaft einzuhalten.




