Wie kaum ein anderes Prinzip, hat das
Dependency Inversion Prinzip in den nunmehr fast 20 Jahren seit
seinen ersten Anfängen einen Siegeszug durch die Softwaretechnik
angetreten, und das auch ohne von seinen Anwendern in der letzten
Tiefe verstanden worden zu sein. Die Ursache hierfür liegt
insbesondere in der Verbreitung von Dependency Injection Containern
wie Spring, welche den Entwickler fast automatisch zu einem
Entwurfsstil führen, der dem DIP folgt. Die Liste der hier
behandelten S.O.L.I.D.-Prinzipien ist somit komplett.
Name, Kurzform | Dependency Inversion Prinzip |
Synonyme |
Umkehr
der Abhängigkeiten,
DIP |
Beschreibung |
Robert
C. Martin formulierte dieses Prinzip in einer frühen Fassung
[Martin 1996] zunächst in insgesamt vier Sätzen, die beim ersten Lesen wenig
eingängig erscheinen:
„A.
Module hoher Ebenen sollten nicht von Modulen niedriger Ebenen
abhängen. Beide sollten von Interfaces abhängen. B. Interfaces
sollten nicht von Details abhängen. Details sollten von
Interfaces abhängen.“
Dabei spricht Martin in der Version von 1996 noch nicht von „Interfaces“, sondern von
„Abstraktionen“ (was der Fokussierung auf C++ geschuldet ist).
Eine kürzere Fassung liefert Martin heute in seinem Blog:
„Erlaube
Abhängigkeiten von Abstraktionen, nicht von Spezialisierungen.“ |
Erläuterung |
Trotz
der umständlicheren Formulierung lohnt ein Blick auf die
ursprüngliche Version des Prinzips: Das zu Grunde liegende
Bild ist eine Modul-Hierarchie: Module (höherer Ebenen) enthalten
Module (niedrigerer Ebenen) und delegieren einen Teil der Arbeit
an diese. Das zu Grunde liegende Konstruktionsprinzip ist „Teile
und herrsche“. Komplexe Software entsteht durch die Komposition
kleinerer Module zu immer komplexeren Modulen.
Martin
fordert nun, dass das in der Hierarchie höherwertige Modul nur
die Abstraktion (das Interface) seiner Dienstmodule kennen darf
und nicht die Dienstmodule selbst.
Stellt
man sich eine tiefe Modul-Hierarchie vor, so könnten sich
Änderungen auf einer tiefen Modul-Ebene bis in die höchsten
Ebenen auswirken, wenn diese Bedingung nicht erfüllt würde.
Umgekehrt wäre es nicht möglich, höhere Ebenen ohne sämtliche
Implementierungs-Details niederer Dienstmodule zu anderen Zwecken
wiederzuverwenden, sei es auch nur für Testzwecke.
Genau dies wird durch
Abstraktion erreicht: Zwischen höherwertigen Modulen und
niederwertigen wird eine Schicht eingezogen. Die Delegation
erfolgt nicht an einen konkreten Dienstleister, sondern an diese
Abstraktionsschicht. Hierachisch aufgebaute Systeme werden auf
diese Weise systematisch von Implementierungs-Details entkoppelt.
Details werden austauschbar. |
Beispiele |
|
Historie |
|
Art des Prinzips |
|
Grad der formalen Spezifikation | Hoch, da syntaktisch überprüfbar. |
Vorteile |
|
Nachteile |
Die
Nachteile der Abstraktion:
|
Übergeordnete Prinzipien |
|
Abgleitete Prinzipien | - |
Qualitätsmerkmale | Änderbarkeit (+), Testbarkeit (+), Wiederverwendbarkeit (+), Verständlichkeit (-), Einfachheit (-) |
Quellen:
[Martin 1994] – OO Design Quality
Metrics - An analysis of dependencies, Robert C. Martin (1994),
hier als PDF-Dokument verfügbar
[Martin 1996] – The Dependency
Inversion Principle, Robert C. Martin, C++ Report (1996)
[Martin 2002] – Agile
Software Development. Principles, Patterns, and Practices,
Robert C. Martin (2002)