15

かなり複雑なシナリオを処理するための最良の方法を見つけるのに少し苦労しています。私はかなりの数の同様の質問を見てきましたが、満足のいくようにこのシナリオに対処したものはありませんでした。

Order(集約ルート)は、複数のOrderLine(子エンティティ)で作成されます。ビジネスルールに従って、各OrderLineは、注文の存続期間中、同じIDを維持する必要があります。OrderLineには多くの(20以上の)プロパティがあり、Orderが「ロックされている」と見なされる前にかなり頻繁に変更できます。さらに、ルートレベルで適用する必要のある不変条件があります。たとえば、各注文明細には数量があり、注文の合計数量はXを超えることはできません。

OrderLinesの変更を検討する際に、このシナリオをモデル化する方法がわかりません。私には4つの選択肢がありますが、どれも満足のいくものではないようです。

1)OrderLineを変更するときは、ルートから提供された参照を使用して変更します。しかし、ルートの不変ロジックをチェックする機能が失われます。

var orderLine = order.GetOrderLine(id);
orderLine.Quantity = 6;

2)注文のメソッドを呼び出します。すべての不変ロジックを適用できますが、OrderLineの多くのプロパティを変更するためのメソッドの急増に悩まされています。

order.UpdateOrderLineQuantity(id, 6);
order.UpdateOrderLineDescription(id, description);
order.UpdateOrderLineProduct(id, product);
...

3)OrderLineを値オブジェクトとして扱った方が簡単かもしれませんが、ビジネス要件ごとに同じIDを維持する必要があります。

4)不変条件に影響を与えない変更については、OrderLinesへの参照を取得し、影響を与える変更についてはOrderを調べることができます。しかし、不変条件がほとんどのOrderLineプロパティの影響を受ける場合はどうなるでしょうか。不変条件に影響を与える可能性のあるプロパティはごくわずかであるため、この異論は仮説ですが、ビジネスロジックが明らかになるにつれて、状況は変化する可能性があります。

任意の提案をいただければ幸いです...私が密集している場合は、遠慮なくお知らせください。

4

6 に答える 6

7
  1. ドメイン不変を破ることができるため、最適ではありません。

  2. コードの重複と不要なメソッドの爆発的な増加につながります。

  3. 1)と同じです。値オブジェクトを使用しても、ドメイン不変を維持するのに役立ちません。

  4. このオプションは私が行くものです。また、それらが実現するまで、潜在的で仮想的な変化について心配することはありません。設計はドメインを理解することで進化し、後でいつでもリファクタリングできます。発生しない可能性のある将来の変更のために、既存の設計を妨げることには実際には価値がありません。

于 2012-05-23T23:17:03.987 に答える
7

2 に対する 4 の欠点の 1 つは、一貫性の欠如です。場合によっては、注文品目の更新に関してある程度の一貫性を維持することが有益な場合があります。特定の更新が注文を介して行われ、他の更新が注文品目を介して行われる理由は、すぐには明確にならない場合があります。さらに、注文明細行に 20 以上のプロパティがある場合、おそらく、それらのプロパティがグループ化されて注文明細行のプロパティが少なくなる可能性があることを示しています。全体として、アプローチ 2 または 4 は、操作をアトミックで一貫性があり、ユビキタス言語に対応していることを確認する限り問題ありません。

于 2012-05-24T02:10:54.170 に答える
5

ドメイン イベントは、最も堅牢なソリューションです。

ただし、それがやり過ぎの場合は、パラメーター オブジェクト パターンを使用して #2 のバリエーションを実行することもできます。つまり、エンティティ ルートに単一の ModfiyOrderItem 関数を配置します。新しい更新された注文項目を送信すると、内部で注文がこの新しいオブジェクトを検証し、更新を行います。

したがって、典型的なワークフローは次のようになります

var orderItemToModify = order.GetOrderItem(id);
orderItemToModify.Quantity = newQuant;

var result = order.ModifyOrderItem(orderItemToModfiy);
if(result == SUCCESS)
{
  //good
 }
else
{
   var reason = result.Message; etc
}

ここでの主な欠点は、プログラマーがアイテムを変更できるが、それをコミットせず、それに気付かないことです。ただし、拡張性とテスト性は容易です。

于 2013-02-14T17:47:48.370 に答える
5

これを行う 5 番目の方法があります。ドメイン イベントを発生させることができます(例: QuantityUpdatedEvent(order, product, amount))。オーダーラインのリストを調べて、集約に内部的に処理させ、一致する製品を選択し、その数量を更新します (または、OrderLineさらに優れた操作に委任します)。

于 2012-07-31T10:22:13.813 に答える
2

プロジェクトが小規模で、ドメイン イベントの複雑さを避けたい場合は、別のオプションがあります。Order のルールを処理するサービスを作成し、それを OrderLine のメソッドに渡します。

public void UpdateQuantity(int quantity, IOrderValidator orderValidator)
{
    if(orderValidator.CanUpdateQuantity(this, quantity))
        Quantity = quantity;
}

CanUpdateQuantity は、現在の OrderLine と新しい数量を引数として受け取ります。注文を検索し、更新によって合計注文数量に違反が発生するかどうかを判断する必要があります。(更新違反の処理方法を決定する必要があります。)

これは、プロジェクトが小規模で、複雑なドメイン イベントが必要ない場合に適したソリューションです。

この手法の欠点は、Order の検証サービスを OrderLine に渡すことです。対照的に、ドメイン イベントを発生させると、Order ロジックが OrderLine の外に移動します。その後、OrderLine は世界に向けて「やあ、数量を変更します」と言うことができます。注文検証ロジックはハンドラーで実行できます。

于 2015-02-26T21:41:17.397 に答える