0

アプリケーションで依存性注入手法を利用しようとしていますが、このコンテキストで DI が必要かどうかで混乱します..

インターフェースを考えてみましょう:

public class ICardsHub {
    public T GetPlayersList<T>();
}

とその実装:

public class GenericHub : ICardsHub {

    LANPlayers LANPlayers;
    WaNPlayers WANPlayers;
    bool AlgorithmsUseTildainLambdas=false;

    public GenericHub(LANPlayers _LANPlayers, WaNPlayers _WANPlayers, 
                           bool algorithmsUseTildainLambdas=false) {
        LANPlayers = _LANPlayers;
        WANPlayers = _WANPlayers;
        AlgorithmsUseTildainLambdas = algorithmsUseTildainLambdas;
    }

    public T GetPlayersList<T>() {
        ....
    }

}

そして、ドライバークラスは次のようなことをすることになっています:

ICardsHub _ifCards = new GenericHub(_LANPlayers, _WANPlayers);
listOfPlayers = _ifCards.GetPlayersList<List<string>>();

ICardsHubこれで、さらに 2 つの;の実装ができました。これらは後でドライバー クラスでインスタンス化されますRedHubBlackHub

質問

  1. Unity IC/DIはこのシナリオにどのようなメリットをもたらしますか?
  2. 問題が解決する場合striping out method parameters from the interface and injecting them to overload constructor、DI コンテナーの使用に適したシナリオは何ですか?
4

3 に答える 3

2

DI により、コードの保守が容易になり、新しい実装への切り替えが容易になります。オーバーロードされたコンストラクターが目的を果たすことに同意しますが、依存関係が非常に多い場合でも、手動でコードを変更して効果的に各場所に移動し、手動で変更する必要があり、それらの一部を見逃すことがあります。中央に配置すると、保守が容易になります。これが、小規模なプロジェクトではなく、大規模なプロジェクトには DI が推奨されない理由です。DI の目的は TDD を解決することではないと思いますが、保守性が向上し、新しいクラスの実装に簡単に切り替えることができます。たとえば、今日はデータベースとして SQL SERVER を使用しており、明日は NOSQL に変更します。クラス名を 1 箇所変更することで、DB と対話するすべてのコードがすべての場所で正常に動作するようになります。TDDはその例の1つです

于 2013-03-30T02:14:09.320 に答える
1

DI の主な動機は、テスト容易性、IMHO です。したがって、テスト パラダイムの外を見ると、混乱が生じる可能性があります。

あなたが説明した例では、ICardsHub が GenericHub、RedHub、および BlackHub の実装のコントラクトを定義していることがわかります。

これらの各実装には、それを異なるものにするいくつかのロジックがあるため、異なるクラスが存在する必要があります。

これらのクラスをテストするために (それぞれの責任は固有です)、これらのクラスがジョブを実行できるようになる前に実行する必要があるいくつかの手順があり、これらの手順の後にもいくつかの手順が必要になる場合があります。

このクラスのテストの範囲は、「事前」ステップにエラーがないことを確認することです。このクラスによって行われたアクションは、「事後」ステップが消費するエラーのない出力を持ちます。

これを念頭に置いて、依存性注入により、次のことが可能になります

  1. 前提条件を簡単に仮定する (つまり、仮定をセットアップしてモック オブジェクトを注入する)
  2. アクションを実行する (このクラスの責任)
  3. 出力を確認します。

ところで、実装では具体的な型ではなくインターフェイスを注入する必要があります。何かのようなもの -

ILANPlayers LANPlayers;
IWaNPlayers WANPlayers;
bool AlgorithmsUseTildainLambdas=false;

public GenericHub(ILANPlayers _LANPlayers, IWaNPlayers _WANPlayers, 
                       bool algorithmsUseTildainLambdas=false) {
    LANPlayers = _LANPlayers;
    WANPlayers = _WANPlayers;
    AlgorithmsUseTildainLambdas = algorithmsUseTildainLambdas;
} 

したがって、テストでは、これらの型の本質的にモック実装であるモックILanPlayersを作成できます。IWanPlayers

于 2013-03-30T02:13:12.057 に答える
0

一般に、単体テストの実行を支援するためにのみ DI を使用します。インターフェイスに対してコーディングする必要があるため、DI を使用してコンポーネントを簡単にモックできます。

あなたのシナリオでは、ICardHub インターフェイスの実装を使用するいくつかのクライアント クラスがあります。問題は、これらの実装のいずれかがデータベース操作またはその他の外部使用を実行するかどうかです。そうでない場合は、DI を使用しない方がよいでしょう。

それでも DI を使用したい場合は、代わりに AutoFac を使用してください。IMO での作業は簡単です。

「ライブラリ」をオフに作成できると思われるコードがある場合、それは DI の良い候補です。これらのコンポーネントはプロバイダーとして考える必要があり、一般的に DI は新しいものではありません。DI は、必要なプロバイダーのインスタンスを作成することからアプリケーションの責任を取り除くだけであり、それを行うのは DI コンテナーであり、アプリケーションはインターフェースのみで動作します。

例を次に示します。

  • DIなし

    IDatabase database = new SqlServer();
    
  • DIあり

    IDatabase database = DIContainer.Get<IDatabase>();
    

ご覧のとおり、アプリケーションは SqlServer データベースを使用しますが、それについては何も知りません。はい、その型を DI コンテナーに登録する必要がありますが、これを行うのは 1 回だけです。したがって、後で他の実装に変更することにした場合、それは非常に簡単です。

于 2013-03-30T02:12:43.100 に答える