【发布时间】:2009-10-02 16:53:45
【问题描述】:
或者,基本实体验证是否被视为规范?
一般来说,将基本实体验证(名称不能为空或为空,日期必须大于 xxx)保留在实际实体中还是在规范之外更好?
如果在规范中,那会是什么样子?您会为每个字段制定一个规范,还是将其全部包含在一个 EntityIsValid 类型规范中?
【问题讨论】:
标签: nhibernate domain-driven-design bdd
或者,基本实体验证是否被视为规范?
一般来说,将基本实体验证(名称不能为空或为空,日期必须大于 xxx)保留在实际实体中还是在规范之外更好?
如果在规范中,那会是什么样子?您会为每个字段制定一个规范,还是将其全部包含在一个 EntityIsValid 类型规范中?
【问题讨论】:
标签: nhibernate domain-driven-design bdd
在我看来,一旦人们对 DDD 有所了解,他们就会选择规范模式并希望将其应用到任何地方。这确实是 Golden Hammer 反模式。
我认为规范模式的位置以及我理解 Domain-Driven Design 的方式是,当您需要独立于实体改变业务规则时,您可以选择应用这种设计模式。
请记住,DDD 是一种迭代方法,因此您不必在第一时间就将其“正确”。我将从在实体中进行基本验证开始。这非常符合 OOD 的基本思想,因为它让表示概念的对象知道数据的有效范围。
在大多数情况下,您甚至不需要显式验证,因为应将实体设计为将约束表示为不变量,从而无法创建违反约束的实例。
如果您有一条规定 Name 不能为 null 或为空,您可以直接在您的 Entity 中主动强制执行:
public class MyEntity
{
private string name;
public MyEntity(string name)
{
if(string.IsNullOrEmpty(name))
{
throw new ArgumentException();
}
this.name = name;
}
public string Name
{
get { return this.name; }
set
{
if(string.IsNullOrEmpty(value))
{
throw new ArgumentException();
}
this.name = value;
}
}
}
name 不能为 null 的规则现在是类的不变量:MyEntity 类现在不可能进入违反该规则的状态。
如果稍后您发现规则更复杂,或者在许多不同概念之间共享,您可以随时将其提取到规范中。
【讨论】:
实体同时具有数据和行为,因此让您的实体确保它们的不变量是恕我直言的方法。否则,您可能会得到 anemic domain model [Fowler]。
如果您的上下文允许您按照 Mark Seemann 的建议在 setter 中强制执行规则,那就太好了,因为您的模型中没有所有“IsValid”和/或“BrokenRules”逻辑。
我曾在两种情况下发现自己需要上述解决方案:
经典的响应/请求 Web 解决方案,其中网页在保存失败时显示实体的所有损坏规则。
模型是从外部更新的数据库中读取的(因此,尽管有设置器逻辑,实体也不是不可能无效的,除非您让 ORM 使用设置器,但对我们来说,重点是了解有效性)。
【讨论】: