13

約7つのパラメーターを必要とするCSVファイル操作から製品をインポートするためのクラスがあります。これはインポーターにとって絶対に必要な情報です。

このパラメータはすべて同じ寿命です。最後に、Immutable Objectが必要です。

読みやすさに影響するため、コンストラクターにすべてをリストするのが怖くて、そのうちの 3 つをセッター インジェクションに移動することにしました。しかし、明らかにそれはエレガントなソリューションではありません。

質問:

1) コンストラクターベースのインジェクションとセッターベースのインジェクションを混在させることは悪い習慣ですか?

2) この特定の問題をどのように解決できますか?

Martin Fowler による "Introduce Parameter Object" リファクタリングを適用することを考えていましたが、これには問題があります。

4 パラメータは非常に簡単に Parameter オブジェクトに移動できます (customerId、projectId、languageId など) - すべて整数です。

他の 3 つのパラメーターは、私が注入するオブジェクトです (モック単体テストに必要です)。

4

1 に答える 1

28

コンストラクター インジェクションとプロパティ インジェクションを混在させることは必ずしも悪いことではありませんが、それほど一般的ではないかもしれません。全体的な戦略として、正しく実装するのがはるかに難しいため、プロパティ インジェクションは避けてください (これは直感に反するように聞こえるかもしれませんが、本当です)。

各パターンをいつ使用するかを理解することが重要です。

  • コンストラクター インジェクションは、デフォルトのインジェクション パターンである必要があります。実装は非常に簡単で、不変条件を保証できます。読み取り専用フィールドに割り当てて、消費者の不変条件を保証します。
  • プロパティ インジェクションは、適切なLocal Default実装があるが、 Open/Closed Principleに従い、上級ユーザーが別の実装を提供してクラスを拡張できるようにする場合に使用できます。

コンストラクターの装飾のため、プロパティ インジェクションを適用しないでください。

必要な依存関係が多すぎる場合は、単一責任の原則に違反している可能性があることを示しています。つまり、クラスが一度に多くのことを実行しようとしているだけです。

パラメーター オブジェクトを導入する代わりに (それ以外の場合は良い提案です)、2 つ以上の依存関係を、これらの依存関係の相互作用を調整する集約サービスにカプセル化することをお勧めします。

初期コンストラクターが次のようになっていると想像してください。

public MyClass(IDep1 dep1, IDep2 dep2, IDep3 dep3, IDep4 dep4, IDep5 dep5)

少し分析を適用した後、この場合、IDep1、IDep3、および IDep4 が特定の方法で一緒に使用されることがわかります。これにより、これらを次のようにカプセル化した集約サービスを導入できます。

public class AggService : IAggService
{
    public AggService(IDep1 dep1, IDep3 dep3, IDep4 dep4)
    {
        // ...
    }

    // ...
}

元のコンストラクターを次のように書き換えることができます。

public MyClass(IAggService aggSrvc, IDep2 dep2, IDep5 dep5)

などなど…

集約サービス自体が適切な概念であることが判明することは非常によくあることであり、突然、開始時よりも豊富な API を使用できるようになります。

于 2009-12-31T15:25:12.537 に答える