比如说,我喜欢为大学的结构建模。大学有一些系(系),每个系都有一些课程。有一条规则是,每个部门都必须是独一无二的,因此其中的每个班级都必须是独一无二的。例如,类的名称需要是唯一的。
真的吗?为什么?该规则的商业价值是什么?如果碰巧有两个同名的班级,企业(大学)的成本是多少。这是否意味着所有时间都使用相同的名字,或者只是在给定的学期内?
DDD 的部分观点是解决方案的设计需要探索“无处不在的语言”以全面了解需求。
换句话说,您可能无法在设计中找到适合此要求的合适方案,因为您尚未找到使其按业务专家期望的方式工作所需的所有实体。
Udi Dahan指出唯一性规则可能根本不属于域:
不属于真正领域逻辑的规则不必在领域模型中实现,他建议,因为它们不为领域建模。
因此,如果您有这样的约束,但该约束不是域本身的结果,那么该约束可以在其他地方正确实现。
Greg Young 还写过关于 set validation 的文章,专门解决了对最终一致性的担忧。
但从广义上讲,是的——如果你真的有一个实体集合,以及一个跨越集合中多个元素的域规则,那么你需要一些聚合来保持集合所在边界的完整性。
实体不一定如您所想。例如,如果您需要名称是唯一的,并且类实体的其余部分只是顺其自然,那么您可以通过创建名称注册表聚合来简化规则;教授为他们的班级保留名称,如果保留可用,则保留的名称可以应用于班级实体。
如果您的核心业务真的是命名事物,需要考虑许多特殊的不变量,您可能会围绕此构建一个大模型。但这并不是特别可能。也许您可以将一两个表添加到关系数据库中——这是解决集合验证问题的好方法——然后继续进行项目中有价值的部分。
还有另一个聚合根“教授”,因为它们是全局可访问的。他们将被分配到一个班级。我不确定它是否被允许,因为聚合根应该只指向另一个聚合根而不是它的内容。
class.assign(professorId);
是这里通常的答案——您传递标识聚合根的代理键。您域中的每个实体都应该有一个。
这里有几点注意事项:我发现现实世界的实体(尤其是人)并不是确定聚合用途的有用起点。主要是因为它们最终成为数据的表示,主要是在域模型之外强制执行不变量的数据。
另外,我发现从名词开始 - class、department、professor - 倾向于将重点放在 CRUD 上,这通常不是一个非常有趣的问题。
相反,我建议考虑做一些有用的事情——一个需要强制执行业务规则的用例,当业务模型说“不,业务现在不允许你这样做”时。