5

ApplicationSettingsクラスが、私のアプリケーションに適用される TimeoutPeriod、 DefaultUnitOfMeasure 、HistoryWindowSize などの設定の一般的なリポジトリであるとします。そして、MyClass がそれらの設定の 1 つである DefaultUnitOfMeasure を利用するとします。

Inversion of Control Containers の適切な使用についての私の読みは、コンストラクターでクラスの依存関係を定義することです。これについて間違っている場合は修正してください。

public class MyClass {
  public MyClass(IDataSource ds, UnitOfMeasure default_uom) {...}
} 

そして、次のような方法でクラスのインスタンス化を呼び出します

var mc = IoC.Container.Resolve<MyClass>();

IDataSourceに具体的な実装が割り当てられ、default_uom が接続されてApplicationSettings.DefaultUnitOfMeasureプロパティからインスタンス化されます。しかし、これらすべてのフープがジャンプするために本当に必要なのかどうか疑問に思う. 私は何のために自分を設定していますか?

public class MyClass {
  public MyClass(IDataSource ds) {
    UnitOfMeasure duom = IoC.Container.Resolve<UnitOfMeasure>("default_uom");
  }
} 

はい、私のクラスの多くはIoC.Containerに依存することになりますが、それは私のクラスのほとんどが持つ依存関係です。クラスが結合されている限り、それを最大限に活用する必要があるようです。アジャイルの達人、どこが間違っているか教えてください。

4

4 に答える 4

4

IoC.Container.Resolve( "default_uom");

これは、IoCコンテナをサービスロケーターとして使用している古典的なアンチパターンだと思います。結果として生じる主な問題は次のとおりです。

  • コンテナーが誤って構成されている場合でも、アプリケーションが失敗することはありません(特定のロジック/状況のセットを除いて発生しない可能性がある、コード内の特定のサービスを初めて解決しようとするときにのみわかります)。
  • テストは難しい-もちろん不可能ではありませんが、テスト用にウィンザーコンテナーの実際の(および半構成された)インスタンスを作成するか、シングルトンにIWindsorContainerのモックを注入する必要があります-これにより、テストに多くの摩擦が加わります。コンストラクター/プロパティを介してテスト対象のクラスにモック/スタブサービスを直接渡すことができるのと比較して。
  • この種のアプリケーションを維持するのは難しい(構成は1つの場所に一元化されていない)
  • 他の多くのソフトウェア開発原則(DRY、SOCなど)に違反している

元のステートメントの懸念される部分は、ほとんどのクラスがIoCシングルトンに依存していることを意味します-コンストラクター/依存関係を介してすべてのサービスが注入されている場合、IoCとの緊密な結合は例外です。ルール-一般に、コンテナーへの依存関係を取得するのは、循環依存関係の問題を回避しようとする、または何らかの理由で実行時にコンポーネントを作成したいなど、トリッキーなことをしているときだけです。多くの場合、汎用IServiceProviderインターフェイス以外のものに依存することは避け、元のプロジェクト以外の環境でコンポーネントを再利用する必要がある場合は、ホームベイクIoCまたはサービスロケーターの実装に切り替えることができます。

于 2008-09-23T03:26:33.623 に答える
4

通常、IoC コンテナーに応じて多くのクラスはありません。私は通常、他のクラスに注入するファサード オブジェクトに IoC をラップしようとしますが、通常、IoC インジェクションのほとんどは、アプリケーションの上位層でのみ行われます。

自分のやり方で行うと、テスト用の IoC 構成を作成せずに MyClass をテストすることはできません。これにより、テストの保守が難しくなります。

もう 1 つの問題は、IoC 構成ファイルを編集して構成を変更したいソフトウェアのパワーユーザーが必要になることです。これは私が避けたいことです。IoC 構成を通常の構成ファイルと IoC 固有のものに分割できます。ただし、通常の .Net 構成機能を使用して構成を読み取ることもできます。

于 2008-09-22T14:39:55.743 に答える
2

特定の例についてコメントするには:

public class MyClass {
    public MyClass(IDataSource ds) {
        UnitOfMeasure duom = IoC.Container.Resolve<UnitOfMeasure>("default_uom");
    }
}

これにより、クラスを再利用することが難しくなります。より具体的には、制限している狭い使用パターンの外でクラスをインスタンス化するのが難しくなります。これが明らかになる最も一般的な場所の1つは、クラスをテストしようとするときです。UnitOfMeasureをコンストラクターに直接渡すことができる場合は、そのクラスをテストする方がはるかに簡単です。

また、UOMインスタンスの名前( "default_uom")の選択は、クラスの使用法によっては、値がオーバーライドされる可能性があることを意味します。その場合、そのようなコンストラクターで値を「ハードコーディング」したくないでしょう。

コンストラクターインジェクションパターンを使用しても、クラスがIoCに依存することはありません。その逆に、クライアントはIoCを使用するかどうかを選択できます

于 2008-09-23T03:50:44.907 に答える
2

はい、私のクラスの多くはIoC.Containerに依存することになりますが、それは私のクラスのほとんどがとにかく持つ依存関係です。

これが問題の核心だと思います。実際、ほとんどのクラスがIoCコンテナー自体に結合されている場合は、設計を再考する必要があります。

一般的に、アプリはブートストラップ中に一度だけコンテナクラスを直接参照する必要があります。コンテナに最初にフックした後、オブジェクトグラフの残りの部分はコンテナによって完全に管理され、これらのオブジェクトはすべて、IoCコンテナによって作成されたという事実に気付かないはずです。

于 2008-09-22T14:34:37.627 に答える