65

ドメイン駆動設計の複雑な集合体の検証にどのように対処しますか?ビジネスルール/検証ロジックを統合していますか?

私は引数の検証を理解し、モデル自体に添付できるプロパティの検証を理解し、メールアドレスまたは郵便番号が有効であること、または名の長さが最小および最大であることを確認するなどのことを行います。

しかし、複数のモデルを含む複雑な検証についてはどうでしょうか。通常、これらのルールとメソッドをアーキテクチャ内のどこに配置しますか?そして、それらを実装するために使用するパターンはありますか?

4

5 に答える 5

65

アプリケーション全体で呼び出しに頼る代わりにIsValid(xx)、Greg Young からのアドバイスを受けることを検討してください。

エンティティを無効な状態にしないでください。

これが基本的に意味することは、エンティティを純粋なデータ コンテナーとして考えることから、動作を伴うオブジェクトについて考えることに移行することです。

個人の住所の例を考えてみましょう。

 person.Address = "123 my street";
 person.City = "Houston";
 person.State = "TX";
 person.Zip = 12345;

これらの呼び出しの間では、エンティティは無効です (互いに一致しないプロパティがあるためです。次のことを考慮してください。

person.ChangeAddress(.......); 

アドレスを変更する動作に関連する呼び出しはすべて、アトミック ユニットになりました。ここでエンティティが無効になることはありません。

状態ではなく動作をモデル化するというこの考え方を採用すると、無効なエンティティを許可しないモデルに到達できます。

これに関する良い議論については、次の infoq インタビューをチェックしてください: http://www.infoq.com/interviews/greg-young-ddd

于 2009-02-06T22:29:04.033 に答える
39

この問題に対する Jimmy Bogard の解決策が気に入っています。彼はブログに「訪問者と拡張メソッドを使用したエンティティ検証」というタイトルの記事を投稿しており、検証コードを格納する別のクラスの実装を提案するエンティティ検証への非常に洗練されたアプローチを提示しています。

public interface IValidator<T>
{
    bool IsValid(T entity);
    IEnumerable<string> BrokenRules(T entity);
}

public class OrderPersistenceValidator : IValidator<Order>
{
    public bool IsValid(Order entity)
    {
        return BrokenRules(entity).Count() == 0;
    }

    public IEnumerable<string> BrokenRules(Order entity)
    {
        if (entity.Id < 0)
            yield return "Id cannot be less than 0.";

        if (string.IsNullOrEmpty(entity.Customer))
            yield return "Must include a customer.";

        yield break;
    }
}
于 2009-06-13T13:28:05.370 に答える