依存関係反転の原理と「実装ではなく、インターフェイスへのプログラム」


12

Dependency Inversion Principleが「実装ではなくインターフェイスへのプログラム」原則とどのように異なるかを理解しようとしています。

「実装ではなく、インターフェイスへのプログラム」の意味を理解しています。また、より柔軟で保守可能な設計を可能にする方法も理解しています。

しかし、依存関係反転の原則が「実装ではなくインターフェイスへのプログラム」の原則とどのように異なるかはわかりません。

Web上のいくつかの場所でDIPについて読みましたが、混乱は解消されませんでした。2つの原則がどのように異なるかはまだわかりません。ご協力いただきありがとうございます。

回答:


25

「インターフェースへのプログラム」とは、具体的な型に依存せずに作業を行うことを意味ますが、依存関係を取得する方法を指定しません。

「Dependency Inversion Principle」では、オブジェクトは依存関係の作成を制御するべきではなく、必要な依存関係をアドバタイズし、呼び出し元に提供させます。しかし、依存関係が具象型かインターフェースかを指定しません。

いくつかのC#コードとの違いを説明します。

次の例は具象型に依存し、それ自体の依存関係の作成を制御します。これは、次のいずれも、「依存関係反転」「インターフェイスにプログラムを」:

public class ThingProcessor
{
    MyThing _myThing;

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

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

次の例はインターフェイスに依存しますが、独自の依存関係の作成を制御します。「インターフェイスへのプログラム」に従いますが、「依存関係の反転」は続きません。

public class ThingProcessor
{
    IMyThing _myThing;

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

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

次の例は具象型に依存しますが、依存関係を作成してそれに渡すことを要求します。「依存関係の反転」に従いますが、「インターフェースへのプログラム」ではありません。

public class ThingProcessor
{
    MyThing _myThing;

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

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

次の例はインターフェイスに依存し、依存関係を作成して渡すことを要求します。「依存関係の逆転」「インターフェースへのプログラム」の両方に従います。

public class ThingProcessor
{
    IMyThing _myThing;

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

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

1
違いの優れたイラスト。
ロリーハンター14

8
あなたが話しているのは、依存性注射です。そして、依存関係の反転と依存関係の注入は2つの異なるものです。
陶酔

1
@Euphoric具体的な実装例としてDependency Injectionを使用して、抽象概念であるDependency Inversion Principleについて話しています。私は違いを理解しています。
エリックキング14

1
@EricKingそれから、「依存関係の逆転の原則」と言うのではなく、あなたの答えの中で明示的に言うべきです...私の答えを読んだ場合、明らかに間違っています。
陶酔14

1
Euphoricに同意します。依存関係反転の原則では、コードの高レベルのレイヤーは、その逆ではなく、低レベルのコードに依存する必要があると述べています。たとえばPrintStream、によって確立されたインターフェイスに依存する必要がありますByteOutputStream。依存性注入では、誰が誰に依存すべきかについては何も言及していません。
ドーバル14

5

それらは一般的に同じものです。あなたが読めば依存関係逆転の原則とは何か、なぜそれが重要なのですか?Dependency Inversion Principleでは、2つの「原則」が基本的に同じことについて話していることに気付くでしょう。

  • 高レベルのモジュールは低レベルのモジュールに依存するべきではありません。どちらも抽象化に依存する必要があります。
  • 抽象化は詳細に依存するべきではありません。詳細は抽象化に依存する必要があります。

インターフェイスは抽象化であり、実装は詳細です。前の2つのステートメントでそれらを置き換えると、基本的に「コードは実装ではなくインターフェイスに依存するはずです」というメッセージが表示されます。それは私にも同じことのように聞こえます。


これは受け入れられた答えである必要があり、他の最も投票された答えは誤解を招く
サームディーベス

2

インターフェイスは、DIを実装する1つの方法です。クラスのコンストラクターメソッドのパラメーターとしてインターフェイスを指定する場合、そのオブジェクトがコンストラクターパラメーターのインターフェイスを実装している限り、任意のオブジェクトをそのコンストラクターメソッドに渡すことができます。

つまり、インターフェイスをプログラミングすると、そのインターフェイスの実装変更できます 。単体テスト中にモックオブジェクトを実際のオブジェクトに置き換えたり、さまざまなデータプロバイダーを指定したりすることができます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.