短縮版
DDDの理論的根拠は、ドメインオブジェクトが機能的なドメイン要件を満たす必要がある抽象化であることです。ドメインオブジェクトがそれらの要件を簡単に満たせない場合は、間違った抽象化を使用している可能性があります。
エンティティ名詞を使用してドメインオブジェクトに名前を付けると、それらのオブジェクトが互いに密結合し、肥大化した「神」オブジェクトになる可能性があります。また、「質問の正しい場所はどこにあるか」などの問題を投げかける可能性があります。 CreateOrderメソッド?」
「正しい」集約ルートを特定しやすくするには、ドメインオブジェクトが機能的な高レベルのビジネス要件に基づいている別のアプローチを検討してください。つまり、システムのユーザーが必要とする機能要件や動作を示唆する名詞を選択します。実行します。
ロングバージョン
DDDはOO設計へのアプローチであり、システムのビジネスレイヤーにドメインオブジェクトのグラフを表示することを目的としています。ドメインオブジェクトは、高レベルのビジネス要件を満たし、理想的にはデータレイヤーに依存できる必要があります。基礎となる永続データストアのパフォーマンスや整合性などのために。
それを見る別の方法は、このリストの箇条書きである可能性があります
- エンティティ名詞は通常、データ属性を提案します。
- ドメイン名詞は振る舞いを示唆すべき
- DDDとOOモデリングは、機能要件とコアドメイン/ビジネスロジックに基づく抽象化に関係しています。
- ビジネスロジックレイヤーは、高レベルのドメイン要件を満たす責任があります。
DDDに関する一般的な誤解の1つは、ドメインオブジェクトは物理的な現実世界の「もの」(つまり、あらゆる種類のデータ/プロパティに起因する、現実世界で指すことができる名詞)に基づく必要があるということですが、データこれらの現実世界の/属性は、機能要件を特定しようとするときに、必ずしも良い出発点とはなりません。
もちろん、ビジネスロジックはこのデータを使用する必要がありますが、ドメインオブジェクト自体は、最終的には機能的なドメインの要件と動作を表す抽象化である必要があります。
例えば; 以下のような名詞Order
やはCustomer
どんな行動を意味し、したがって、一般的なビジネスロジックを表現するために役に立たない抽象化され、ドメインオブジェクトはありません。
ビジネスロジックの表現に役立つ可能性のある抽象化の種類を探すときは、システムが満たすことが期待される一般的な要件を考慮してください。
- 販売担当者として、販売する製品の価格と数量を記載した請求書を作成できるように、新しい顧客の注文を作成します。
- カスタマーサービスアドバイザーとして、保留中の注文をキャンセルして、倉庫オペレーターが注文を処理できないようにしたいと考えています。
- カスタマーサービスアドバイザーとして、製品を在庫に調整し、顧客の元の支払い方法で支払いを返金できるように、注文明細を返却したいと考えています。
- 倉庫オペレーターとして、保留中のすべての商品と配送情報を表示して、商品を選択してクーリエ経由で発送できるようにしたいと考えています。
- 等
DDDアプローチによるドメイン要件のモデリング
上記のリストに基づいて、そのような注文システムのいくつかの潜在的なドメインオブジェクトを検討してください。
SalesOrderCheckout
PendingOrdersStream
WarehouseOrderDespatcher
OrderRefundProcessor
これらはドメインオブジェクトとして、さまざまな動作ドメイン要件の所有権を持つ抽象化を表します。実際、彼らの名詞は、彼らが果たす特定の機能要件を強く示唆しています。
(EventMediator
新しい注文が作成されたとき、または注文が出荷されたときなどを知りたいオブザーバーに通知を渡すなど、追加のインフラストラクチャもある可能性があります)。
たとえば、SalesOrderCheckout
おそらく顧客、配送、製品に関するデータを処理する必要がありますが、注文の配送、保留中の注文の並べ替え、または払い戻しの発行の動作には関係ありません。
のSalesOrderCheckout
ドメイン要件を満たすためには、顧客が多すぎるアイテムを注文することを防ぎ、おそらく検証を実行し、おそらくシステムの他の部分の通知を上げるなどのビジネスルールを適用することが含まれます。他のオブジェクトの。
エンティティ名詞を使用してドメインオブジェクトを表すDDD
このような単純な名詞治療の潜在的な危険がいくつかありOrder
、Customer
そしてProduct
ドメインオブジェクトとしては、それらの問題の中には、あなたが質問で暗示するものがあります:
- この方法は、処理する場合
Order
、Customer
およびProduct
それが属しているドメインオブジェクトを、?
- これら3つのオブジェクトの集約ルートはどこにありますか?
ドメインオブジェクトを表すためにエンティティ名詞を選択すると、次のようなことが起こります。
Order
、Customer
およびProduct
「神」のオブジェクトに成長するリスクがある
Manager
すべてを結びつけるために単一の神オブジェクトで終わるリスク。
- これらのオブジェクトは相互に密結合するリスクがあります-
this
(またはself
)を渡さずにドメイン要件を満たすのは難しい場合があります
- 「リークの多い」抽象化を開発するリスク-つまり、ドメインオブジェクトはカプセル化を弱める数十の
get
/ set
メソッドを公開することが期待されています(そうでない場合、他のプログラマーが後で説明するでしょう)。
- ビジネスデータ(UIを介したユーザーデータ入力など)と一時的な状態(注文が変更されたときのユーザーアクションの「履歴」など)の複雑な混合により、ドメインオブジェクトが肥大化するリスク。
DDD、OOデザイン、プレーンモデル
DDDとOOデザインに関する一般的な誤解は、「プレーン」モデルはどういうわけか「不良」または「アンチパターン」であるということです。マーティンファウラーは貧血ドメインモデルについての記事を書いていますが、彼がその記事で明らかにしているように、DDD自体はレイヤー間のクリーンな分離のアプローチに「矛盾」すべきではありません
「ドメインオブジェクトに動作を組み込むことは、永続化やプレゼンテーションの責任などからドメインロジックを分離するためにレイヤーを使用するという確固たるアプローチと矛盾しないことを強調する価値もあります。ドメインオブジェクトにあるべきロジックは、ドメインロジック-検証、計算です。 、ビジネスルール-あなたがそれをなんと呼んでもいい」
つまり、プレーンモデルを使用して他のレイヤー間で転送されるビジネスデータ(たとえば、ユーザーが新しい注文を作成したいときにユーザーアプリケーションから渡される注文モデル)を保持することは、「貧血ドメインモデル」と同じではありません。「プレーン」データモデルは、多くの場合、データを追跡し、レイヤー間でデータを転送するための最良の方法です(REST Webサービス、永続ストア、アプリケーションまたはUIなど)。
ビジネスロジックはこれらのモデルのデータを処理し、ビジネス状態の一部として追跡できますが、必ずしもこれらのモデルの所有権を取得するわけではありません。
集計ルート
ドメインは、オブジェクトの例を再び見ると- 、SalesOrderCheckout
、、PendingOrdersStream
明らかな集約ルートはまだありません。しかし、これらのドメインオブジェクトには、重複していないように見える非常に個別の責任があるため、実際には問題になりません。 WarehouseOrderDespatcher
OrderRefundProcessor
機能的には、データベースに新しい注文を追加したときに前者のジョブが完了SalesOrderCheckout
するPendingOrdersStream
ので、がと対話する必要はありません。一方、PendingOrdersStream
はデータベースから新しい注文を取得できます。これらのオブジェクトは実際には相互に直接対話する必要はありません(おそらく、イベントメディエーターが2つのオブジェクト間で通知を提供する可能性がありますが、これらのオブジェクト間の結合は非常に緩やかであると予想します)。
おそらく、Aggregate Rootは、IoCコンテナになり、これらのドメインオブジェクトの1つ以上をUIコントローラに挿入し、EventMediator
やなどの他のインフラストラクチャも提供しRepository
ます。あるいは、ビジネス層の上にある一種の軽量のオーケストレータサービスになるかもしれません。
集約ルートは必ずしもドメインオブジェクトである必要はありません。ドメインオブジェクト間で懸念の分離を維持するために、集約ルートがビジネスロジックを持たない別のオブジェクトである場合は、一般的に良い方法です。