【问题标题】:Nested Validation嵌套验证
【发布时间】:2012-09-07 10:17:13
【问题描述】:

我想知道最好的验证方法是什么。

如果我有一个由基元、关联和其他自定义对象的集合组成的复杂对象对象,IsValid() 方法是否应该验证子对象以及根对象的所需字段/键?

如果是,这应该在某种抽象类中,还是最好使用接口?对于抽象,我需要将我的子对象接口转换为它们的具体类定义才能使用抽象方法,而对于接口验证,我相信我可以让我的子对象作为接口,因为我称之为他们的验证方法。

另外,我使用的不是 MVC,而是带有 Web 表单的 MVP(并尝试使用 DDD 原则)。

谢谢。

更新

我有一个 ScheduledMeeting 的聚合根:

class ScheduledMeeting : BaseValidation
{
     ScheduledMeetingID {get;set;}
     ITimeSlot TimeSlot {get;set;}
     IList<IMeetingAssignee> Assignees{get;set;}
     DateTime meetingDate {get;set;}

     AssignEmployees(IList<IEmployees> employees){}
}

目前有一个BaseValidation抽象类,类似如下:

 public bool isValid(bool validateKeys)
    {
        if (validateKeys)
        {
            ValidateRequiredFields();
            ValidateKeys();
        }
        else
        {
            ValidateRequiredFields();
        }
        return true;
    }  

其中 ValidateRequiredFields() 和 ValidateKeys() 在实现对象时被覆盖。

如果我要使用上述方法并级联到 IMeetingAssigned,我需要在 ScheduledMeeting 中同时循环 ValidateKeys() 和 ValidateRequiredKeys(),将 IMeetingAssigned 转换为具体的 MeetingAssigned,然后再调用 ValidateKeys() 或 ValidateRequiredKeys()这个对象(因为它也将实现 BaseValidation)等等,一直向下。

更新 2

我被 .NET 3.5 困住,因此无法实现代码合同等(据我所知)。

【问题讨论】:

    标签: c# validation domain-driven-design


    【解决方案1】:

    首先不要让您的对象进入无效状态,为您省去很多“IsValid”的麻烦。

    【讨论】:

    【解决方案2】:

    由于您使用领域驱动设计,我假设您已将您的类识别和建模为聚合

    回答您的问题:是的,聚合根 负责确保其自身及其所包含的所有内容在任何给定时间点都有效。聚合根永远不应处于无效状态。

    来自 cmets 的更新:摆脱您的验证界面。聚合从一开始就不应该处于无效状态。每当您的 AR 状态即将改变时,请确保生成的状态不会破坏任何不变量。如果可以,AR 应该拒绝修改。

    强制执行不变量,事后不验证。

    【讨论】:

    • 嗨 - 是的。我有一个聚合根(=>ScheduledMeeting,它有:TimeSlot 值对象,以及 List 和其他原语字段。这是否意味着(聚合根的)子对象不应该关注验证全部?
    • 从外部的角度来看,聚合根最终负责确保随时处于有效状态。当然,在内部它可以将验证委托给它的部件或外部服务。但是,前提应该始终是:尽可能简单。
    • 那么在这种情况下,首选的方法是什么?据我所知,使用抽象类意味着您需要了解子类的具体实现才能调用抽象是有效的方法。接口绕过了对具体铸造的这种需求,但没有共享行为。我不确定拥有一个其方法由抽象类实现的 Ivalidation 接口是否是不好的做法 -> 这意味着我将使用抽象和接口的组合,两者在一定程度上耦合。
    • 摆脱你的验证界面。聚合从一开始就不应该处于无效状态。每当您的 AR 状态即将改变时,请确保生成的状态不会破坏任何不变量。如果可以,AR 应该拒绝修改。
    • 但这不只是在调用 IsValid 或 CheckInvariants 时发生的变化吗?换句话说,我尝试将员工分配给 ScheduledVisit,此时 ScheduledVisit 对象将需要调用 CheckInvariants,并向下级联。所以这与我们已经在尝试解决的情况相同,不是吗? (除非我误解了)。
    猜你喜欢
    • 1970-01-01
    • 2012-01-09
    • 2016-09-17
    • 2012-12-12
    • 2011-05-12
    • 2018-06-18
    • 1970-01-01
    • 1970-01-01
    • 2021-09-06
    相关资源
    最近更新 更多