シナリオ:
顧客が注文し、製品を受け取った後、注文プロセスに関するフィードバックを提供します。
次の集計ルートを想定します。
- お客様
- 注文
- フィードバック
ビジネスルールは次のとおりです。
- 顧客は自分の注文についてのみフィードバックを提供でき、他の人のフィードバックは提供できません。
顧客は、注文に対する支払いが済んでいる場合にのみフィードバックを提供できます。
class Feedback { public function __construct($feedbackId, Customer $customer, Order $order, $content) { if ($customer->customerId() != $order->customerId()) { // Error } if (!$order->isPaid()) { // Error } $this->feedbackId = $feedbackId; $this->customerId = $customerId; $this->orderId = $orderId; $this->content = $content; } }
ここで、企業が新しいルールを望んでいると想定します。
顧客
Supplierは、注文の商品がまだ稼働している場合にのみフィードバックを提供できます。class Feedback { public function __construct($feedbackId, Customer $customer, Order $order, Supplier $supplier, $content) { if ($customer->customerId() != $order->customerId()) { // Error } if (!$order->isPaid()) { // Error } // NEW RULE HERE if (!$supplier->isOperating()) { // Error } $this->feedbackId = $feedbackId; $this->customerId = $customerId; $this->orderId = $orderId; $this->content = $content; } }
最初の2つのルールの実装をFeedback
集約自体の中に配置しました。特に、Feedback集合体が他のすべての集合体をIDで参照しているので、これを行うのは快適
です。たとえば、Feedbackコンポーネントのプロパティは、他の集約の存在を知っていることを示している
ので、これらの集約の読み取り専用の状態も知っておくと安心です。
ただし、そのプロパティに基づいて、Feedbackアグリゲートはアグリゲートの存在を認識していないSupplierため、このアグリゲートの読み取り専用の状態を認識して
いる必要がありますか?
ルール3を実装する別のソリューションは、このロジックを適切なに移動することCommandHandlerです。しかし、これはドメインロジックを私のオニオンベースのアーキテクチャの「中心」から遠ざけているように感じます。
Supplierアグリゲートの動作状態は、Orderリポジトリを介して照会されません。SupplierおよびOrder2つの別個の集合体です。次に、DDD / CQRSメーリングリストで、集約ルートとリポジトリを他の集約ルートメソッド(コンストラクタを含む)に渡すことについて質問がありました。さまざまな意見がありましたが、グレッグヤングは、集約ルートをパラメーターとして渡すことは一般的であると述べましたが、別の人は、リポジトリーはドメインよりもインフラストラクチャーに密接に関連していると述べました。たとえば、リポジトリは「メモリコレクションで抽象化」され、ロジックがありません。
Customerが自分の注文の1つにのみフィードバックを提供できるように($order->customerId() == $customer->customerId())、サプライヤーID($order->supplierId() == $supplier->supplierId())も比較する必要があります。最初のルールは、ユーザーが誤った値を入力するのを防ぎます。2番目のルールは、プログラマーが誤った値を指定しないようにします。それにもかかわらず、サプライヤが動作しているかどうかのチェックは、Feedbackエンティティまたはコマンドハンドラのいずれかで行う必要があります。質問はどこですか。
