IoCコンテナで販売してください


17

コードでIoCコンテナを使用することをお勧めします。動機は簡単です。次の依存性注入コードを取得します。

class UnitUnderTest
{
    std::auto_ptr<Dependency> d_;
public:
    UnitUnderTest(
        std::auto_ptr<Dependency> d = std::auto_ptr<Dependency>(new ConcreteDependency)
    ) : d_(d)
    {
    }
};


TEST(UnitUnderTest, Example)
{
    std::auto_ptr<Dependency> dep(new MockDependency);
    UnitUnderTest uut(dep);
    //Test here
}

に:

class UnitUnderTest
{
    std::auto_ptr<Dependency> d_;
public:
    UnitUnderTest()
    {
        d_.reset(static_cast<Dependency *>(IocContainer::Get("Dependency")));
    }
};


TEST(UnitUnderTest, Example)
{
    UnitUnderTest uut;
    //Test here
}

//Config for IOC container normally
<Dependency>ConcreteDependency</Dependency>

//Config for IOC container for testing
<Dependency>MockDependency</Dependency>

(上記はもちろん仮想的なC ++の例です)

依存関係コンストラクターパラメーターを削除することにより、クラスのインターフェイスが単純化されることに同意しますが、いくつかの理由により、治療法は病気よりも悪いと思います。まず、これは私にとって大きなものです。これにより、プログラムが外部構成ファイルに依存するようになります。単一のバイナリ展開が必要な場合、これらの種類のコンテナは使用できません。2番目の問題は、APIが弱く、ひどく、文字列型であるということです。(この仮想的な例の)証拠は、IoCコンテナーへの文字列引数と、結果へのキャストです。

だから..これらの種類のコンテナを使用することには他の利点がありますか、それともコンテナを推奨するものに同意しませんか?


1
サンプルコードは、IoC実装の非常に悪い例のように見えます。私はC#にしか精通していませんが、C ++でもコンストラクターインジェクションとプログラム設定を行う方法はありますか?
rmac

回答:


12

多くのレイヤーと多くの可動部品を持つ大規模なアプリケーションでは、利点と比較してかなり軽微に見える欠点があります。

コンテナはクラスの「インターフェイスを単純化」しますが、非常に重要な方法でそれを行います。コンテナは、依存性注入が作成する問題の解決策です。依存性注入は、場所全体、オブジェクトグラフ、機能領域全体に依存性を渡す必要があるということです。ここには、1つの依存関係を持つ1つの小さな例があります。このオブジェクトに3つの依存関係があり、それに依存するオブジェクトに、それらに依存する複数のオブジェクトがある場合などはどうでしょうか。コンテナがなければ、それらの依存関係チェーンの最上位にあるオブジェクトは、アプリケーション全体のすべての依存関係を追跡する責任を負うことになります。

さまざまな種類のコンテナもあります。それらのすべてが文字列で入力されるわけではなく、すべてが構成ファイルを必要とするわけでもありません。


3
しかし、大規模なプロジェクトは、すでに述べた問題を悪化ます。プロジェクトが大きい場合、構成ファイル自体が巨大な依存関係の磁石になり、実行時に1つのタイプミスが未定義の動作を引き起こすことがさらに容易になります。(つまり、設定ファイルにタイプミスがあると、間違ったタイプが返された場合にキャストによって未定義の動作が発生します)。依存関係の依存関係については、ここでは関係ありません。コンストラクターがそれらを作成するか、テストがトップレベルの依存関係をモックアウトします。
ビリーONeal

...続き...プログラムがテストされていない場合、デフォルトの具象依存関係が各ステップでインスタンス化されます。他の種類のコンテナについて、いくつかの例はありますか?
ビリーONeal

4
TBH DI実装の豊富な経験はありませんが、.NETのMEFを見てください。MEFは文字列を入力する必要はありますが、設定ファイルはなく、インターフェイスの具体的な実装は「登録済み」です。クラス自体に。ところで、「コンストラクターがそれらを作成する」と言うとき-それがあなたがしていることであれば(別名「貧乏人のコンストラクター注入」)、コンテナーは必要ありません。これを行うことに対するコンテナの利点は、コンテナがこれらすべての依存関係に関する情報を一元化することです。
nlawalker

その最後のコメントの+
1-

1
私が全体の要点を理解するのを助けた素晴らしい答え。要は、定型文を単純化するだけでなく、依存関係チェーンの上部の要素を下部の要素と同じように単純にすることです。
クリストファーバーマン

4

JavaのGuice IoCフレームワークは、構成ファイルではなく構成コードに依存しています。つまり、構成は実際のアプリケーションを構成するコードと変わらないコードであり、リファクタリングなどが可能です。

Guiceは、最終的に構成を正しくしたJava IoCフレームワークであると思います。


C ++に類似した例はありますか?
ビリーONeal

@ビリー、私は言うことができるほどC ++に精通していない。

0

Ben Scheirmanによるこの素晴らしいSOの回答では、C#のコード例をいくつか説明しています。IoCコンテナ(DI)のいくつかの利点:

  • 依存関係チェーンは入れ子になる可能性があり、それらを手動で接続するとすぐに扱いにくくなります。
  • アスペクト指向プログラミングの使用を有効にします。
  • 宣言型およびネストされたデータベーストランザクション。
  • 宣言的かつネストされた作業単位。
  • ロギング。
  • 事前/事後条件(契約による設計)。

1
単純なコンストラクター注入では、これらのことをどのように実装できないのかわかりません。
ビリーONeal

良い設計では、コンストラクター注入または別のメソッドで十分かもしれません。これらのIoCコンテナーの利点は、特定の場合にのみ得られる可能性があります。WPFプロジェクトでINotifyPropertyChangedを使用して与えられた例は、そのような例の1つです。
-dodgy_coder
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.