Dependency Injection und der Injektor

Dependecy Injection ist auch unter dem Namen Inversion of control bekannt. Bevor wir zeigen, welche Kontrolle dies umkehrt und welche Vorteile sich daraus ergeben, zeigen wir zuerst den klassischen Weg.

Der klassische Weg

Klassisch kümmert sich eine Funktion selber um das instanziieren von weiteren Objekten. Gucken wir uns folgende Funktion an:

function findUser(user){
  var db = new Database(...);
  db.find('users', user);
}

Die Funtkion findUser sucht einen Benutzer aus einer Datebank-Tabelle heraus. Dazu muss eine Verbindung zu einer Datenbank hergestellt werden. findUser kümmert sich selber darum, das ensprechende Objekt Database zu instanziieren. Die Kontrolle, Objekte zu erstellen liegt somit bei der Funktion selbst.

Mit Dependecy Injection

Mit Dependency Injection wird die Kontrolle über das Instanziieren der Funktion entzogen. Die Kontrolle hat jetzt eine zentrale Stelle, die diese Arbeit erledigt. Diese zentrale Stelle nennen wir Injektor. Die Funktion muss nicht wissen, woher db kommt und wie db instanziiert wird. Wir könnten also Folgendes schreiben:

function findUser(db){
  db.find('users', user);
}

Der Injektor und die richtige Reihenfolge

Der Injektor kann nicht nur Instanzen erzeugen, sondern kümmert sich auch darum, diese in die richtige Reihenfolge zu setzen. Nehmen wir ein Beispiel mit untereinander abhängigen Services:

AngularJS - Injektor

Als Pseudo-JavaScript würden wir die Services folgendermaßen erzeugen:

service 'S1', function(S2, S5, S6)
service 'S2', function(S3, S4, S5)
service 'S3', function(S6)
service 'S4', function(S3, S5)
service 'S5', function()
service 'S6', function()

Der Injektor von AngularJS löst den Baum von Abhängigkeiten korrekt auf und sorgt für die richtige Reihenfolge beim Instanziieren: S6, S3, S5, S4, S2, S1.

Welche Vorteile bringt Dependency Injection?

  • Der Code ist modularer und wiederverwendbar
  • Der Code ist meistens wartbarer
  • Der Code einfacher zu testen
  • Das API ist simpler und abstrakter

Der Injektor von AngularJS

Der Injektor von AngularJS erkennt die benutzten Services anhand der Parameternamen. Im Folgenden werden Database DBUsername und DBPassword übergeben. Der Injektor sucht dementsprechend nach Services mit den Namen DBUsername und DBPassword.

app.value('DBUsername', 'root');
app.value('DBPassword', 'secret');
app.factory('Database', function(DBUsername, DBPassword) { ... });

Diese Konvention ist sinnvoll, um sich zusätzliche Konfigurationsdateien zu sparen. Alternativ müsste nämlich eine Mapping-Datei erstellt werden, die Funktionsnamen mit entsprechenden Abhängigkeiten enthält.

AngularJS benutzt Dependency Injection durchgehend.



Dieses Kapitel auf GitHub erweitern oder verbessern