2015-08-05 5 views
7

Im Allgemeinen sind meine Abhängigkeiten zu Schnittstellen abstrahiert, aber ich werde nur eine konkrete Implementierung während der nicht testing Verwendung verwenden. Zum Beispiel gab ich ein FooService schreiben:Dependency Injection: was verlieren Sie beim Instanziieren konkreter Klassen im parameterlosen Konstruktor

public class FooService : IFooService 
{ 
    private readonly IBarDependency _barDependency; 

    public FooService(IBarDependency barDependency) 
    { 
     this._barDependency = barDependency; 
    } 

    public FooService() : this (new BarDependency()) 
    { 
     // nothing to do here 
    } 

    . . . // code goes here 
} 

Jetzt Puristen neigen entsetzt nach Luft zu schnappen, weil ich eine konkrete Klasse im Konstruktor instanziiert parameterlos. Ich habe dies in der Vergangenheit mit einem Achselzucken abgetan, weil ich weiß, dass ich die konkrete Klasse nur dann nicht verwenden werde, wenn ich Abhängigkeiten teste und verspotte.

Während es tut Paar die FooService Klasse in die BarDependency Klasse, es ist kein eng Kupplung; Diese Klassen und Interfaces existieren auch in der gleichen Assembly, daher scheint es mir nicht so, als ob ich hier viel verliere oder mich in eine Ecke male. Ich kann die Klasse FooService immer noch leicht testen, ohne Code zu bekommen, der nicht manipulierbar ist, nur indem ich den Konstruktor benutze, der es mir erlaubt, überspannte Schnittstellen zu übergeben.

Die Frage ist also: Was ist hier eigentlich gefährdet? Was verliere ich mit diesem Muster, das einen IoC-Container wert ist?

+0

Ich verwende den gleichen Ansatz in kleinen Projekten. DI und andere "doing it right" -Regeln machen kleine Projekte meist zu komplex. Sicher, es bringt viele Vorteile, aber es ist nicht immer die Mühe wert. –

Antwort

6

Lebensdauerverwaltung, zum Beispiel. Vielleicht verwenden Sie in Ihrem Code BarDependency und möchten nur eine Instanz am Leben erhalten. Dies ist nicht möglich, wenn jeder Benutzer eigene Instanzen erstellt.

Sie müssen auch alle Verwendungen von new BarDependency() finden, wenn Sie es jemals mit new NewBarDependency() ersetzen möchten.

Ein Container behebt beide Probleme für Sie, da Sie dann die Instanziierung und den Lebenszyklus von Objekten in einer Methode konfigurieren, nämlich wo Sie Ihren Container einrichten.

+0

Sie schlagen also vor, dass IoC-Container besser für Singleton-Pattern-Injektionen geeignet sind? Das macht Sinn. –

+1

Ja, Sie können eine Lebensdauer von "einmal pro Anwendungsdomäne" verwenden, sodass Sie keine Singletons oder statischen Klassen benötigen. – CodeCaster

1

Was Sie ohne Abhängigkeitsinjektion verlieren, ist die Fähigkeit, alle Aspekte des Abhängigkeitsmanagements zu zentralisieren. Das Visualisieren des Abhängigkeitsdiagramms und das Verwalten der Lebenszyklen Ihrer Objekte ist einfacher, wenn Sie alle Informationen an einem Ort haben und nicht über den gesamten Code verstreut sind.

Ein konkretes Beispiel wäre, wenn Sie die Standardimplementierung von IBarDependency ersetzen möchten, die in einigen, aber nicht in allen Klassen verwendet wird. Der Grund dafür, welche zu ersetzen sind, ist viel einfacher, wenn die Abhängigkeiten alle in der gleichen Datei oder Gruppe von Dateien verdrahtet sind.

2

Es kommt darauf an, aber wenn auf den FooService von einem anderen Entwickler zugegriffen werden muss, wird die Abhängigkeit von BarDependency grundsätzlich ausgeblendet. Meiner Meinung nach ist nicht nur das Mocking und Testen der Grund für die Verwendung der Abhängigkeitsinjektion, sondern auch ein klarer Hinweis darauf, was von bestimmten Klassen verwendet wird und was sie richtig arbeiten müssen. Und vielleicht bin ich zu sehr puristisch, aber wenn ein solches Muster in Ordnung ist, dann ist es einfach, weiter zu gehen und am Ende mit einem total eng gekoppelten und harten, wartbaren Code zu enden.