Dependency Injection

Dependency Injection (DI) ist ein Begriff, der im Zusammenhang mit der objektorientierten Programmierung steht. Damit wird ausgedrückt, dass Module ( Objekte, Klassen) ihre Abhängigkeiten - Informationen oder ein bestimmtes Verhalten durch den Aufruf von Methoden - von einer anderen, externen Instanz zugewiesen bekommen, was dann auch als Injektion bezeichnet wird. Diese Injektion wird von einem DI-Framework - wie etwa dem Spring oder Unity-Framework - durchgeführt. Eng verknüpft mit dem Begriff der Dependency Injection ist das Prinzip Inversion of Control - die Umkehrung des Kontrollflusses. Es lassen sich mit Setter Injection, Constructor Injection und Interface Injection drei verschiedene Arten von Dependency Injection unterscheiden.


Damit werden auch die Ebenen deutlich, auf denen die Injektion erfolgt. Das Ziel der Verwendung von DI ist es, Abhängigkeiten zwischen Modulen zu minimieren. Dependency Injection ist auch ein Konzept, was als Bestandteil einer Software-Architektur verwendet werden kann. Der Begriff der Dependency Injection wurde durch Martin Fowler geprägt und eingeführt. Unter dem u.g. Link ist eine ausführliche Beschreibung von Martin Fowler zu diesem Thema verfügbar.

Inversion of Control

Bereits seit Beginn der Objektorientierung ist das Prinzip des Inversion of Control (IoC) ein in diesem Zusammenhang diskutierter Aspekt. Aber erst im Verlauf der weiteren Entwicklung von objektorientierten Programmiersprachen und Konzepten wie beispielsweise im Umfeld von C++, Java, Python u.a. wurde dieses Thema wieder populärer; obwohl das Prinzip keineswegs eine neue Erfindung ist. Nunmehr ist Inversion of Control als ein allgemeines Merkmal von Frameworks zu verstehen, was man im allgemeinem Sprachgebrauch auch als das sogenannte Hollywood-Prinzip "Don´t call us, we´ll call you!" bezeichnet. Damit liegt die Verantwortlichkeit bei der Programmausführung auf Seiten des Frameworks - was auch als umgekehrter Kontrollfluss bezeichnet wird. Damit liegt die Verantwortlichkeit ausdrücklich nicht bei den Komponenten, die auf Grundlage dieses Frameworks entwickelt wurden. Dazu müssen die entsprechenden Module sogenannte Callback-Methoden (Callbacks) implementieren. Dabei wird die Laufzeit-Umgebung für das Framework durch einen Container zur Verfügung gestellt. Die Callbacks geben dem Framework während der Laufzeit die Möglichkeit der Übergabe - der Injektion - von Informationen an diese Module oder auch durch Injektion ein bestimmtes Verhalten von Module durch den Aufruf ihrer Methoden zu realisieren. So kann auch der Lebenszyklus eines kompletten Moduls von außen durch die Callbacks beeinflusst werden.

Dependency Injection (DI) ist eine spezielle Form des Inversion of Control-Prinzips, das von Martin Fowler definiert und eingeführt wurde. Der Hintergrund war die vorwiegende Nutzung des Inversion of Control-Prinzips für die Injektion von Referenzen auf benötigte Ressourcen durch leichtgewichtige Frameworks wie Spring und Container wie PriceContainer oder Excalibur. Durch DI können Dienste sogenannter Service-Fabriken nach außen hin verborgen werden. Als Fabriken werden in der Objektorientierung Objekte bezeichnet, die wiederum andere Objekte erzeugen können. So sollen durch die Nutzung von DI keine Abhängigkeiten zwischen Modulen und Klassen entstehen. Die Verantwortlichkeit für das Zusammenwirken von Modulen liegt in jedem Fall beim Framework, das dazu weitergehende Informationen bezüglich der Konfigurationen dieser Module benötigt. Diese werden entweder direkt in den Code integriert oder aber stehen separat in einer Konfigurationsdatei - häufig eine XML-Datei - zur Verfügung. Die Übergabe von genutzten Objekten an zu nutzende Objekte wird also immer auf Basis dieser Konfigurationsinformationen erfolgen. Die Wahl der Konfiguration ist abhängig vom jeweils vorliegenden Einzelfall.

Die verschiedenen Formen der Dependency Injection

Verschiedene Arten von IoC

Verschiedene Arten von IoC

Es gibt drei grundlegend verschiedene Formen von Dependency Injection bei der Übergabe von Modulen:

Setter Injection. Das DI-Framework sorgt über die Setter-Methode dafür, dass ein benötigtes Modul injiziert wird.

Constructor Injection. Beim Constructor Injection werden die benötigten Module als Argument des Konstruktors einer Klasse übergeben.

Interface Injection. Hier erfolgt die Injektion über explizit implementierte Schnittstellen (interfaces) sowohl auf Seiten des genutzten Moduls als auch vom nutzenden Modul. Diese Möglichkeit der Injektion wird in der Praxis jedoch vermieden, da sich durch die Implementierung der Interfaces wiederum Abhängigkeiten ergeben.

Vorteilhaft anzuwenden ist DI bei der Zusammenführung einer Anwendung aus verschiedenen Modulen. Dabei können durch das Verfahren verschiedene Arten der Konfiguration unterstützt werden. Durch die Zuordnung von Modulen zu einer Konfiguration können durch das Framework beliebige Formen der Konfiguration beispielsweise spezielle Server-Konfigurationen oder Test-Konfigurationen aufgebaut werden. Dabei liegt der Schwerpunkt von Dependency Injection auf der Entkopplung von Modulen, die ansonsten keinerlei Berührung haben. Dependency Injection ist nicht als Ersatz für Fabriken anzusehen. Bei der Konfiguration der Module über separate Dateien gibt es aber auch einen großen Nachteil für den Entwickler - die Abläufe einer Applikation sind ohne genaue Kenntnis der Konfigurationsdatei nicht mehr nachvollziehbar.

Für unterschiedliche Programmiersprachen sowie Plattformen gibt es die verschiedensten Frameworks, die Dependency Injection unterstützen:

  • Für Java: Spring, EJB 3.0, Seam, Guice.
  • Für .NET: Unity, Ninject, ObjectBuilder, LightCore, PicoContainer, Structuremap.
  • Für Python: PyContainer.
  • Für Ruby: Needle,Copland.
  • Für C++: DSM.
  • Für PHP5: Garden, Symfony Components, Stubbles IoC.
Eine alternative Möglichkeit zur Dependency Injection sind sogenannte Service Locator - damit bezeichnet man ein übergeordnetes Verzeichnis von Diensten. Der Service Locator kennt für alle Dienste, die eine Applikation benötigt, eine entsprechende Realisierung und stellt sie dieser auf Anfrage zur Verfügung. Da hier jedoch nichts geschieht ohne dass das nutzende Modul explizit anfragt, kann nicht von einer Umkehrung des Kontrollflusses - der Voraussetzung für Dependency Injection - gesprochen werden.

http://www.martinfowler.com/articles/injection.html

Informationen zum Artikel
Deutsch: Dependency Injection
Englisch: dependency injection - DI
Veröffentlicht: 17.03.2010
Wörter: 906
Tags: #Entwicklung, Codierung
Links: .NET, Aspekt, C++, Code, Container