依存関係注入コンテナーの利点は何ですか?
-
02-07-2019 - |
質問
依存関係注入自体の利点は理解しています。春を例に考えてみましょう。また、AOP やさまざまな種類のヘルパーなどの他の Spring 機能の利点も理解しています。XML 構成には次のような利点があるのではないかと考えています。
<bean id="Mary" class="foo.bar.Female">
<property name="age" value="23"/>
</bean>
<bean id="John" class="foo.bar.Male">
<property name="girlfriend" ref="Mary"/>
</bean>
次のような単純な古い Java コードと比較してください。
Female mary = new Female();
mary.setAge(23);
Male john = new Male();
john.setGirlfriend(mary);
これはデバッグが容易で、コンパイル時間のチェックが容易で、Java しか知らない人でも理解できます。では、依存関係注入フレームワークの主な目的は何でしょうか?(またはその利点を示すコードの一部)。
アップデート:
の場合には
IService myService;// ...
public void doSomething() {
myService.fetchData();
}
myService の実装が複数ある場合、IoC フレームワークはどのようにして myService の実装を推測するのでしょうか?指定されたインターフェイスの実装が 1 つだけあり、IoC コンテナにそれを使用するよう自動的に決定させると、2 番目の実装が出現した後に壊れてしまいます。また、意図的にインターフェースの実装が 1 つだけある場合は、それを挿入する必要はありません。
IoC の利点を示す小さな構成を見るのは非常に興味深いでしょう。私はしばらく Spring を使用していますが、そのような例を提供することはできません。また、私が使用している Hibernate、dwr、およびその他のフレームワークの利点を示す単一行を表示できます。
更新 2:
IoC 設定は再コンパイルせずに変更できることがわかりました。それは本当に良いアイデアでしょうか?誰かが再コンパイルせずに DB 認証情報を変更したい場合は理解できますが、その人は開発者ではない可能性があります。実際、開発者以外の誰かが IoC 構成を変更する頻度はどのくらいですか?開発者にとって、構成を変更する代わりにその特定のクラスを再コンパイルする手間は不要だと思います。また、開発者以外の人にとっては、作業を楽にして、より単純な構成ファイルを提供したいと思うでしょう。
更新 3:
インターフェースとその具体的な実装間のマッピングの外部構成
それを外部化することで何がそんなに良いのでしょうか?すべてのコードを外部にするわけではありませんが、確かに可能です - ClassName.java.txt ファイルにコードを配置し、その場で手動で読み取ってコンパイルするだけです - すごい、再コンパイルを回避できました。なぜコンパイルを避けなければならないのでしょうか?
マッピングを手続き型コードではなく宣言的に提供するため、コーディング時間を節約できます。
宣言的なアプローチが時間を節約できる場合があることを理解しています。たとえば、Bean プロパティと DB 列の間のマッピングを 1 回だけ宣言すると、Hibernate はロード、保存、HSQL に基づく SQL の構築などの際にこのマッピングを使用します。ここで宣言的アプローチが機能します。Spring の場合 (私の例では)、宣言の行数が増え、対応するコードと同じ表現力がありました。そのような宣言がコードよりも短い場合の例があれば、それを見てみたいと思います。
制御の反転原理により、実際の実装を偽の実装に置き換えることができるため (SQL データベースをメモリ内の実装に置き換えるなど)、単体テストが容易になります。
私は制御の反転の利点を理解しています (ここで説明する設計パターンを依存性注入と呼びたいと思います。IoC の方がより一般的であるためです。制御には多くの種類があり、そのうちの 1 つ (初期化の制御) のみを反転します)。私は、なぜプログラミング言語以外のものが必要になるのかと疑問に思っていました。コードを使用して、実際の実装を偽の実装に置き換えることは間違いなくできます。そして、このコードは設定と同じことを表現します。フィールドを偽の値で初期化するだけです。
mary = new FakeFemale();
DIのメリットは理解しています。同じことを行うコードを構成する場合と比較して、外部 XML 構成によってどのような利点が追加されるのか理解できません。私はコンパイルを避けるべきだとは思いません。私は毎日コンパイルしており、今も生きています。DI の設定は宣言型アプローチの悪い例だと思います。宣言は、一度宣言され、かつさまざまな方法で何度も使用される場合に便利です。たとえば、Bean プロパティと DB 列の間のマッピングが保存、ロード、検索クエリの構築などに使用される Hibernate cfg などです。この質問の冒頭のように、Spring DI 構成はコードの構成に簡単に変換できますよね。それは Bean の初期化にのみ使用されますね。つまり、宣言的なアプローチでは何も追加されないということですね。
Hibernate マッピングを宣言するとき、Hibernate に何らかの情報を与えるだけで、Hibernate はそれに基づいて動作します。何をすべきかは指示しません。Spring の場合、私の宣言は Spring に何をすべきかを正確に指示します。では、なぜそれを宣言するのでしょうか、なぜただそれを実行しないのでしょうか?
最後の更新:
皆さん、多くの回答が依存性注入について教えてくれています。私はそれが良いことだと知っています。質問は、コードを初期化するのではなく、DI 構成の目的についてです。私は、コードを初期化する方が短くて明確だと考える傾向があります。私の質問に対してこれまでに得られた唯一の答えは、構成が変更されたときに再コンパイルを回避できるということです。この場合、なぜコンパイルを避けるべきかということは私にとって大きな秘密なので、別の質問を投稿する必要があると思います。
解決
私自身、IoC を使用する (そして外部構成を利用する) 主な理由の 1 つは、次の 2 つの領域にあります。
- テスト
- 生産保守
テスト
テストを 3 つのシナリオに分割した場合 (これは大規模な開発ではごく普通のことです):
- 単体テスト
- 結合テスト
- ブラックボックステスト
最後の 2 つのテスト シナリオ (統合とブラック ボックス) では、アプリケーションのどの部分も再コンパイルしません。
テスト シナリオのいずれかで構成を変更する必要がある場合 (例:別のコンポーネントを使用して銀行統合を模倣するか、パフォーマンス負荷を実行すると)、これは簡単に処理できます (ただし、これには IoC の DI 側を構成する利点があります。
さらに、アプリが複数のサイト (サーバーとコンポーネントの構成が異なる) で使用されている場合、またはライブ環境で構成が変更されている場合は、テストの後半の段階を使用して、アプリがそれらの変更を処理することを確認できます。
生産
開発者は運用環境 (特にアプリが複数の顧客や別々のサイトに配布されている場合) を制御できません (そして制御すべきではありません)。私にとって、これが IoC と外部構成の両方を使用する本当の利点です。開発者に戻ってテストを行うことなく、ライブ環境を微調整して調整できるかどうかはインフラストラクチャ/運用サポート次第であるためです (コンポーネントを移動するだけの場合はコストが高くなります)。
まとめ
IoC の外部構成の主な利点は、他の人 (開発者以外) にアプリケーションを構成する権限を与えることで得られますが、私の経験では、これは限られた状況でのみ役に立ちます。
- アプリケーションは、環境が異なる複数のサイト/クライアントに配布されます。
- 実稼働環境およびセットアップに対する開発制御/入力が制限されています。
- シナリオのテスト。
実際に私は、何かを開発するときでも、それが実行される環境を制御できる場合でも、時間が経つにつれて、構成を変更する権限を他の人に与えたほうが良いことがわかりました。
- 開発中は、いつ変更されるかわかりません (アプリは非常に便利なので、会社はそれを他の人に販売します)。
- 適切な構成モデルを設定して使用すれば対処できたかもしれないわずかな変更が要求されるたびに、コードを変更するという作業に煩わされるのは望ましくありません。
注記:アプリケーションとは、(実行可能ファイルだけではなく) 完全なソリューションを指すため、アプリケーションの実行に必要なすべてのファイル.
他のヒント
依存関係の注入は、オブジェクトの委任が通常、オブジェクトの継承よりも有用な設計パターンである (つまり、オブジェクトが関係を持つという関係は、オブジェクトが関係を持つという関係よりも有用である) という観察にルーツを持つコーディング スタイルです。ただし、DI が機能するにはもう 1 つの要素、つまりオブジェクト インターフェイスの作成が必要です。これら 2 つの強力な設計パターンを組み合わせると、ソフトウェア エンジニアは柔軟な疎結合コードを作成できることにすぐに気づき、依存性注入の概念が生まれました。ただし、DI が本格的に普及したのは、特定の高級言語でオブジェクト リフレクションが利用できるようになってからです。リフレクション コンポーネントは、今日のほとんどの DI システムの中核となっています。DI の本当に優れた側面には、オブジェクト自体とは独立した外部のシステムを使用して、プログラムでオブジェクトを選択し、構成して他のオブジェクトに注入する機能が必要だからです。
言語は、通常のオブジェクト指向プログラミング手法と、オブジェクト インターフェイスおよびオブジェクト リフレクション (Java や C# など) のサポートの両方を適切にサポートする必要があります。C++ システムでは DI パターンを使用してプログラムを構築できますが、言語自体にリフレクション サポートがないため、アプリケーション サーバーやその他の DI プラットフォームをサポートできず、DI パターンの表現力が制限されます。
DIパターンで構築したシステムの強み:
- DI コードは、「依存」機能が明確に定義されたインターフェイスに外挿されているため、再利用がはるかに簡単で、適切なアプリケーション プラットフォームによって設定が処理される個別のオブジェクトを他のオブジェクトに自由にプラグインできるようになります。
- DI コードはテストがはるかに簡単です。オブジェクトによって表現される機能は、アプリケーション ロジックで期待されるインターフェイスを実装する「モック」オブジェクトを構築することによって、ブラック ボックスでテストできます。
- DIコードはより柔軟です。これは、極端に言えば、本質的に疎結合のコードです。これにより、プログラマは、一方の端では必要なインターフェイス、もう一方の端では表現されたインターフェイスのみに基づいて、オブジェクトの接続方法を選択できます。
- DI オブジェクトの外部 (Xml) 構成は、他の人が予期しない方向にコードをカスタマイズできることを意味します。
- 外部構成は、オブジェクトの初期化とオブジェクトの相互依存性管理のすべての問題をアプリケーション サーバーで処理できるという点で、懸念事項の分離パターンでもあります。
- DI パターンを使用するために外部構成は必要ないことに注意してください。単純な相互接続の場合は、小さなビルダー オブジェクトで十分であることがよくあります。両者の間には柔軟性のトレードオフがあります。ビルダー オブジェクトは、外部から見える構成ファイルほど柔軟なオプションではありません。DI システムの開発者は、利便性よりも柔軟性の利点を比較検討する必要があります。構成ファイルで表現されるオブジェクト構築に対する小規模で細かい制御は、将来的に混乱とメンテナンス コストを増大させる可能性があることに注意してください。
間違いなく DI コードのほうが面倒に思えますし、オブジェクトを構成する XML ファイルをすべて他のオブジェクトに挿入するのは難しいようです。しかし、これが DI システムのポイントです。一連の構成設定としてコード オブジェクトを組み合わせて一致させる機能により、ユーザー側でのコーディングを最小限に抑えながら、サードパーティのコードを使用して複雑なシステムを構築できます。
質問で提供されている例は、適切にファクタリングされた DI オブジェクト ライブラリが提供できる表現力の表面に触れているだけです。ある程度の練習と多くの自己規律により、ほとんどの DI 実践者は、アプリケーション コードのテスト カバレッジが 100% であるシステムを構築できることに気付きます。この一点だけでも異常です。これは、数百行のコードからなる小規模なアプリケーションの 100% のテスト カバレッジではありませんが、数十万行のコードで構成されるアプリケーションの 100% のテスト カバレッジです。このレベルのテスト容易性を提供する他の設計パターンを説明することはできません。
わずか数十行のコードのアプリケーションは、いくつかのオブジェクトと一連の XML 構成ファイルを追加するよりも理解しやすいという点では、そのとおりです。ただし、最も強力な設計パターンと同様に、システムに新しい機能を追加し続けると、利点が得られます。
つまり、大規模な DI ベースのアプリケーションは、デバッグが容易であり、理解も容易です。XML 構成は「コンパイル時チェック」されていませんが、この作成者が認識しているすべてのアプリケーション サービスは、互換性のないインターフェイスを持つオブジェクトを別のオブジェクトに挿入しようとすると、開発者にエラー メッセージを表示します。また、ほとんどの場合、既知のオブジェクト構成をすべてカバーする「チェック」機能が提供されます。これは、インジェクトされるオブジェクト A が、設定されているすべてのオブジェクト インジェクションに対してオブジェクト B に必要なインターフェイスを実装していることを確認することによって、簡単かつ迅速に実行できます。
これは少し内容の濃い質問ですが、膨大な量の XML 構成は実際にはあまりメリットがないということに私も同意する傾向があります。私は、アプリケーションが、重いフレームワークを含め、依存関係をできるだけ軽くすることを好みます。
これらは多くの場合コードを簡素化しますが、複雑さによるオーバーヘッドもあり、問題の追跡がかなり困難になります (私はそのような問題を直接見たことがありますし、ストレートな Java の方がはるかに快適に対処できると思います)。
それはスタイルとあなたが快適に感じるものによって少し変わると思います...独自のソリューションを活用して、それを隅々まで知るメリットを得るのが好きですか、それとも、構成が正しくない場合には困難が判明する可能性がある既存のソリューションに頼るのが好きですか?それはすべてトレードオフです。
ただし、XML 構成は少し苦手です...私はそれを何としてでも避けようとします。
コードをデータに変更できるときはいつでも、正しい方向への一歩を踏み出すことができます。
何かをデータとしてコーディングするということは、コード自体がより汎用的で再利用可能であることを意味します。これは、データがそのデータに正確に適合する言語で指定できることも意味します。
また、XML ファイルは GUI またはその他のツールに読み込まれ、実用的に簡単に操作できます。コード例でそれを行うにはどうすればよいでしょうか?
私は、ほとんどの人がコードとして実装するものを常にデータに因数分解しています。これにより、残ったコードがよりクリーンになります。メニューをデータとしてではなくコードで作成する人がいるとは考えられません。コードでメニューを作成するのは定型文のため、明らかに間違いであることは明らかです。
DI コンテナを使用する理由は、単なるゲッターとセッターである 10 億のプロパティをコード内で事前に構成する必要がないためです。本当にこれらすべてを new X() でハードコーディングしますか?確かにデフォルトを使用することもできますが、DI コンテナーを使用するとシングルトンを非常に簡単に作成できるため、初期化などの雑多なタスクではなく、コードの詳細に集中できます。
たとえば、Spring では、InitializingBean インターフェイスを実装し、afterPropertiesSet メソッドを追加できます (コードを Spring に結合することを避けるために、「init-method」を指定することもできます)。これらのメソッドを使用すると、クラス インスタンスのフィールドとして指定されたインターフェイスが起動時に正しく構成されていることを確認できるため、ゲッターとセッターを null チェックする必要がなくなります (シングルトンをスレッド セーフに保つことができると仮定すると) )。
さらに、複雑な初期化を自分で行うよりも、DI コンテナを使用した方がはるかに簡単です。たとえば、私は XFire の使用を支援します (CeltiXFire ではありません。Java 1.4 のみを使用します)。このアプリは Spring を使用していましたが、残念ながら XFire の services.xml 構成メカニズムを使用していました。要素のコレクションが 1 つ以上のインスタンスではなく 0 つ以上のインスタンスを持つことを宣言する必要がある場合、この特定のサービス用に提供された XFire コードの一部をオーバーライドする必要がありました。
XFire の Spring Bean スキーマには、特定のデフォルトが定義されています。したがって、Spring を使用してサービスを構成していた場合、Bean を使用できた可能性があります。代わりに、Bean を使用する代わりに、services.xml ファイルで特定のクラスのインスタンスを指定する必要がありました。これを行うには、コンストラクターを提供し、XFire 構成で宣言された参照をセットアップする必要がありました。実際に行う必要がある変更では、単一のクラスをオーバーロードする必要がありました。
しかし、services.xml ファイルのおかげで、コンストラクター内の Spring 構成ファイルのデフォルトに従ってデフォルトを設定する 4 つの新しいクラスを作成する必要がありました。Spring 構成を使用できたなら、次のように言えたはずです。
<bean id="base" parent="RootXFireBean">
<property name="secondProperty" ref="secondBean" />
</bean>
<bean id="secondBean" parent="secondaryXFireBean">
<property name="firstProperty" ref="thirdBean" />
</bean>
<bean id="thirdBean" parent="thirdXFireBean">
<property name="secondProperty" ref="myNewBean" />
</bean>
<bean id="myNewBean" class="WowItsActuallyTheCodeThatChanged" />
代わりに、次のようになりました。
public class TheFirstPointlessClass extends SomeXFireClass {
public TheFirstPointlessClass() {
setFirstProperty(new TheSecondPointlessClass());
setSecondProperty(new TheThingThatWasHereBefore());
}
}
public class TheSecondPointlessClass extends YetAnotherXFireClass {
public TheSecondPointlessClass() {
setFirstProperty(TheThirdPointlessClass());
}
}
public class TheThirdPointlessClass extends GeeAnotherXFireClass {
public TheThirdPointlessClass() {
setFirstProperty(new AnotherThingThatWasHereBefore());
setSecondProperty(new WowItsActuallyTheCodeThatChanged());
}
}
public class WowItsActuallyTheCodeThatChanged extends TheXFireClassIActuallyCareAbout {
public WowItsActuallyTheCodeThatChanged() {
}
public overrideTheMethod(Object[] arguments) {
//Do overridden stuff
}
}
したがって、最終的な結果として、1 つの追加クラスといくつかの単純な依存関係コンテナー情報が達成する効果を実現するには、4 つの追加のほとんど無意味な Java クラスをコードベースに追加する必要がありました。これは「規則を証明する例外」ではなく、規則です...プロパティが DI コンテナーですでに提供されており、特殊な状況に合わせて単にプロパティを変更するだけであれば、コード内での癖の処理がはるかに簡単になります。それは頻繁に起こります。
あなたの答えがあります
各アプローチには明らかにトレードオフがありますが、外部化された XML 構成ファイルは、IDE ではなくビルド システムを使用してコードをコンパイルするエンタープライズ開発に役立ちます。ビルド システムを使用すると、ビルドのバージョンなどの特定の値をコードに挿入することができます (コンパイルのたびに手動で更新する必要があるのは面倒な場合があります)。ビルド システムがバージョン管理システムからコードを取得する場合、問題はさらに大きくなります。コンパイル時に単純な値を変更するには、ファイルを変更し、コミットし、コンパイルし、変更のたびに元に戻す必要があります。これらは、バージョン管理にコミットする変更ではありません。
ビルド システムと外部構成に関するその他の有用な使用例は次のとおりです。
- 異なるビルドの単一のコードベースにスタイル/スタイルシートを挿入する
- 単一のコードベースに異なる動的コンテンツ (またはそれらへの参照) セットを挿入する
- さまざまなビルド/クライアントのローカリゼーション コンテキストを挿入する
- WebサービスURIをバックアップサーバーに変更する(メインサーバーがダウンした場合)
アップデート:上記の例はすべて、クラスへの依存関係を必ずしも必要としないものに関するものでした。ただし、複雑なオブジェクトと自動化の両方が必要なケースは簡単に構築できます。たとえば、次のとおりです。
- Web サイトのトラフィックを監視するシステムがあると想像してください。同時ユーザーの数に応じて、ログ記録メカニズムをオン/オフにします。おそらく、メカニズムがオフになっている間に、スタブ オブジェクトがその場所に置かれます。
- ユーザーの数に応じて、参加者の数に応じて P2P を実行する機能を切り替える Web 会議システムがあると想像してください。
設定を変更するたびにコードを再コンパイルする必要はありません。これにより、プログラムの展開とメンテナンスが簡素化されます。たとえば、構成ファイルを 1 つ変更するだけで、あるコンポーネントを別のコンポーネントと交換できます。
ガールフレンドの新しい実装をスロットに入れることができます。したがって、コードを再コンパイルせずに新しい女性を挿入できます。
<bean id="jane" class="foo.bar.HotFemale">
<property name="age" value="19"/>
</bean>
<bean id="mary" class="foo.bar.Female">
<property name="age" value="23"/>
</bean>
<bean id="john" class="foo.bar.Male">
<property name="girlfriend" ref="jane"/>
</bean>
(上記は Female と Hot Female が同じ GirlfFriend インターフェイスを実装していることを前提としています)
.NET の世界では、ほとんどの IoC フレームワークが XML 構成とコード構成の両方を提供します。
たとえば、StructureMap と Ninject は、滑らかなインターフェイスを使用してコンテナを構成します。XML 構成ファイルの使用に制約されなくなりました。Spring も .NET に存在しており、これが歴史的な主要な構成インターフェイスであるため、XML ファイルに大きく依存していますが、コンテナをプログラムで構成することは依然として可能です。
使いやすさ 部分的な構成を組み合わせる 最終的な完全な構成にします。
たとえば、Web アプリケーションでは、通常、モデル、ビュー、コントローラーは別個の構成ファイルで指定されます。宣言的なアプローチを使用すると、たとえば次のようにロードできます。
UI-context.xml
Model-context.xml
Controller-context.xml
または、別の UI といくつかの追加コントローラーを使用してロードします。
AlternateUI-context.xml
Model-context.xml
Controller-context.xml
ControllerAdditions-context.xml
同じことをコードで行うには、部分的な構成を組み合わせるためのインフラストラクチャが必要です。コードで実行することは不可能ではありませんが、IoC フレームワークを使用すると確かに簡単です。
多くの場合、重要なポイントは、 誰が プログラムの作成後に構成を変更しています。コード内の設定では、それを変更する人が元の作成者と同じスキルやソース コードなどへのアクセス権を持っていると暗黙的に想定されます。
運用システムでは、設定の一部のサブセットを抽出することが非常に実用的です (例:あなたの例では年齢)をXMLファイルに変換し、たとえば許可します。システム管理者またはサポート担当者は、ソース コードやその他の設定に対する全権限を与えずに値を変更したり、単に複雑さから切り離したりすることができます。
Spring の観点から、私は 2 つの答えを与えることができます。
まず、XML 構成は構成を定義する唯一の方法ではありません。ほとんどのことはアノテーションを使用して構成できますが、XML を使用して行う必要があるのは、ライブラリから使用している接続プールなど、作成しないコードの構成です。Spring 3には、例のハンドロールDI構成と同様に、Javaを使用してDI構成を定義するメソッドが含まれています。したがって、Spring を使用するからといって、XML ベースの構成ファイルを使用する必要があるわけではありません。
次に、Spring は単なる DI フレームワークではありません。トランザクション管理や AOP など、他にも多くの機能があります。Spring XML 構成は、これらすべての概念を組み合わせたものです。多くの場合、同じ構成ファイル内で Bean の依存関係、トランザクション設定を指定し、バックグラウンドで AOP を使用して実際に処理するセッション スコープの Bean を追加します。XML 構成は、これらすべての機能を管理するのに適した場所であることがわかりました。また、アノテーション ベースの構成と XML 構成は、Java ベースの構成を行うよりもスケールアップが優れていると感じています。
しかし、あなたの言いたいことはわかりますし、Java で依存関係注入構成を定義することに何も問題はありません。私は通常、単体テストや、DI フレームワークを追加していないほど小規模なプロジェクトに取り組んでいるときに、これを自分で行います。私は通常、Java で構成を指定しません。それは、Spring を使用することを選択したときに、Java で構成を指定する必要があるためです。ただし、これは好みであり、XML 構成が Java ベースの構成より優れているという意味ではありません。
Spring にはプロパティ ローダーもあります。このメソッドを使用して、環境に依存する変数を設定します (例:開発、テスト、受け入れ、実稼働など)。これは、たとえば、リッスンするキューなどです。
プロパティを変更する理由がない場合、このように設定する理由もありません。
あなたのケースは非常に単純であるため、Spring のような IoC (制御の反転) コンテナーは必要ありません。一方、「実装ではなくインターフェイスに対してプログラミングする」場合 (これは OOP の良い習慣です)、次のようなコードを作成できます。
IService myService;
// ...
public void doSomething() {
myService.fetchData();
}
(myService のタイプは IService であることに注意してください。具体的な実装ではなくインターフェイスです)。初期化中に IoC コンテナーが IService の正しい具体的なインスタンスを自動的に提供できるようにすると便利です。多くのインターフェイスと多くの実装がある場合、それを手動で行うのは面倒な場合があります。IoC コンテナ (依存関係注入フレームワーク) の主な利点は次のとおりです。
- インターフェースとその具体的な実装間のマッピングの外部構成
- IoC コンテナは、複雑な依存関係グラフの解決、コンポーネントの有効期間の管理など、いくつかの難しい問題を処理します。
- マッピングを手続き型コードではなく宣言的に提供するため、コーディング時間を節約できます。
- 制御の反転原理により、実際の実装を偽の実装に置き換えることができるため (SQL データベースをメモリ内の実装に置き換えるなど)、単体テストが容易になります。
XML 構成ファイルで初期化すると、コンピューターにアプリをデプロイしているクライアントとのデバッグ/適応作業が簡素化されます。(再コンパイル+バイナリファイルの置き換えが不要なため)
最も魅力的な理由の 1 つは、「ハリウッドの原則":電話しないでください、私たちがあなたに電話します。コンポーネントは、他のコンポーネントやサービス自体へのルックアップを行う必要はありません。代わりに、それらは自動的に提供されます。Java では、これはコンポーネント内で JNDI ルックアップを行う必要がなくなったことを意味します。
また、コンポーネントを単独で単体テストすることもはるかに簡単です。必要なコンポーネントの実際の実装を与える代わりに、(おそらく自動生成された) モックを使用するだけです。