32

私はDDDを使い始めたばかりなので、これはばかげた質問かもしれません...

実行時に値を取得するためにエンティティが (いくつかの IRepository インターフェイスを介して) リポジトリにアクセスしても問題ありませんか? たとえば、プロパティの「デフォルト」選択を強制したい:

class Person {
    private Company _employer;

    public Company Employer {
        get { return _employer; }
        set { 
            if(value != null) {
                _employer = value;
            } else {
                _employer = employerRepository.GetDefaultEmployer();
            }
        }
    }

    ...
}

私の質問は、このようなことを行うことが DDD の原則に対する恐ろしい違反であるかどうかです。そうでない場合、私の次の質問は、使用するリポジトリを提供する最良の方法は何ですか? Person オブジェクトの作成時に指定する必要がありますか?

ありがとう、P

4

5 に答える 5

26

それはDDDの恐ろしい違反ではありません.それは恐ろしい違反です...まあ...それはただひどいです(私はこの舌を頬に言います):)。

まず、エンティティはリポジトリを持つことに依存するようになります...これは理想的ではありません。理想的には、リポジトリで Person を作成し、現在のドメイン コンテキストで有効にするために必要なすべてのものを割り当てます。

そのため、Person が必要な場合は、 personRepository.GetPersonWithDefaultEmployer() に移動し、デフォルトの雇用主が設定されている人を取得します。personRepository は、employerRepository に依存しており、それを使用して個人を入力してから返します。

PersonReposotory : IPersonRepository
{
    private readonly IEmployerRepository employerRepository;

    //use constructor injection to populate the EmployerRepository
    public PersonRepository(IEmployerRepository employerRepository)
    {
        this.employerRepository = employerRepository;
    }

    public person GetPersonWithDefaultEmployer(int personId)
    {
        Person person = GetPerson(personId);
        person.Employer = employerRepository.GetDefaultEmployer(personId);
        return person;
    }
}
于 2009-05-06T01:54:08.003 に答える
7

あなたの質問に対する一種の答えは標準です:それは依存します.

経験則として、これは絶対に行わないでください。リポジトリへの参照なしでエンティティを保持します。

[実用的な帽子をかぶる]これを行う非常に、非常に、非常に正当な理由がある非常にまれなケースでは、なぜそれを行うのかを説明する大きなコメントを追加して実行します。参照を追加するか、Double Dispatchを使用して合格しますリポジトリ[脱帽]

また、DDD の原則に従いたい場合は、ドメインの専門家と反復的な開発プロセスにアクセスできることを強くお勧めします ( Eric Evans を参照してください - 私が本から学んだこと )。

ドメインの専門家と一緒に、境界コンテキストを定義する必要があります。最も重要なのは、集約とその集約ルート、およびそれらのエンティティと値オブジェクトです。最初は DDD の道を進むのは簡単ではありませんが、見返りはそれだけの価値があります。

あなたが投稿したコードに関するいくつかのこと:

  1. エンティティにパブリック セッターを設定することはお勧めしません。代わりに、意図をより適切に表現する方法を使用してください。

  2. _employer フィールドを初期化せずに person インスタンスを作成すると、Employer プロパティの getter は null を返します。その後、Employer プロパティの値を null に設定すると、次に getter を呼び出したときに null 以外の値が返されます。これは、クラスのユーザーにとっておそらく予期しないことです。

  3. Person の Employer を (パブリック セッターまたはパブリック メソッドによって) 設定する呼び出し元は、設定する必要がある正確な Company インスタンスを、それが既定のインスタンスであっても知っている必要があります。おそらく、呼び出し元はリポジトリへの参照を持つことができます。

  4. 具体的なドメインによっては、Company が値オブジェクトになる場合があります。その場合、_employer を null で初期化する代わりに、値オブジェクトのデフォルト値で初期化できます。これは、非常に少数の企業 (1 ~ 2) しかなく、それらが不変であり、特定の動作を持たない場合に当てはまります。

于 2011-03-22T09:58:23.033 に答える
5

エンティティがリポジトリを意識するべきではないと言うのは簡単ですが、それを実践するのは難しいと思います。特に、集約が内部に vo の大きなコレクションを取得する場合は、それをリファクタリングし、コレクション全体をメモリにロードするオーバーヘッドを回避するために、実際にリポジトリとして機能するドメイン サービスに追加するなどの操作を委任する必要があります。
しかし、エンティティにリポジトリを知らせるのは合理的ではないと思います。必要な場合は、代わりにドメイン サービスを使用して ください。また、リポジトリが単一責任の原則に違反しているかどうかも考慮する必要があります。リポジトリは、通常のファクトリではなく、集約ルートのコレクションと見なされるべきでした。

于 2013-08-11T18:02:40.723 に答える
0

まず、エンティティ自体とエンティティを組み立てる方法は、実際には2つの義務だと思います。したがって、理想的には、それらを異なるクラスに分散することをお勧めします。しかし、それも依存しています。

于 2013-08-10T05:26:13.137 に答える
0

ddd を実行することをお勧めしますか?

また、インメモリ リポジトリではなく、リポジトリ用のリレーショナル データベースがあり、1000 人の従業員を雇い主にしたい場合はどうでしょうか。employeeRepository 呼び出しで 1000 件のクエリを実行する予定ですか?

personRepository の実装を支援するために、NHibernate または任意の ORM を使用します。NHibernate では、これに近い Hibernate Query を使用します。「from Person join fetch Employer」は、各「Person」インスタンスに「Employer」インスタンスを 1 つの SQL クエリだけでロードします。

DDDに違反していますか?

于 2011-03-20T18:25:14.303 に答える