或者,基本实体验证是否被视为规范?
一般来说,将基本实体验证(名称不能为空或空,日期必须大于 xxx)保留在实际实体中还是在规范之外更好?
如果在规范中,那会是什么样子?您是否会对每个字段都有一个规范,或者将其全部包含在一个 EntityIsValid 类型规范中?
或者,基本实体验证是否被视为规范?
一般来说,将基本实体验证(名称不能为空或空,日期必须大于 xxx)保留在实际实体中还是在规范之外更好?
如果在规范中,那会是什么样子?您是否会对每个字段都有一个规范,或者将其全部包含在一个 EntityIsValid 类型规范中?
在我看来,一旦人们对 DDD 有所了解,他们就会选择规范模式并希望将其应用到任何地方。那真的是金锤反模式。
我对规范模式的看法以及我理解领域驱动设计的方式是,当您需要独立于实体改变业务规则时,您可以选择应用这种设计模式。
请记住,DDD 是一种迭代方法,因此您不必在第一时间就将其“正确”。我将从在实体中进行基本验证开始。这与 OOD 的基本思想非常吻合,因为它让表示概念的对象知道数据的有效范围。
在大多数情况下,您甚至不需要显式验证,因为应该设计实体以便将约束表示为不变量,从而无法创建违反约束的实例。
如果您有一条规则说 Name 不能为 null 或为空,您可以直接在您的实体中主动执行它:
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 类现在不可能进入该规则被破坏的状态。
如果稍后您发现规则更复杂,或者在许多不同的概念之间共享,您总是可以将其提取到规范中。
实体既有数据又有行为,因此让您的实体确保它们的不变量是恕我直言的方法。否则,您最终可能会得到一个贫乏的域模型[Fowler]。
如果您的上下文允许您按照 Mark Seemann 的建议在设置器中强制执行规则,那将是很好的,因为您的模型中没有所有“IsValid”和/或“BrokenRules”逻辑。
我曾在两种情况下发现自己需要上述解决方案:
经典的响应/请求 Web 解决方案,其中网页在保存失败时显示实体的所有损坏规则。
该模型是从外部更新的数据库中读取的(因此,尽管有设置器逻辑,实体也不是不可能无效的,除非您让 ORM 使用设置器,但我们的重点是找出有效性) .