12

デフォルトの実装をデフォルトのコンストラクターにハードコーディングするよりも、IOCコンテナーを使用することの利点を誰かが説明できますか?

言い換えれば、このコードの何が問題になっていますか?

public class MyClass
{
    private IMyInterface _myInterface;

    public MyClass()
    {
        _myInterface = new DefaultMyInterface();
    }

    public MyClass(IMyInterface myInterface)
    {
        _myInterface = myInterface;
    }
}

私の知る限り、このクラスはコンストラクターインジェクションを十分にサポートしているため、単体テストとモックを簡単に実行できます。それに加えて、デフォルトのコンストラクターはIOCコンテナーの計算オーバーヘッドを取り除きます(プロセス全体がはるかに透過的であることは言うまでもありません)。

IOCコンテナを使用することで私が見ることができる唯一の利点は、インターフェイスの実装を頻繁に切り替える必要がある場合です。私は何かが足りないのですか?

4

8 に答える 8

12

IoCの考え方は、コンポーネントの機能の一部をシステムの別の部分に委任することです。IoCの世界では、お互いを知らないコンポーネントがあります。MyClassとIMyInterfaceの実装の間に緊密な結合を作成しているため、この例はこれに違反しています。主なアイデアは、コンポーネントがどのように使用されるかについての知識がないということです。あなたの例では、あなたのコンポーネントはその使用についていくつかの仮定をします。

実際にはこのアプローチは機能しますが、IoCと明示的なオブジェクトの初期化を混在させることはIMOの良い習慣ではありません。

IoCは、コードの明確さを犠牲にして遅延バインディングを実行することにより、緩い結合を提供します。このプロセスに動作を追加すると、事態はさらに複雑になり、一部のコンポーネントが望ましくない動作または予期しない動作のオブジェクトを受け取る可能性がある場合にバグが発生する可能性があります。

于 2008-09-19T10:22:59.857 に答える
4

サイドを選んでください:)

つまり、IOCが推奨されます。コードの問題は、最後に述べたように、コードを再コンパイルせずに依存関係のデフォルトの実装を交換できないことです。IOCを使用すると、再コンパイルせずに、外部ファイル内のオブジェクトの構成または構成を変更できます。
IOCは、残りのコードから「構築と組み立て」の責任を引き継ぎます。 IOCの目的は、コードをテスト可能にすることではありません...それは楽しい副作用です。(TDDコードがより良い設計につながるように)

于 2008-09-19T10:36:58.873 に答える
2

このコードには何も問題はなく、SpringやGuiceなどの依存性注入フレームワークでも使用できます。

多くの開発者は、コンパイル手順を必要とせずに実装を切り替えることができるため、SpringのXML構成ファイルをコード内の依存関係を配線するよりも有利であると考えています。この利点は、実際には、クラスパスにすでにいくつかの実装がコンパイルされており、展開時に実装を選択したい場合に実現されます。コンポーネントが展開後にサードパーティによって提供される状況を想像できます。同様に、展開後にパッチとして追加の実装を出荷したい場合があります。

ただし、すべてのDIフレームワークがXML構成を使用しているわけではありません。たとえば、Google Guiceには、他のJavaクラスと同じようにコンパイルする必要があるJavaクラスとして記述されたモジュールがあります。

では、コンパイル手順が必要な場合でも、DIの利点は何ですか?これにより、元の質問に戻ります。私は次の利点を見ることができます:

  1. アプリケーション全体のDIへの標準的なアプローチ。
  2. 構成は他のロジックからきちんと分離されています。
  3. プロキシを注入する機能。たとえば、Springでは、実装の代わりにプロキシを挿入することで、宣言型のトランザクション処理を行うことができます。
  4. 構成ロジックの再利用が容易になります。DIを広範囲に使用すると、時間の経過とともに進化する依存関係の複雑なツリーが表示されます。明確に分離された構成レイヤーとフレームワークのサポートなしでそれを管理することは悪夢になる可能性があります。DIフレームワークを使用すると、継承やその他の手段を通じて構成ロジックを簡単に再利用できます。
于 2008-09-19T10:50:31.337 に答える
2

私が持っている唯一の懸念は、(1)デフォルトのサービス依存関係自体に別の/セカンダリサービス依存関係がある場合(など... DefaultMyInterfaceはILoggerに依存する)、(2)最初のサービス依存関係を2番目のサービス依存関係から分離する必要がある(スタブ ILogger で DefaultMyInterface をテストする必要があります)。その場合、明らかにデフォルトの「new DefaultMyInterface」を失い、代わりに次のいずれかを実行する必要があります。

他の投稿者がリストした懸念事項のいくつかは、あなたの質問には当てはまらないかもしれません。複数の「本番」実装について質問していませんでした。単体テストについて質問しています。 ユニットテストの場合、あなたのアプローチは、私の最初の警告が述べられているように、正当に思えます。私も、単純な単体テスト ケースで使用することを検討します。

同様に、何人かの回答者は、繰り返しについて懸念を表明しました。私も繰り返しは好きではありませんが、(1) デフォルトの実装が実際にデフォルトであり (YAGNI: デフォルトを変更する予定はありません)、(2) 私が述べた最初の警告が適用されるとは信じていない場合、および(3)あなたが共有したより単純なコードアプローチを好むなら、この特定の形式の繰り返しは問題ではないと思います.

于 2010-04-13T17:52:24.090 に答える
1

緩い結合に加えて、IoCはコードの重複を減らします。IoCを使用していて、インターフェイスのデフォルトの実装を変更する場合は、1か所で変更する必要があります。デフォルトのコンストラクターを使用してデフォルトの実装を注入する場合、インターフェースが使用されるすべての場所でそれを変更する必要があります。

于 2008-09-19T10:37:45.097 に答える
1

他のコメントに加えて、これらのケースでは DRY (Do Not Repeat Yourself) の原則を主張することができます。そのデフォルトの構築コードをすべてのクラスに入れなければならないのは冗長です。また、必要のない特殊なケースの処理も導入されています。

于 2008-10-22T17:52:10.170 に答える
0

デフォルトの実装をハードコーディングする手法をIOCコンテナと一緒に使用できなかった理由がわかりません。ただ、構成で指定しない依存関係は、デフォルトの実装を採用します。

それとも私は何かが足りないのですか?

于 2008-09-19T10:23:07.627 に答える
0

IOCコンテナを使用する理由の1つは、ソフトウェアの遅い構成を容易にするためです。

たとえば、特定のインターフェイスの実装をいくつか提供するとします。顧客(または専門サービスチーム)は、IOC構成ファイルを変更することでどちらを使用するかを決定できます。

于 2008-09-19T10:24:35.097 に答える