依存性注入とIoCコンテナーを使用する利点は何ですか?


62

Dependency InjectionとIoC Containersについての講演を予定しており、それを使用するための良い議論を探しています。

このテクニックとこれらのツールを使用する最も重要な利点は何ですか?


1
参照してくださいここここ StackOverflowの回答のためにと、ここでのIoCの良い完全な記事のために。あなたは比較のために、それに対する議論をしたい場合や、頭ここ SO上。
ジェシーC.スライサー

14
お尻にならないように...しかし、DI / IOCを使用する理由がわからない場合、なぜそれについて話しているのですか?賭けを失う?;-)
スティーブンA.ロウ

2
@スティーブン、彼の上司は彼にそれをするように頼んだかもしれません。

1
@Steven、私はすでにDIを常に使用しています(一部の人はあまりにも頻繁に言うでしょう:-D)。
アンディローリー

2
DI の過剰使用について人々が話すことはほとんどありません。すべての決定を遅らせる場合、スパゲッティコードに相当するオブジェクト指向オブジェクトを作成します。一貫性のある設計を行うには、ある時点で真の決定を下す必要があります。
マクニール

回答:


47

私にとって最も重要なことは、単一責任の原則に従うことを容​​易にすることです。

DI / IoCを使用すると、オブジェクト間の依存関係を簡単に管理できます。その結果、一貫性のある機能を独自のコントラクト(インターフェイス)に分割することが容易になります。その結果、DI / IoCを知って以来、私のコードははるかにモジュール化されました。

これの別の結果は、Open-Closed Principleをサポートする設計への道をはるかに簡単に見ることができることです。これは、最も自信に満ちたテクニックの1つです(自動テストに次ぐ)。私は、オープンクローズドプリンシプルの美徳を十分に支持できるとは思わない。

DI / IoCは、私のプログラミングキャリアで「ゲームチェンジャー」であった数少ないものの1つです。DI / IoCを学習する前と後に書いたコードの間には、品質に大きなギャップがあります。もう少し強調しておきましょう。 巨大なコードの品質を向上させます。


3
オープンクローズドプリンシパルはなぜそんなに重要なのですか?API /インターフェースを変更する必要があると感じたら、どうしていけないのですか?
アルネエバーツソン

@ArneEvertssonロバートC.マーティンのオープンクローズドプリンシパルの話を聞いてください。あなたは悟りを開きます。
Alternatex

@AmeEvertsson Open-Closedは、他の人が使用するモジュールとしてコードを提供する場合(商用製品としてなど)、コードを変更せずに使用中にコードをより適応させるため、非常に重要です
James Ellis-Jones

2
DIでは、単純に依存関係を具体的なクラスに作成するよりもかなり複雑であるため、依存関係を簡単に管理できません。ただし、柔軟性はありますが、「適切な」単体テストを行わない限り、多くの場合、その柔軟性は必要ありません。説明されている主な利点はどちらも、よりシンプルなService Locatorにも当てはまります。
ジェームズエリスジョーンズ

1
私は何年も前にこの答えを否定しました。1)実際には、プログラマは新しいクラスを作成する代わりに、注入された「コントローラ」、「サービス」、「DAO」などにメソッドを追加し続けるだけなので、DIの広範な使用はSRP に対して機能する傾向があります。新しい機能。これは、通常、DIフレームワークまたはコンテナを使用するJavaおよびC#.NETプロジェクトで発生するものです。2)オープン・クローズドの原則は、クラス(実装)継承の有用性に関するバートランド・マイヤーの妄想にすぎません。彼の1400+ページの本でそれを検索すると、私が意味することを見るでしょう-それは本当にばかげています。
ロジェリオ

9

本当に私の目を開いた例は、そのような方法で作成されたオブジェクトを簡単に単体テストできるようにする方法を見ていました。それ以前は、単体テストのためにオブジェクトを分離しようとして問題がありました。多くの場合、はるかに大きなシステムとやり取りするためのテストを作成します。これは、システム全体の予測可能性がはるかに低く、個々のコンポーネントよりも変更が発生しやすいため、非常に困難でした。


3

依存性注入の利点は次のとおりです。

  1. あなたのコードはきれいで読みやすいです。
  2. コードは疎結合です。
  3. 実装がXMLファイルで構成されているため、より再利用可能です。異なるコンテキストで使用できます。
  4. コードは異なるモック実装で簡単にテストできます。

1

実際のメリットは技術的なものよりも政治的なものだと思います。DIは、単なるService Locatorパターンの代替であり、それ以上のものではありません。それ自体では、SRPやOCPのような原則に従うことや、レイヤーを分離することは簡単にはなりません。他の回答者は、IMOという異なる概念と手法を混同しています。

Service Locatorを使用するか、適用可能な場合(ほとんどの場合)に直接依存関係をインスタンス化するだけで、高い凝集度と低い結合に関して同じ目標を達成できます。

今、私は多くの人がこの意見に反対することを知っています。具体的な例を説明させていただきます。


2
ただし、通常、サービスロケーターを直接呼び出したり、具体的な依存関係をインスタンス化すると、依存関係、または少なくとも依存関係がどこから来たのかがハードワイヤードされます。これはDIの目的に反しているようです。サービスロケーターも挿入する必要があります。
マットH

Service Locatorを使用しても、通常は「注入」されないService Locatorクラス自体の使用を除き、何も組み込まれません。具体的な実装クラスをインスタンス化することは、外部設定が必要ない場合にはまったく問題ありません(たとえば、プログラマは通常、DIを使用する代わりにArrayListクラスを直接インスタンス化します-これはやり過ぎです)。
ロジェリオ

1
「低カップリング」について言及した後、サービスロケーターはアプリケーションのカップリングのレベルに影響を与えないと言います。コード上で直接コラボレーターをインスタンス化するのと同じように、オブジェクトをその依存関係と結合するより完璧な方法は考えられません。両方のシナリオをどのように単体テストしますか?敬意を表して、あなたが言ったことすべてに完全に反対します。
クリントイーストウッド

@Jonathan DIを紹介し記事を読んでください。著者は、DIとServiceLocatorは「ほぼ同等」であり、後者は「わずかなエッジ」であると結論付けています。重要なカップリングは、コンポーネントと、複数の実装を持つ他のコンポーネントとの間です。ServiceLocatorは、実装が1つだけのインフラストラクチャサービスなので、大丈夫です。注:「該当する場合は常に依存関係をインスタンス化する」と書きました。もちろん、設定を使用から分離する必要がある場合は、実行しません。
ロジェリオ

1
@Jonathan単体テストに関しては、コラボレーターをインスタンス化すると、そのようなテストの作成が妨げられるという神話です。依存関係の実装からクラスを分離するジョブを実行する有名なモッキングツールがあります(それらが注入されているかどうかは関係ありません)。
ロジェリオ

-1

テストの目的で内部オブジェクトを公開するためにDIが使用される場合、パターンは悪用されています。


1
「内部オブジェクト」とはどういう意味ですか?で、実際の OOP(プログラマのおそらく唯一の1%は、それが本当に何を意味するのか知っているノート)、メッセージ(すなわちメソッド呼び出し)を送信する手段によって互いに通信オブジェクトがあります。その意味で、各オブジェクトには単一の責任が必要であり、他のオブジェクトよりも「重要な」オブジェクトはありません...単一のオブジェクトには単一の義務があり、システム全体が提供する機能を実現するために協力します。すべてのオブジェクトを孤立した方法でテストすることが重要であるため、どのケースも見逃していないことがわかります。これがDIの優れた点です。
クリントイーストウッド

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