34

これは実用的なドメイン駆動設計の問題です。

概念的には、集約ルートを定義するまで取得すると思います。

Aggregate ルートとして表示されている Employee エンティティがあります。ビジネスでは、一部の従業員が業務関連の違反をログに記録することがあります。

従業員-----*違反

すべての従業員がこれに該当するわけではないので、違反は従業員集計の一部ではないと思いますよね?

従業員とそれに関連する違反を処理したい場合、この 2 つの別個のリポジトリ インタラクションはサービスによるものですか?

最後に、違反を追加すると、そのメソッドは従業員エンティティにあるのでしょうか? 助けてくれてありがとう!

4

7 に答える 7

26

さらに多くの調査を行った後、私は自分の質問に対する答えを持っていると思います.

Paul Stovell は、 DDD メッセージボードでの同様の質問に対して、このわずかに編集された応答をしました。「従業員」を「顧客」に、「違反」を「注文」に置き換えてみてください。

Customer が Order を参照しているからといって、必ずしも Order が Customer 集約ルート内にあるとは限りません。顧客の住所は独立している可能性がありますが、注文は独立している可能性があります (たとえば、顧客が誰であるかに関係なく、すべての新しい注文を処理するサービスがある場合があります。このシナリオでは、顧客 -> 注文に移動する必要はありません)。

ドメインの観点からは、これらの参照の有効性を疑問視することさえできます (顧客は注文のリストを参照しています)。顧客のすべての注文が実際に必要になる頻度はどれくらいですか? 一部のシステムでは理にかなっていますが、他のシステムでは、1 人の顧客が多くの注文を行う場合があります。日付範囲内の顧客の注文、まだ処理されていない顧客の注文、または未払いの注文などが必要になる可能性があります。それらすべてが必要になるシナリオは比較的まれです。ただし、注文を処理する場合は、顧客情報が必要になる可能性が高くなります。したがって、コードでOrder.Customer.Nameは便利ですが、Customer.Orders[0].LineItem.SKUおそらくそれほど便利ではありません。もちろん、それはあなたのビジネスドメインに完全に依存します.

つまり、顧客の更新は注文の更新とは何の関係もありません。そして、注文、または私の場合の違反は、顧客/従業員とは無関係に処理されると考えられます.

違反に詳細行がある場合、違反行を変更すると違反に影響する可能性があるため、違反と違反行は同じ集計の一部になります。

編集** 私のドメインのしわは、違反には動作がないことです。それらは基本的に、起こった出来事の記録です。その影響についてはまだわかりません。

于 2009-05-08T00:01:45.073 に答える
23

Eric Evanは、彼の著書「ドメイン駆動設計:ソフトウェアの中心にある複雑さへの取り組み」で次のように述べています。

AGGREGATEは、データ変更の目的で1つの単位として扱う関連オブジェクトのクラスターです。

ここには2つの重要なポイントがあります。

  1. これらのオブジェクトは「ユニット」として扱う必要があります。
  2. 「データ変更」を目的としています。

あなたのシナリオでは、従業員と違反は必ずしも一緒のユニットではありませんが、OrderとOrderItemの例では、それらは単一のユニットの一部であると思います。

集合体の境界をモデル化するときに重要なもう1つのことは、集合体に不変条件があるかどうかです。不変条件は、「全体」の集合体内で有効である必要があるビジネスルールです。たとえば、OrderとOrderItemの例の場合、注文の合計コストが事前定義された金額よりも少なくなければならないことを示す不変条件がある場合があります。この場合、OrderItemをOrderに追加するときはいつでも、この不変条件を適用して、Orderが有効であることを確認する必要があります。しかし、あなたの問題では、あなたのエンティティ間で不変条件は見られません:従業員と違反。

とても短い答え:

従業員と違反はそれぞれ2つの別々の集合体に属していると思います。これらの各エンティティは、独自の集約ルートでもあります。したがって、EmployeeRepositoryとViolationRepositoryの2つのリポジトリが必要です。

また、違反から従業員への一方向の関連付けが必要だと思います。このようにして、各違反オブジェクトはそれが誰に属しているかを認識します。ただし、特定の従業員のすべての違反のリストを取得する場合は、ViolationRepositoryに問い合わせることができます。

var list = repository.FindAllViolationsByEmployee(someEmployee);
于 2010-04-01T06:59:22.950 に答える
2

従業員エンティティと違反があり、各違反には動作自体がないと言います。上記の内容から、集約ルートが 2 つあるように思われます。

  • 従業員
  • EmployeeViolations (EmployeeViolationCard または EmployeeViolationRecords と呼びます)

EmployeeViolations は同じ従業員 ID によって識別され、違反オブジェクトのコレクションを保持します。このように、従業員の動作と違反を分離​​して取得し、動作のない違反エンティティを取得しません。

違反がエンティティか値オブジェクトかは、そのプロパティに基づいて決定する必要があります。

于 2012-01-08T09:53:50.083 に答える
1

これについては、Mosh に概ね同意します。ただし、ビジネスの観点から見たトランザクションの概念に注意してください。したがって、実際には「データ変更の目的で」を「トランザクションの目的で」と解釈します。

リポジトリは、ドメイン モデルのビューです。ドメイン環境では、これらの「ビュー」は実際にビジネス機能または機能 (トランザクション) をサポートまたは表現します。適切な例として、従業員は 1 つ以上の違反をしている可能性があり、もしそうなら、ある時点でのトランザクションの側面です。ユースケースを検討してください。

シナリオ:「従業員が職場に違反する行為を行った。」これは、発生した一種のビジネス イベント (つまり、トランザクション、またはより大規模な分散トランザクションの一部) です。影響を受けるルート ドメイン オブジェクトは、実際には複数の観点から見ることができるため、混乱を招きます。ただし、ビジネス プロセスで現実世界をできるだけ正確にモデル化する必要があるため、ビジネス トランザクションに関連する動作については覚えておく必要があります。リレーションシップに関しては、リレーショナル データベースの場合と同様に、概念的なドメイン モデルは実際にはすでにこれを示している必要があります (つまり、結合性)。多くの場合、どちらの方向にも読み取ることができます。

従業員 <---- 犯した -------犯した ----> 違反

したがって、このユース ケースでは、これは違反を扱うトランザクションであり、ルート (つまり「プライマリ」エンティティ) は違反であると言えます。それが、その特定のビジネス アクティビティまたはビジネス プロセスで参照する集約ルートになります。しかし、別のアクティビティやプロセスでは、「新しい従業員プロセス」などの Employee 集約ルートを使用できないというわけではありません。注意を払っていれば、循環参照の悪影響や、ドメイン モデルを複数の方法でトラバースできることはありません。ただし、これを管理することは、ビジネス ドメインのコントローラー部分、またはそれに相当するものによって検討および処理する必要があることを警告します。

余談: パターン (つまり MVC) の観点から考えると、リポジトリはビューであり、ドメイン オブジェクトはモデルであるため、何らかの形式のコントローラー パターンも使用する必要があります。通常、コントローラーは、リポジトリー (集約ルートのコレクション) の具体的な実装とアクセスを宣言します。

データアクセスの世界では...

例として LINQ-To-SQL を使用すると、DataContext は Customer および Order エンティティのビューを公開するコントローラーになります。ビューは、非宣言型のフレームワーク指向のテーブル型です (リポジトリとほぼ同等)。ビューはその親コン​​トローラーへの参照を保持し、多くの場合、コントローラーを介してビューが具体化される方法/時期を制御することに注意してください。したがって、コントローラーはプロバイダーであり、マッピング、変換、オブジェクトのハイドレーションなどを処理します。モデルはデータの POCO です。かなり典型的な MVC パターン。

例として N/Hibernate を使用すると、ISession は、session.Enumerable(string query) または session.Get(object id) または session.CreateCriteria(typeof(Customer) を介して Customer および Order エンティティのビューを公開するコントローラーになります。 )。リスト()

ビジネスロジックの世界では...

Customer { /*...*/ }

Employee { /*...*/ }

Repository<T> : IRepository<T>
              , IEnumerable<T>
              //, IQueryable<T>, IQueryProvider //optional

{ /**/ }

BusinessController {
 Repository<Customer>  Customers { get{ /*...*/ }} //aggregate root
 Repository<Order> Orders { get{ /*...*/ }} // aggregate root
}

簡単に言えば、ビジネス プロセスとトランザクションをガイドにして、プロセス/アクティビティが実装またはリファクタリングされるにつれて、ビジネス インフラストラクチャが自然に進化するようにします。さらに、従来のブラック ボックス デザインよりも構成可能性を優先します。サービス指向またはクラウド コンピューティングに到達すると、満足することでしょう。:)

于 2010-05-25T01:17:52.063 に答える
0

結論はどうなるの?と思っていました。

「違反」はルート エンティティになります。また、「違反」は「従業員」ルート エンティティによって参照されます。つまり、違反リポジトリ <-> 従業員リポジトリ

しかし、違反をルートエンティティにすることについて混乱しています。これは、動作がないためです。

しかし、「行動」はルートエンティティとしての資格を得るための基準ですか? 私はそうは思わない。

于 2009-10-15T13:47:02.210 に答える
0

Order...OrderItem の例に戻ると、システム内に分析モジュールがあり、OrderItems を直接調べたい場合があります。つまり、特定の製品のすべての orderItems、またはそれより大きいすべての注文項目を取得します。いくつかの与えられた値など、そのような多くのユースケースがあり、「集約ルート」を極端に駆動すると、OrderItem はそれ自体が異なる集約ルートであると主張できますか??

于 2012-05-22T10:26:31.593 に答える