业务对象或实体应该自我验证吗?

时间:2010-03-02 00:10:26

标签: c# validation domain-driven-design

Business Objects的验证是一个常见问题,但有一些解决方案可以解决这个问题。

其中一个解决方案是使用独立的NHibernate.Validator框架,这是一个基于属性的验证框架。

但我正面临着概念上的担忧。像NH.Validator这样的属性验证器很棒,但只有在Session中的save-update-delete时才会执行验证。

所以我想知道业务对象是否不应该自我验证以保持自己的完整性和一致性?

3 个答案:

答案 0 :(得分:10)

恕我直言 - 业务对象(BO)/实体有效需要2个验证步骤:

第1步:BO /实体自我验证 - 在此,我们只检查实体在其状态F中是否有效。例如:如果设置了邮政编码,那么它是否具有有效字符&具有有效长度等,形成BO /实体级别验证。但超出此验证级别,我们无法说明BO / Entity在您的业务域和/或存储库中是有效的。 通常,BO / Entity可以强制执行此级别的验证。

第2步:上下文验证 - 在此,我们需要验证BO / Entity是否在其持久存储的存储库的上下文中是有效的。 F.Ex。:邮政编码是否适用于下订单/发送订单的国家/地区等。 对于此验证,可能需要涉及当前上下文中的一些或所有实体,以确保BO / Entity有效。

因此,为了使实体保持纯净,您需要将验证分成这两个步骤 - 一个由实体本身执行。第二个是由持久化/与实体合作的存储库。

HTH。

答案 1 :(得分:6)

尽管如此,他们并不总是可以进行自我验证。如果您输入“无效”邮政编码怎么办?您可以验证邮政编码需要采用特定格式,但如果您希望它们“有效”,即“现有并匹配城市”,该怎么办?或者,如果您只接受来自特定区号的电话号码,并且有效代码列表位于法律部门维护的数据库中,该怎么办?

如果您可以执行语义验证,那就太棒了,可以进入商务舱。但通常情况下,您可能需要额外的验证,这些验证根本无法由业务类本身处理,但需要由与数据库和其他外部服务进行通信的类来处理。

答案 2 :(得分:2)

我不知道我们是否在谈论同样的想法,但如果我们是,我喜欢你的解释。很快,我会解释我为解决这个问题所做的工作。在我的例子中,我的域层中的所有bussines对象必须覆盖两个方法:

显然,为了保持这一点,我有更多的课程牵连,但我不会写在这里,因为我只是试图解释这个概念

List<ValidationRule> notPassedValidationRules = new List<ValidationRule>();

//...

public override void ValidateErrorsWhenSaving(Validator validator)
{
    //...
}

public override void ValidateErrorsWhenDelete(Validator validator)
{
   //...
}        

在这些方法中,我检查了一些布尔条件,保留了一组未通过的规则。在我的情况下,在我的Unit Of Work提交更改(插入新实体,更新,删除)之前调用这些方法,并在提交之前向用户显示可能的错误。