C# 在领域驱动设计的项目中,您将验证放在何处?

C# 在领域驱动设计的项目中,您将验证放在何处?,c#,validation,domain-driven-design,C#,Validation,Domain Driven Design,我应该将域对象的验证逻辑放在解决方案中的何处?我应该把它们放在域类、业务层还是其他层 为此,我还想使用Microsoft企业库中的验证应用程序块和策略注入应用程序块 我应该使用什么样的验证策略将所有这些很好地结合在一起 提前谢谢大家 我通常把它放在域对象中。这是因为域对象是我关心的验证对象,因此如果特定对象的规则发生更改,我知道在哪里更新它,而不必在某个特定验证类/文件中搜索一组不相关的实体规则 我意识到这可能不被视为POCO,但每个项目都有特定的例外,这一点对我来说通常是有意义的。同样,在某些

我应该将域对象的验证逻辑放在解决方案中的何处?我应该把它们放在域类、业务层还是其他层

为此,我还想使用Microsoft企业库中的验证应用程序块和策略注入应用程序块

我应该使用什么样的验证策略将所有这些很好地结合在一起


提前谢谢大家

我通常把它放在域对象中。这是因为域对象是我关心的验证对象,因此如果特定对象的规则发生更改,我知道在哪里更新它,而不必在某个特定验证类/文件中搜索一组不相关的实体规则

我意识到这可能不被视为POCO,但每个项目都有特定的例外,这一点对我来说通常是有意义的。同样,在某些项目中,从视图中引用域实体是有意义的,因此,实现IPropertyChanged,而不是不断地将值从实体复制到一整套其他视图特定对象

我进行验证的旧方法是,我有一个像下面这样的IValidator接口,每个实体都实现了该接口

public interface IValidator
{
   IList<RuleViolation> GetViolations();
}

编辑:我删除了我关于过去不太喜欢企业库的评论,因为Chris告诉我,它现在非常类似于NHibernate验证,您可以根据自己的需要进行任何一种验证

将其放在域类中可以确保始终完成验证,但会使类膨胀。它也可能违反单一责任原则,具体取决于您如何解释(它添加了验证责任)。将其放在域类中也会限制您进行一种验证。此外,除非使用继承,否则同一规则可能必须在相关类中多次实现(DRY)。如果您这样做,验证将在您的域中展开

外部验证(您可以通过DI、工厂、业务层或上下文获得验证对象)确保您可以根据上下文交换验证规则(例如,对于要以部分完成状态保存的长时间运行的进程,可以使用一个验证对象来保存,另一个用于检查域类是否真的有效并准备好使用)。域类将更简单(虽然您必须执行最少的检查,如空检查,以防止运行时错误,但责任更少),并且您还可以重用相关类的规则集。通过这种方式,验证集中在域模型的一小部分。B.t.w.您可以将外部验证注入域类本身,确保类本身进行验证,只是不知道它们正在验证什么


但是,不能对验证应用程序块发表评论。正如你总是要权衡利弊一样,从来没有一个有效的解决方案。

首先,我同意@i8abug

但我确实想进一步讨论架构。每一个设计架构,比如域驱动的,都应该被看作是一个建议,并仔细观察

在每一个步骤中,你都应该问自己,关于你的申请,这个问题的优点和缺点是什么

其中很多都涉及到添加大量代码,并使项目严重复杂化,但效益甚微

验证点就是一个很好的例子。正如Stefan所说,单一责任原则基本上说,你需要创建一整套其他类,其目的是只验证原始对象的状态。显然,这会给应用程序添加很多代码。可能是为你生成的,可能你必须手工编写。Regar如果没有必要,更多的代码通常意味着不那么健壮,当然也意味着更难理解

分离所有这些的好处是,您可以交换验证规则。好吧,好吧。缺点是,您现在有两个文件要查看并为每个类定义创建。即:更多工作。您的应用程序需要交换验证规则吗?可能不需要。我甚至敢打赌,很少有人会这样做

坦白地说,如果你沿着这条路走下去,那么你可以把所有的东西都定义为一个结构,让所有那些“助手”类爬回去处理验证、持久性、设置属性等等,因为作为一个成熟的类,你几乎什么都买不到

综上所述,我倾向于自包含类。换句话说,它们知道它们的属性如何相互关联,知道什么是可接受的值。它们还可以对自己和它们的孩子执行操作。换句话说,它们知道它们是什么。这倾向于简化编码和实现。这也导致我在这里真正做的唯一区别是实现持久性的控制反转;它允许我在运行时交换数据提供程序;这是我已经做过的几个应用程序的要求


关键是,仔细考虑你在做什么,并决定在你的特定情况下这是否是最好的方式。所有这些编程“规则”毕竟只是建议。

这取决于情况。首先,你需要了解你在验证什么

您可以验证:

  • 从Http post检索的值可以解析为日期时间
  • 客户名称不超过100个符号
  • 那个顾客有足够的钱买东西
  • 正如您所见,这些验证在本质上是不同的,因此它们的重要性是不同的(请参阅“并非所有规则都是平等创建的”一段)


    您可能要考虑的是域对象处于无效状态。

    这将大大降低复杂性,因为
    //I can't remember the exact syntax but it is very similar to this
    public class MyEntity
    {
    
    [NHibernateValidation(Length(min=1, max=10)]
    public String Name {get;set;}
    
    }
    
    //... and then later ...
    NHibernateValidator.Validate(myEntity);