当前位置:  开发笔记 > 编程语言 > 正文

域驱动设计中的验证

如何解决《域驱动设计中的验证》经验,为你挑选了3个好方法。

您如何处理域驱动设计中复杂聚合的验证?您是否整合了业务规则/验证逻辑?

我理解参数验证.我理解可以附加到模型本身的属性验证,并执行检查电子邮件地址或邮政编码是否有效或者名字具有最小和最大长度等操作.

但是涉及多个模型的复杂验证呢?您通常将这些规则和方法放在您的架构中?你用什么模式来实现它们?



1> Ben Scheirma..:

不要依赖于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


他不只是提倡它,因为听起来不错,他在这种思维模式中拥有非常庞大的系统.
我一直认为你发布的Greg Young的建议在现实世界中并不实用.

2> 小智..:

我喜欢Jimmy Bogard解决这个问题的方法.他在他的博客上发表了一篇名为"访问实体验证和扩展方法"的文章,其中他提出了一种非常优雅的实体验证方法,建议实现一个单独的类来存储验证代码.

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

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

    public IEnumerable 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;
    }
}


但有一件事,不应该是`返回BrokenRules(entity).Count()> 0`这一行真的是`返回BrokenRules(entity).Count()<= 0`?
我只是看了Jimmy的帖子,并且基本上在本地组合了一个快速测试,并且我说我不喜欢这种方法的一件事是如果你使用扩展方法来实现它,就像他的文章中,当消费者键入"实体"时. ",有两种Validate()方法出现.一个坐在实体上实现IValidatable 接口,另一个是扩展方法.我是否正在使用两个.Validate()方法来消耗实体,我可能不知道在没有查看每个方法的情况下调用哪个实体.

3> thinkbeforec..:

我通常使用规范类,它提供了一种方法(这是C#,但你可以用任何语言翻译它):

bool IsVerifiedBy(TEntity candidate)

该方法对候选者及其关系进行全面检查.您可以在规范类中使用参数使其参数化,就像检查级别一样......

您还可以添加方法以了解候选人未验证规范的原因:

IEnumerable BrokenRules(TEntity canditate) 

您可以简单地决定实现第一个方法,如下所示:

bool IsVerifiedBy(TEntity candidate)
{
  return BrokenRules(candidate).IsEmpty();
}

对于破坏的规则,我通常编写一个迭代器:

IEnumerable BrokenRules(TEntity candidate)
{
  if (someComplexCondition)
      yield return "Message describing cleary what is wrong...";
  if (someOtherCondition) 
      yield return
   string.Format("The amount should not be {0} when the state is {1}",
        amount, state);
}

对于本地化,您应该使用资源,以及为什么不将文化传递给BrokenRules方法.我将这些类放在模型命名空间中,其名称建议使用它们.

推荐阅读
凹凸曼00威威_694
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有