7

大規模なソリューション (> 100 プロジェクト) があり、ほぼすべてのタイプがインスタンス化のためにサービス ロケーター (例 1) または独自のタイプ ディクショナリ (例 2) のいずれかを使用します。

たとえば、次のようなものがあります。

IQuote quote = Registry.Resolve<IQuote>(); 

また

IQuote quote = Registry.Find<IQuote>(args);

2 番目の例では、構成ファイルに移動して、リフレクションを使用してインスタンス化する具体的なオブジェクトを見つけます。

コードをたどる場合、どの具象型が使用されているかが明確でないため、作業がより困難になります。そのため、コードの一部を学習しようとするときに、マッピングを何度も確認する必要があります。上記を例として使用すると、F12 on:quote.DoSomething()を押すと、インターフェース定義に移動します。

また、実装が少し難しくなります。代替手段が 1 つのクラスだけの場合、インターフェイス + 具象クラス + 構成マッピングが必要です。

考えてみると、何かが別の型に「交換」されたことはありません。したがって、IoC を実装しましたが、それを使用していないか、少なくともほとんど使用していません。

それで-それは実際に価値がありますか?実装が間違っていたり、やりすぎたりしていませんか? 私は何か誤解していますか?

4

5 に答える 5

5

皆さんが使用しているのは、次の理由により、アンチパターンと見なされているService Locatorです。

  1. すべての単体テストでService Locatorを使用する必要があります(DI ではDI コンテナーは関与しません) 。
  2. アーキテクチャ全体を Service Locator に結合します ( DIでは、コンポジション ルートのみがDI コンテナーを使用します) 。
  3. コンポーネントの依存関係をすぐに確認することはできません ( DIではコンストラクター インジェクションがあります) 。
  4. 他のテストが誤って別の構成を使用しないように構成を管理する必要があるため、単体テストはより複雑になります (Tear Down)。

http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx

于 2012-07-02T08:02:31.997 に答える
4

私の意見では、すべてのクラスで DI を念頭に置いて作業する必要はありません。次の戦略を使用します。

  1. モジュールの境界を決定します。
  2. 同じモジュール内で、可能な場合は具象クラスを使用します。
  3. モジュール間通信は、可能な限り DI を使用してください。

モジュールは比較的きめ細かくする必要があります。

DI を使用する必要がある一般的な場所がいくつかあります。多くの場合、置き換え可能なデータ ソースと (それほど頻繁ではありませんが) アルゴリズムです。常識を働かせて、何かを交換する必要があるかどうかを確認してください。何かに DI が必要な場合や、DI に悩まされている場合は、ためらわずに早期リファクタリングを行ってください。

于 2012-07-01T16:21:26.750 に答える
2

あなたが示しているのは依存関係の注入ではなく、構成可能なレジストリです(これもパターンですが、まったく異なります)。そうです、悪い考えであり、一種の誤解のように見えます。

いくつかの設計パターンのメリットを享受できるようにするには、事前にメリットを理解する必要があります。それらを知らない場合は、おそらく気にしないでください。

于 2012-07-01T16:28:42.720 に答える
1

単体テストの場合、ある種の依存性注入は、スタブまたはモック...依存関係に不可欠です。(単体テストは、ファイルシステム、データベース、ネットワークなどの依存関係にぶつからないようにする必要があります)

于 2012-07-01T16:17:11.027 に答える
0

依存性注入のより一般的な概念を、非常に柔軟な形式のDIの実装を終了する手段であるDIコンテナーの使用と混同していると思います。これは、 DIを概念として説明する良い記事です。

あなたのシナリオでは、DIコンテナーを取り除くことができるように思えますが、テスト容易性のためだけに、何らかの形式のDIを保持したい場合があります(他の人がすでに指摘しているように)。このための一般的な実装パターンは、依存関係を注入でき、単体テストで使用される「広範な」コンストラクターの実装です。さらに、具象クラスをインスタンス化して「広い」コンストラクターに渡す「より狭い」コンストラクターがあります。これらは、依存関係を実際に交換する必要が生じるまで、本番コードで使用できます。

例:

class MyClass
{   
    // This will be called from production code
    public MyClass() : this(new Foo(), new Bar())
    {}        

    // This will be called from tests and can be used in production code if needed
    public MyClass(IFoo foo, IBar bar)
    {
       //do whatever you want to do in the ctor here
    }
}
于 2012-07-01T17:12:24.287 に答える