Seite wählen

Wenn man beginnt zu programmieren und mit Objekt orientierter Programmierung gerade erst anfängt, baut man in den meisten Fällen unbemerkt Abhängigkeiten auf. Und zwar Abhängigkeiten von oberen Schichten also High-Level Schichten an untere Low-Level Schichten. Und das ist immer doof.

Warum? Weil sich die Anforderungen im Business Betrieb häufiger ändern, als man sich am Anfang eines Projektes gedacht hat. Nehmen wir an Dein Chef kommt morgen rein und sagt die, dass er allen seinen Kunden ab morgen anstatt CSV Dateien XML Dateien schicken will und in Zukunft vielleicht irgendwann auch noch PDF, und HTML und was auch immer für Dateiformate dazukommen werden. Ach so, ja, und die ganzen Formate sollen dann auch alle noch gelesen werden können. Dein System ist aber nun mal komplett hart auf CSV Dateien ausgelegt und macht genau das, was am Anfang mit der Geschäftsleitung vereinbart war.

Die Abhängigkeiten der High-Level Module von Low-Level Modulen muss invertiert also umgekehrt werden. Ein High-Level Modul ist alles, was irgendwas Anderes aufruft. Und beide Schichten die High- sowie die Low-Level Schicht sollten von sogenannten Abstraktionen abhängen. Und der einfachste Weg, um das zu erreichen ist mit einer Schnittstelle und einem Interface. Ein Interface erzwingt das Implementieren von bestimmten Methoden, die dann in der implementierenden Klasse eingebaut werden müssen. Abstraktionen sollen nicht von Details abhängen. Das heißt, die Abstraktionen sollten kein wissen darüber haben müssen, wie bestimmte Dinge erledigt werden, sondern nur dass sie erledigt werden. Und das ist dann eine saubere Schnittstelle. Und wenn wir Dependency Inversion gut machen, dann sind unsere Schnittstelle automatisch sauber.

Immer wenn wir „new“ verwenden, dann sind das immer feste Abhängigkeiten von Low-Level Modulen und Du solltest versuchen, diese Abhängigkeiten so weit wie es geht durch das Benutzen von zum Beispiel Interfaces, Factories oder Dependency Injection aufzulösen. Das Ergebnis ist, dass wir einzelne Module hinzufügen können und sie nur an einer einzigen Stelle austauschen brauchen anstatt Teile der Anwendung neu schreiben zu müssen. Wir haben also nicht mehr die eine große monolithische Codebase, sondern ein modulares System, dass flexibel auf Änderungen der Anforderungen reagieren kann. Jedes dieser kleinen Teile der Appliaktion tut genau eine Sache und ist somit austauschbar.

Vorteil ist also, dass es separate testbare Module gibt, in die man sogenannte Mockobjekte injizieren kann, über deren Inhalte, also Ein- und Ausgaben, man volle Kontrolle hat. So Laufen keine zufälligen Daten in den Test und verfälschen diesen.

Beispielcode gibts hier: https://github.com/DesertCoderz/DependencyInversion