4

私は依存性注入について読んでいて、多くのフレームワークで行われているように、XML で依存性を指定することの魅力を理解しています。私は通常、工場を呼び出して具体的なオブジェクトを取得する大規模なシステムに取り組んでおり、このウィキペディアの記事に示されているように、手動で注入された依存関係がおそらくより優れている理由を理解するのに苦労しています。

次の理由から、ファクトリを呼び出す方が良いように思えます。

  1. コードの呼び出しでは、特定の依存関係が存在することを認識したり気にしたりする必要はありません。
  2. 新しい依存関係が呼び出し先に追加された場合、呼び出しコードを変更する必要はありません。
  3. 呼び出しコードには、注入する具体的なインスタンスを選択する専用のロジックは必要ありません。

依存関係の注入は、呼び出し元のコードが依存関係の具象クラスを決定する必要がある場合にのみメリットがあるように思えます。「これが私のデータです。今処理します」のようなものです。

見逃したものはありますか?

更新: 明確にするために、既存のコードのほとんどはファクトリを直接呼び出します。したがって、新しい Ball オブジェクトを取得するには、次のようなコードが表示されます。

Ball myBall = BallFactory.getObject();

これらのファクトリの多くは、新しい具体的なオブジェクト タイプ (プラグイン フレームワーク) を実行時に登録できるように実装されています。

したがって、最初のコメントのいくつかを見ると、DI の場合、私の呼び出しコードは通常、Ball オブジェクトではなく、BallFactory を渡すように見えます。その利点は、クラスが使用するファクトリへの結合さえないため、クラスがよりジェネリックになる可能性があることだと思います。

4

4 に答える 4

3

依存性注入は、単体テストの際に役立ちます。クラスの依存関係のいずれかをクラスに注入できる(したがって、モックもできる)ため、クラスの機能を分離して分離することができます。これは、依存関係がDBなどの外部リソースにアクセスする場合に特に役立ちます。

最近、テストにおける依存性注入の利点を示した記事を読みました。具体的には静的メソッドに関するものですが、同じことが工場にも当てはまります。

http://misko.hevery.com/2008/12/15/static-methods-are-death-to-testability/

@decezeが言うように、工場に注入すると、両方の長所を活用できます...

于 2012-08-17T14:02:29.477 に答える
2

どちらが「優れている」というわけではありません。依存性注入を単独で使用することも、ファクトリを単独で使用することも、これらを組み合わせて使用​​することもできます。

また、工場について言及した 3 つのポイントはすべて、依存性注入に対しても同様に有効です。依存関係は、必ずしも即時の「呼び出しコード」によってではなく、いつでも注入できることに注意してください。実際、これが DI フレームワークの役割です。基本的には、メイン アプリケーション オブジェクトを作成し、すべての依存関係を注入する巨大なファクトリです。

ファクトリを明示的に使用することは、コードが実行時に依存関係の新しいインスタンスを作成できる必要がある場合にのみ役立ちます。それ以外の場合は、単純に DI フレームワークを使用して、アプリケーションの起動時にすべての静的依存関係を注入する方がはるかに簡単です。

于 2012-08-18T04:48:52.053 に答える
2

依存性注入と抽象ファクトリを組み合わせて使用​​すると便利なことがよくありますが、それには 2 つの理由があります。(手動)依存性注入を使用する理由は、単体テスト中に特別なオブジェクトを注入できるようにするためです。呼び出し元のコードがオブジェクトの作成を担当しないことを設計が示している場合 (1-2-3 の箇条書きのように)、提供された依存関係は抽象ファクトリのインスタンスになります。is が注入されるオブジェクトは、必要に応じてファクトリを使用してオブジェクトを作成します。

2 つのファクトリを使用して、バックギャモンの簡単なゲームと難しいゲームの依存関係 (ここでは 1 つの依存関係、Dice) を生成するとします。

public class EasyGameFactory implements GameFactory
{
  Dice createDice()
  {
    return new LuckyDice();
  }
}

public class NormalGameFactory implements GameFactory
{
  Dice createDice()
  {
    return new RandomDice();
  }
}

単体テストの目的で、Dice 実装のどちらも使用したくないので、GameFactory の特別な実装を作成します。

public class CustomGameFactory implements GameFactory
{
  private Dice mDice;

  public CustomGameFactory(Dice dice)
  {
    mDice = dice;
  }

  Dice createDice()
  {
    return mDice;
  }
}

このファクトリは、生産コード ツリーの一部である必要はありません。テスト コードを使用して、Dice の特別な実装をファクトリに提供します。

public class TestBackgammon
{
  @Test public void shouldReturnDiceThrown() 
  {
    SettableDice dice = new SettableDice();
    Game game = new GameImpl(new CustomGameFactory(dice));

    dice.setDice(new int[] {4, 5});
    game.nextTurn();
    assertArrayEquals(new int[] {4, 5}, game.diceThrown());
  }
}
于 2012-08-18T08:27:14.060 に答える
1

printf依存性注入を使用するかどうかは、C での使用と使用の違いに少し似ていfprintfます。発信者は、選択をしなければならないという代償を払って柔軟性を得ます。呼び出し元が柔軟性を必要としない場合 (たとえば、プログラムのすべての出力が stderr またはファイルではなく stdout に送られる場合)、柔軟性は純粋な負担です。呼び出し元は常に同じ「正しい」値を渡さなければならないからです。

依存性注入を純粋な負担と見なす場合、それは呼び出し元が実際には使用していないことを意味します。

あなたのポイント1と3はどちらも、「呼び出し元のコードが何が起こるかに影響を与える自由が少ない」と言っていますが、これは必ずしも利点ではありません。特にテスト コードは、依存関係を注入することでメリットが得られますが、呼び出し元が他の理由で柔軟性を必要とする場合もあります。でログを記録しますprintfか、それともインジェクトされたロガーで関数を呼び出してログを記録しますか?

ポイント 2 は、API をどのように進化させるかにかかっています。はい、元の設計を変更する必要がある場合は、固定された非表示の依存関係を使用することで、API がその変更を反映するのを防ぐことができます。場合によっては、新しい依存関係のデフォルト値で古い API を維持し、追加のパラメーターを使用して新しいメソッド/コンストラクターをどこかに追加できます。

とはいえ、私が使用した言語の標準ライブラリは、大量の依存性注入を必要としません。したがって、API がそれを必要としないと考えているのはあなただけではありませんが、現在よりも社内でより多くのことを得ることができるのではないかと思います。たとえば、リモート マシンに接続せずにネットワーク コードをテストできますか? そうでない場合は、テスト手順のその部分がより簡単で迅速であり、可能であればより正確な診断ができるかどうかを検討してください.

于 2012-08-17T14:14:35.020 に答える