6

現在のプロジェクトでは、DDD / オニオン アーキテクチャをますます採用しています。私がまだはっきりしていない多くのことの 1 つは、どの程度のカプセル化が必要かということです。具体例でわかりやすく説明。

namespace MyProject.Model
{
    public class ComplexEntity
    {
        private int _id;
        public int Id { get {return _id;} }
        public ValueObjectA ValueA {get; set;}
        public bool IsBool {get; set;}
        public ComplexEntity(ValueObjectA a, bool isBool)
        {
            // Do some validation first
            ValueA = a;
            ValueB = b;
            IsBool = isBool;
        }
    }

    public class ValueObjectA
    {
        public bool IsBoolA {get; private set;}
        public bool IsBoolB {get; private set;}
        public ValueObjectA(bool a, bool b)
        {
            IsBoolA = a;
            IsBoolB = b;
        }
    }

    public Interface IComplextEntityFactory
    {
        // Option 1
        ComplexEntity Create(
            ValueObjectA a,
            bool IsBool);

        // Option 2
        ComplexEntity Create(
            bool valueABool a,
            bool valueBBool b,
            bool isBool);
    }
}

質問

エンティティの工場については、

  1. 呼び出し元が値オブジェクトを構築し、それを使用して ComplexEntity を初期化することを期待しますか?
  2. 基本的に CLR の基本型をファクトリに渡し、エンティティを構成するすべての ValueObject を作成しますか?

私はオプション 2 に傾いていますが、それを裏付ける文献が見つからないようです。

編集 1

正直なところ、私はまだはっきりしていません。集約ルートはどうですか?

my entity が他のエンティティを参照する場合 (例: 以下)。

  1. IComplexEntityFactory,が必要ILessComplexEntityFactoryですか? またはIComplexEntityAggregateFactory、 LessComplexEntity を作成し、 ComplexEntity をインスタンス化するだけですか?
  2. AggregateFactory ソリューションの場合、ファクトリに渡された LessComplexEntity 属性が既存の LessComplexEntity に対応する場合はどうすればよいですか? リポジトリから取得して再利用しますか? それとも、呼び出し元にエラーを返しますか?
  3. AggregateFactory のメソッド シグネチャは何ですか? (ValueObject a, ValueObject b)、または(ValueObject value, LessCompelxEntity entity)

    public class ComplexEntity { プライベート readonly int _id; public int Id { get { return _id;} }

    public ValueObject Value {get; set;}
    public LessComplexEntity Entity {get; set;}
    
    public ComplexEntity(int id, ValueObject value, LessComplexEntity entity)
    {
    }
    

    }

    public class LessComplexEntity { プライベート readonly int _id; public int Id { get {return _id;} } public ValueObject 値 {get; set;} public LessComplexEntity(int id, ValuObject value) { } }

4

2 に答える 2

5

オプション1を選択します。

  • ComplexEntity を構築するには ValueObjectA が必要であることをすべての人に明示します。どこかで使用されているメソッドを見ると、より読みやすく、頭を悩ませることが少なくなります。

  • ValueObjectA が変更された場合、Create() のシグネチャを変更してファクトリ内の値オブジェクトの作成を調整するのではなく、コードを 1 か所 (ファクトリの呼び出し元) だけで変更する必要があります。

  • ファクトリの Create() メソッドへのパラメータが少ないほど、冗長性​​が低くなり、読みやすくなります。

  • 単体テストでは、必要な ValueObjectA を注入できるようにするためのより多くのオプションが提供されます。ValueObjectA の作成をファクトリ内に完全に隠しておくと、テストに関してできることは多くありません。

[編集]

Aggregate Roots and Factory の実際の問題が何であるかは明確ではありませんが、既存のオブジェクトを取得/再水和する責任と、オブジェクトを作成する責任を混同しないでください。

一般的なルールとして、Factory の仕事は小さなパーツ (プリミティブ型、値オブジェクト、エンティティなど) から新しいオブジェクトを組み立てることだと思います。

工場にはこれらすべての部品が提供されるべきであり、どこかからそれらを回収または再水和することは工場の義務ではありません。それは Factory の呼び出し元に任せることができます。これにより、ファクトリがよりまとまりがあり、より少ないクラス (リポジトリなど) に結合されます。

于 2012-07-09T14:26:04.427 に答える
2

ファクトリ メソッドで必要なパラメーターの数を減らすため、オプション #1 をお勧めします。しかし、私のアドバイスは、問題の集計が作成戦略を必要とする場合にのみファクトリを使用することです。

あなたのコメントの 1 つで、次のように述べています。

「..しかし、私はファクトリの利点を理解していません。その場合、それを構成するすべてのサブコンポーネントを作成するのではなく、ComplexEntity のコンストラクタを呼び出すだけです。」

ファクトリの仕事は、渡されたデータを見て、集計をインスタンス化する方法を決定することです。私の経験では、これが必要となる一般的なシナリオは、継承/ポリモーフィズムが使用されている場合です。たとえば、SavingsAccount と CurrentAccount という 2 つのサブクラスを持つ抽象 Account クラスがあるとします。ファクトリの仕事は、与えられたデータからインスタンス化するものを決定することです。

ファクトリのもう 1 つの潜在的な利点は、表現力です。集約が複数の方法 (つまり、異なる引数) でインスタンス化できる場合、これは、オーバーロードされたコンストラクターよりもファクトリのメソッド名でより適切に表現できます。

私が言うように、私のアドバイスは、上記の理由のいずれかでない限り、すべての集計に対してファクトリを作成しないことです。それ以外の場合は、指摘したように、同じ引数が渡されたコンストラクターを呼び出す 1 行だけになります。

于 2012-07-09T14:01:45.230 に答える