总结一下领域模型的验证(附代码下载)

  一:什么是领域模型(Domain Model)

         1,Entities

         2,Value Objects

         3,Relations

  二:只谈验证(Validation)——三种常见的做法

         1,Constructor/Method based Validation

         2,Validate() Method

         3,Validation Services

         4,Validation Configuration

  一:什么是领域模型(Domain Model)

  我们可以在概念层次认为Domain Model就是在大的领域边界中的,可以用基于离散的思想来限定出的,承载“数据”和“关系”的小边界(个人给的定义,仅供参考)。定义中蕴含着这样一层意思:所谓模型乃是我们限定出的用于解决问题的承载着“数据”与“关系”的“问题边界”,也就是Model不一定跟现实中的真实物理对象一一对应,虽然大都一一对应。领域大边界由Model小边界来明确,Model小边界需要由领域大边界来给限定出问题的范围(因为宇宙是无穷的开放的,除了那个终极规律外的任何规律都是有适用范围的,不限定出范围就会寸步难行,无法认识任何问题了)。

  领域模型承载的数据可以分为两个类别:Entities和Value Objects。Model中的数据依照一定“规则”模拟出一个有机的问题模型,这个“规则”约等于Relations。

  1, Entity是这样的数据,在它的生命周期中需要一个标识(Identity)。在Domain Model中(注意这里的Model是在一个限定的领域中的)如果某条数据脱离了这个标识就没有了意义的话,那么这样的数据就是该Domain Model的Entities类别的数据了。比如在cnblogs的系统中,每一个BlogSite都有一个BlogTitle,但是这个BlogTitle是可以修改的,当我修改了我的BlogSite的BlogTile后我却依然能够通过“www.cnblogs.com/xuefly”访问到,这里可以说“www.cnblogs.com/xuefly”就是我的blog的标识了。如果没有这个标识存在的话,那么BlogTitle在空间中的存在也就没有了意义(当BlogTitle与BlogSite脱离后BlogTitle就变成了“字符串”,而在Blog领域中“字符串”是没有意义的)。像BlogTitle这样的数据就是属于BlogSite模型的的Entitys类别的数据,我们把这样的数据交给BlogSite来验证的话是合理的。比如当我们修改自己的BlogSite的BlogTile中包含敏感的非法字符时或者长度超过了一定限度时,修改就不会保存成功,这里的验证就该是由BlogSite本身来完成的。

  2, Value Objects是这样的数据:它的存在不需要标识。存在就是要有意义,还是在cnblogs的系统中,每个BlogSite都会有博主(BlogOwner),因为我们的BlogSite是单用户的所以在BlogSite中应该会有一个BlogUser:Person类型的属性,我们假设这个属性被命名为BlogOwner。

  BlogOwner是一个BlogUser类型的对象,BlogUser类型对象的存在不依赖于BlogSite的存在,也就是即使没有BlogSite的话这个被指向了BlogSite.BlogOwner的BlogUser类型的对象依然有存在的意义(是否可以这样理解,BlogUser是一个Person,而Person在Blog领域中是具有意义的)。这里的BlogOwner就可以归为BlogSite的Value Object类别的数据了。我们看到BlogSite有一个ID标识,这个ID标识是提供给BlogTitle这样的BlogSite的Entitys类别的数据的,并不是提供给BlogOwner的。再进一步说明就是:在一个BlogSite类型的对象blogSite1中,blogSite1的BlogOwner属性值原来指向user1,而现在我们把blogSite1.BlogOwner指向null,这时user1失去了与blogSite1的联系,然而user1却在整个Blog领域中依旧具有实际的意义,因为在Blog领域中必须有用户这个概念(BlogUser Class),user1是一个用户,user1在blog领域中依旧有意义。而BlogTitle就不同了(blogSite1.BlogTitle = blogTitle1),如果我们把blogSite1.BlogTitle指向null的话,BlogTitle1同样与blogSite1脱离了关系,这个时候blogTitle1由“博客标题”变成了“字符串”,blogTitle1是个字符串,它在Blog领域中没有意义。BlogOwner属于BlogSite的Value Objects类别的数据,BlogOwner的数据应交由BlogUser模型来验证,不应由BlogSite模型来验证。与BlogSite一样BlogUser.Name,BlogUser.LoginID,BlogUser.Password属于BlogUser模型的Entitys类别的数据。

  3,关系(Relations)

  ……

  二,只谈验证(Domain Model Validation)

  业务规则要求我们的Domain Model必须满足某些约束,比如BlogSite的BlogTitle的长度不能大于等于255个字符等,这就是业务规则。如果说对BlogTitle的长度进行约束貌似还有点不怎么说的通的话,那么在Blog领域中业务规则要求BlogUser类型的对象的Age属性不能小于等于零就是无可厚非的了。正是这些被约束的数据组成了Domain Model,通过这些约束,低级的数据(基本数据类型)被我们组织成了更高一级的复杂类型的数据——Domain Model Class,然后领域中的所有Domain Model交织起来最终又诠释了整个领域。我们认为:没有边界的宇宙中的每一个概念都是被约束出来的,无论是“领域”还是领域中的“模型”,终极都是由规则约束出来的具有边界的问题模型。如果没有了约束就没有了Model没有了Domain,一切可以认识的东西都没有了,只剩下了一个开放的没有边界的宇宙了。可见“规则”(Rule)是多么的重要,而执行规则就需要“验证”(Validation)。

  1, 基于构造的验证

  将验证放在构造对象的时候,比如构造函数中或者放在属性中。在这种情况下,当验证失败的时候我们一般直接抛出异常,比如抛出自定义的ValidationException异常,将错误信息放在自定义异常中。

public class Person : Entity
{
private string _name;
private DateTime _birthday;

public string Name
{
get
{
return _name;
}
set
{
if (value.IsNullOrEmpty())
{
throw new IsNullOrEmptyException("名称不能为空");
}
_name
= value;
}
}

public DateTime Birthday
{
get
{
return _birthday;
}
set
{
if (value >= DateTime.Now || DateTime.Now.AddYears(-120) > value)
{
throw new ValidationException("出生日期不在有效的范围内");
}
_birthday
= value;
}
}
}

it知识库总结一下领域模型的验证(附代码下载),转载需保留来源!

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。