Prinzip der Abhängigkeitsinversion vs "Programm auf eine Schnittstelle, keine Implementierung"

12

Ich versuche zu verstehen, wie sich das Prinzip der Abhängigkeitsinversion vom Prinzip "Programm zu einer Schnittstelle, nicht zu einer Implementierung" unterscheidet.

Ich verstehe, was "Programmieren auf eine Schnittstelle, keine Implementierung" bedeutet. Ich verstehe auch, wie es flexiblere und wartbarere Designs ermöglicht.

Ich verstehe jedoch nicht, wie sich das Prinzip der Abhängigkeitsinversion vom Prinzip "Programm zu einer Schnittstelle, nicht zu einer Implementierung" unterscheidet.

Ich habe an mehreren Stellen im Internet über DIP gelesen, was meine Verwirrung nicht beseitigt hat. Ich sehe immer noch nicht, wie sich die beiden Prinzipien voneinander unterscheiden. Danke für Ihre Hilfe.

Aviv Cohn
quelle

Antworten:

25

"Auf eine Schnittstelle programmieren" bedeutet , dass Sie für Ihre Arbeit nicht von einem konkreten Typ abhängig sind , aber nicht angeben, wie Sie Ihre Abhängigkeit erhalten sollen.

Das "Prinzip der Abhängigkeitsinversion" besagt, dass ein Objekt die Erstellung seiner Abhängigkeiten nicht steuern sollte, sondern nur die benötigte Abhängigkeit ankündigen und vom Aufrufer bereitstellen lassen sollte . Es wird jedoch nicht angegeben, ob die Abhängigkeit ein konkreter Typ oder eine Schnittstelle sein soll.

Ich werde die Unterschiede mit etwas C # -Code veranschaulichen.

Das folgende Beispiel hängt von einem konkreten Typ ab und steuert die Erstellung der eigenen Abhängigkeit. Es folgt weder "Programm auf eine Schnittstelle" noch "Abhängigkeitsinversion":

public class ThingProcessor
{
    MyThing _myThing;

    public ThingProcessor()
    {
        _myThing = new MyThing();
    }

    public void DoSomething()
    {
        _myThing.DoIt();
    }
}

Das folgende Beispiel hängt von einer Schnittstelle ab, steuert jedoch die Erstellung der eigenen Abhängigkeit. Es folgt "Programm zu einer Schnittstelle", aber nicht "Abhängigkeitsinversion":

public class ThingProcessor
{
    IMyThing _myThing;

    public ThingProcessor()
    {
        _myThing = ThingFactory.GiveMeANewMyThing();
    }

    public void DoSomething()
    {
        _myThing.DoIt();
    }
}

Das folgende Beispiel hängt von einem konkreten Typ ab, fordert jedoch an, dass seine Abhängigkeit erstellt und an ihn übergeben wird. Es folgt "Abhängigkeitsinversion", aber nicht "Programmieren auf eine Schnittstelle":

public class ThingProcessor
{
    MyThing _myThing;

    public ThingProcessor(MyThing myThing)
    {
        _myThing = myThing;
    }

    public void DoSomething()
    {
        _myThing.DoIt();
    }
}

Das folgende Beispiel hängt von einer Schnittstelle ab und fordert dazu auf, dass deren Abhängigkeit erstellt und an diese übergeben wird. Es folgt sowohl "Abhängigkeitsinversion" als auch "Programm auf eine Schnittstelle":

public class ThingProcessor
{
    IMyThing _myThing;

    public ThingProcessor(IMyThing myThing) // using an interface
    {
        _myThing = myThing;
    }

    public void DoSomething()
    {
        _myThing.DoIt();
    }
}
Eric King
quelle
1
Hervorragende Darstellung des Unterschieds.
Rory Hunter
8
Sie sprechen von einer abhängigen Injektion. Und Abhängigkeitsinversion und Abhängigkeitsinjektion sind zwei verschiedene Dinge.
Euphoric
1
@Euphoric Ich spreche über das Prinzip der Abhängigkeitsinversion, das ein abstraktes Konzept ist, indem ich die Abhängigkeitsinjektion als konkretes Implementierungsbeispiel verwende. Ich verstehe den Unterschied.
Eric King
1
@EricKing Dann sollten Sie ausdrücklich sagen, dass in Ihrer Antwort "Das" Abhängigkeitsinversionsprinzip "sagt ...", was offensichtlich falsch ist, wenn Sie meine Antwort lesen.
Euphoric
1
Ich stimme Euphoric zu. Das Prinzip der Abhängigkeitsinversion besagt, dass übergeordnete Codeebenen von untergeordneten Codeteilen abhängen sollten und nicht umgekehrt. ZB PrintStreamsollte von der von eingerichteten Schnittstelle abhängen ByteOutputStream. Die Abhängigkeitsinjektion erwähnt nichts darüber, wer von wem abhängen sollte.
Doval
5

Sie sind im Allgemeinen dasselbe. Wenn Sie lesen Was ist das Prinzip der Abhängigkeitsinversion und warum ist es wichtig? und Abhängigkeitsinversionsprinzip werden Sie erkennen, dass die beiden "Prinzipien" im Grunde genommen über dasselbe sprechen.

  • High-Level-Module sollten nicht von Low-Level-Modulen abhängen. Beides sollte von Abstraktionen abhängen.
  • Abstraktionen sollten niemals von Details abhängen. Details sollten von Abstraktionen abhängen.

Schnittstelle ist eine Abstraktion und Implementierung ist ein Detail. Wenn Sie sie in den beiden vorherigen Anweisungen ersetzen, erhalten Sie im Grunde "Code sollte von Schnittstellen und nicht von Implementierungen abhängen". Und das klingt für mich genauso.

Euphorisch
quelle
Dies sollte die akzeptierte Antwort sein, die andere am meisten
gewählte
2

Schnittstellen sind eine Möglichkeit, DI zu implementieren. Wenn Sie eine Schnittstelle als Parameter in der Konstruktormethode einer Klasse angeben, können Sie ein beliebiges Objekt an diese Konstruktormethode übergeben, sofern dieses Objekt die Schnittstelle des Konstruktorparameters implementiert.

Mit anderen Worten, durch Programmieren einer Schnittstelle können Sie die Implementierung dieser Schnittstelle ändern . Auf diese Weise können wir beim Testen von Einheiten reale Objekte durch Scheinobjekte ersetzen, verschiedene Datenanbieter angeben usw.

Robert Harvey
quelle