EMZETT.
Login

Dependency Injection

Kurz: Bei Dependency Injection (Abhängigkeitsinjektion) bekommt ein Objekt die Dinge, die es braucht, von außen übergeben, statt sie selbst zu erzeugen – meist über den Konstruktor.

Genauer: Dadurch hängt eine Klasse nur von einer Schnittstelle ab, nicht von einer konkreten Umsetzung. Die konkrete Variante wird an einer zentralen Stelle gewählt. Das senkt die Kopplung, macht Code austauschbar und erst richtig testbar (Unit-Tests bekommen Attrappen statt echter Datenbanken).

Im Detail

# ohne DI: fest verdrahtet
class BerichtAlt:
    def __init__(self):
        self.db = MySqlDatenbank()      # kann nicht ausgetauscht werden
 
# mit DI: Abhängigkeit kommt von außen
class Bericht:
    def __init__(self, db):
        self.db = db
 
    def erstelle(self):
        return f"{len(self.db.lade_alle())} Einträge"
 
class FalscheDatenbank:                  # Attrappe für Tests
    def lade_alle(self):
        return ["a", "b", "c"]
 
print(Bericht(FalscheDatenbank()).erstelle())    # 3 Einträge

Arten der Injektion

  • Konstruktor-Injektion (bevorzugt): Abhängigkeiten sind beim Erzeugen vollständig vorhanden.
  • Setter-/Property-Injektion: nachträglich gesetzt, optional.
  • Methoden-Injektion: pro Aufruf übergeben.

DI-Container

In großen Anwendungen übernimmt ein Container das Zusammenbauen: Spring (Java), ASP.NET Core (C#), NestJS und Angular (TypeScript), Dagger (Kotlin). Man registriert, welche Implementierung zu welcher Schnittstelle gehört, und der Container erzeugt die Objekte samt aller Abhängigkeiten.

DI setzt das „D“ der SOLID-Prinzipien um (Dependency Inversion): Hohe Ebenen hängen von Abstraktionen ab, nicht von Details. Verwandt ist das Factory-Muster.

Siehe auch: SOLID, Schnittstelle, Unit-Test, Abstraktion