5

私は擬似コードで単純なエンティティを持っています: Order

class Order{    
    private int quantity;
    private Date orderDate;
    private Date shippingDate;

    public Order(int quantity, Date orderDate, Date shippingDate){
        if(quantity <= 0){ throw new Exception("Invalid quantity")}
        if(shippingDate < orderDate){ throw new Exception("Invalid shippingDate")}
        if(...more validation...){....throw Exceptions...}

       //assign values if everything is OK
    }
}

description、quantity、orderDate、shippingDate はすべて Web フォームから読み取られます。それぞれが多数のバリデータによって構成されたテキスト フィールドです。

quantityField= new TextField('txt_quantity');
quantityFiled.addNotNullValidator().addNumaricValidator().addPositiveIntegerValidator()

ご覧のとおり、検証ロジックはTextField検証とエンティティ検証の間で重複しています。クラス、クラス、クラス
を作成して、エンティティに値オブジェクトの概念を導入しようとしました。したがって、私のエンティティは代わりに次のようになります。QuantityOrderDateShippingDateOrder

class Order{    
    private Quantity quantity;
    private OrderDate orderDate;
    private ShippingDate shippingDate;

    public Order(Quantity quantity, OrderDate orderDate, ShippingDate shippingDate){
        //assign values without validation I think??!!
    }
}

たとえば、クラス Quantity は次のようになります。

クラス数量{

private int quantity;
public Quantity(int quantity){
        if(quantity <= 0){ throw new Exception("Invalid quantity")}
        this.quantity=quantity;
}

}

今質問:

  1. 集約ルートは、集約全体の検証を担当するものではありませんか? 私のQuantityクラスはそれに違反していませんか?
  2. QuantityWebフォーム検証のコンストラクターで検証を再利用するにはどうすればよいですか? 検証コードが重複していると思うので、一度検証するか、少なくとも検証ロジックを再利用するにはどうすればよいですか。
  3. すべての値オブジェクトはそれ自体を検証するため、エンティティで何も検証してはならないということですか?
  4. ShippingDate検証に依存するためOrderDate、出荷日はどのように検証すればよいですか?
  5. DDD ファクトリーは、これらすべてのどこに当てはまりますか?
4

3 に答える 3

2
  1. 集約ルートは、集約に不変条件を適用することになっていますが、すべての検証を行うわけではありません。特に、一般的にコンストラクターまたはファクトリーで処理される構築時の検証ではありません。実際のところ、できるだけ多くの (コンテキスト固有ではない) 不変式をコンストラクターとファクトリーに移動することは有益です。Aggregate ルートまたはエンティティ自体でandメソッドを繰り返し使用することに依存するよりも、常に有効なエンティティを保持する方がはるかに優れていると思います。ValidateThis()ValidateThat()

  2. 基本的に 3 種類の検証があります。クライアント側の検証、アプリケーションの検証 (コントローラーまたはアプリケーション層サービス)、およびドメインの検証 (ドメイン層) です。クライアント側の検証が必要であり、再利用できません。アプリケーションの検証は、ドメインの検証に依存できます。これは、例では Quantity コンストラクターを呼び出し、それによってスローされた例外を処理することを意味します。passwordただし、アプリケーション固有の非ドメイン ルールの独自のセットを持つこともできます。たとえば、password_confirm.

  3. 常に有効なエンティティ1とほぼ同じ精神で、値オブジェクトは不変にするのが最善です。ただし、これは本質的な検証であり、包含エンティティに周辺の検証を完全に含めることができます (たとえば、list にその種類の値オブジェクトを 3 つ以上含めることはできず値オブジェクト A は常に値オブジェクト B と一緒になるなど)。

  4. これは状況に応じた検証であり、ShippingDate 固有の不変条件の検証ではありません。ShippingDate >= OrderDateしたがって、Order は、これらの各値オブジェクトの有効性とは別に、それをチェックする責任を負う必要があります。

  5. ファクトリは、オブジェクトの構築ロジックが複雑で、それ自体が責任を負うほど複雑であり、SRP のおかげで、オブジェクトのコンストラクタまたはコンシューマに適合しない場合に使用する必要があります。ファクトリには、コンストラクタと同様に、構築時の検証ロジックが含まれているため、一種の不変のエンフォーサにもなります。

于 2013-01-23T13:35:34.007 に答える
2
  1. コンテキストに関係なく、ドメイン内でいずれかQuantityが負になることができない場合、これは完全に理にかなっています
  2. 私見コンストラクターの検証は、アプリケーションによるクラスの正しい使用Quantityを保証するのに役立ちます。例外がスローされます。これらは、予期されるワークフローではなく、例外的な状態を意味します。したがって、ユーザーによるアプリケーションの正しい使用を保証する Web フォームの検証とはまったく異なる目的があります。無効な入力を予期して処理します。少なくとも、単一責任の原則に違反せずに排除できる重複は見られません。
  3. そうではないと思います。値オブジェクト内でこれをif(shippingDate < orderDate)どのように検証する予定でしたか?
  4. ああ、問題がわかります。同じ答え: この検証は Order エンティティに属します。また、すべてに値オブジェクトを使用する必要はありません。注文日または出荷日に固有の制約がない場合は、そのまま使用してDateください。
  5. これは別の質問のようです。値オブジェクトとの関連性はわかりません。
于 2013-01-22T12:49:35.133 に答える
0

これらは多くの質問です、あなたはそれらを単一の質問に分解したいかもしれません。

質問2から5は、さまざまな要因に大きく依存し、意見の対象となります。

しかし、これが質問1(および質問3と4)に対する私の答えです。

骨材はその完全性に責任があります。集約ルートではありません。Aggregateが全体として有効である限り、Aggregate内のすべてのアイテムは独自の検証を行うことができます。

状態の検証(正しい量または負ではない量として)は、それぞれのクラス内で実行できます。相互依存状態の検証はShippingDate >= OrderDate、たとえばAggregateRootなどのより高いレベルで実行できます。

于 2013-01-22T12:51:05.453 に答える