質問

私は最近 StructureMap を使用しており、その経験をとても楽しんでいます。ただし、すべてをインターフェイスすることに簡単に夢中になり、大量のインターフェイスをコンストラクターに取り込むクラスができてしまうのはわかります。依存関係注入フレームワークを使用している場合、それは実際には大きな問題ではありませんが、インターフェイスするためだけに実際にインターフェイスする必要のない特定のプロパティが存在すると感じます。

何をインターフェース出力するのか、単にプロパティをクラスに追加するのか、どこで線を引くのでしょうか?

役に立ちましたか?

解決

デザインについて考えてみましょう。DI を使用すると、構成変更を通じてコードの機能を変更できます。また、クラス間の依存関係を解消できるため、オブジェクトの分離とテストが容易になります。これがどこで意味があり、どこで意味がないかを判断する必要があります。完璧な答えはありません。

経験則として、テストが難しすぎる場合は、単一の責任と静的な依存関係に関する問題が発生していると考えられます。単一の関数を実行するコードをクラスに分離し、インターフェイスを抽出し、DI フレームワークを使用して実行時に正しいインスタンスを挿入することで、静的な依存関係を解消します。こうすることで、2 つの部分を個別にテストすることが簡単になります。

他のヒント

依存関係の注入の主な問題は、疎結合アーキテクチャのように見えても、実際はそうではないことです。

実際にやっていることは、その結合をコンパイル時からランタイムに移行することですが、クラス A が機能するためにインターフェイス B が必要な場合は、インターフェイス B を実装するクラスのインスタンスを提供する必要があります。

依存関係の注入は、基本コードを再コンパイルせずに動的に変更する必要があるアプリケーションの部分にのみ使用してください。

Inversion of Control パターンに役立つと思われる使用例:

  • プラグインのアーキテクチャ。したがって、適切なエントリ ポイントを作成することで、提供する必要があるサービスの契約を定義できます。
  • ワークフローのようなアーキテクチャ。複数のコンポーネントを接続して、コンポーネントの出力を別のコンポーネントの入力に動的に接続できます。
  • クライアントごとのアプリケーション。プロジェクトの一連の「機能」に対して料金を支払うさまざまなクライアントがいるとします。依存関係の注入を使用すると、コア コンポーネントと、クライアントが支払った機能だけを提供するいくつかの「追加」コンポーネントだけを簡単に提供できます。
  • 翻訳。これは通常、翻訳目的では行われませんが、アプリケーションの必要に応じて、さまざまな言語ファイルを「挿入」できます。これには、必要に応じて RTL または LTR ユーザー インターフェイスが含まれます。

依存関係注射は、基本コードを再コンパイルせずに動的に変更する必要があるアプリケーションの部分にのみ使用する必要があります

DI は、コードを外部リソース (データベース、Web サービス、XML ファイル、プラグイン アーキテクチャ) から分離するために使用する必要があります。データベースに依存するコンポーネントをテストする場合、コード内のロジックをテストするのにかかる時間は、多くの企業では法外なほど時間がかかります。

ほとんどのアプリケーションでは、データベースは動的に変更されません (動的に変更される可能性はあります) が、一般的に言えば、アプリケーションを特定の外部リソースにバインドしないことがほとんどの場合に推奨されます。リソースの変更に伴う量は少なくなければなりません (データ アクセス クラスのメソッド内で循環的複雑度が 1 を超えることはほとんどありません)。

「クラスにプロパティを追加するだけ」とはどういう意味ですか?

私の経験則は、クラスを単体テスト可能にすることです。クラスが別のクラスの実装の詳細に依存している場合は、クラスを分離してテストできるようにリファクタリング/抽象化する必要があります。

編集:コンストラクター内の大量のインターフェイスについて言及しています。代わりにセッター/ゲッターを使用することをお勧めします。そうすることで、長期的には維持しやすくなることがわかりました。

懸念を分離するのに役立つ場合にのみそれを行います。

おそらくクロスプロジェクトのように、ライブラリプロジェクトの1つで実装者にインターフェイスを提供し、実装プロジェクトは彼らが望む特定の実装を注入します。

でもそれだけです...他のすべての場合、システムが不必要に複雑になるだけです

世界中のすべての事実とプロセスがあっても..すべての決断は結局は判断の判断に帰結する - どこで読んだか忘れた
それはむしろ経験や飛行時間の問題だと思います。基本的に、依存関係が近い将来置き換えられる可能性のある候補オブジェクトとして認識される場合は、依存関係の注入を使用します。「classA とその依存関係」を置換用の 1 つのブロックとして見る場合、私はおそらく A の deps に DI を使用しないでしょう。

最大の利点は、アプリケーションのアーキテクチャを理解し、さらには明らかにするのに役立つことです。依存関係チェーンがどのように機能するかを非常に明確に確認できるようになり、関係のない部分を変更することなく、個々の部分を変更できるようになります。最終的には疎結合アプリケーションが完成します。これにより、より良い設計が可能になり、今後もコードを分離して整理し続けるのに設計が役立つため、改善を続けることができることに驚かれることでしょう。また、特定のインターフェイスの実装を自然に置き換えることができるため、単体テストも容易になります。

使い捨てのアプリケーションもいくつかありますが、疑問がある場合は、インターフェイスを作成することにします。ある程度練習すればそれほど負担にはなりません。

私が取り組んでいるもう一つのアイテムは、 どこで依存性注入を使用すればよいですか? StructureMap への依存関係はどこにありますか?スタートアップアプリケーション内だけですか?それは、すべての実装を最上層から最下層までずっと引き継がなければならないことを意味しますか?

私は Castle Windsor/Microkernel を使用しています。他には何も使用した経験がありませんが、とても気に入っています。

注射するものはどうやって決めるのですか?これまでのところ、次の経験則が役に立ちました。クラスが非常に単純で単体テストが必要ない場合は、クラス内で自由にインスタンス化できます。そうでない場合は、コンストラクターを介して依存関係を持たせる必要があるでしょう。

インターフェイスを作成する必要があるのか​​、単にメソッドとプロパティを仮想化する必要があるのか​​については、次のいずれかの場合、クラスが別のアプリケーションである程度の再利用可能性を持っていることが確認できる(つまり、ロガー) または b) コンストラクターのパラメーターの量、またはコンストラクターに大量のロジックがあるため、クラスをモックすることが困難な場合。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top