Domain driven design DDD:作为聚合根的大学
Domain driven design DDD:作为聚合根的大学,domain-driven-design,Domain Driven Design,一段时间以来,我一直在处理领域驱动的设计。不幸的是,我在总量方面有一些问题
比如说,我喜欢模拟一所大学的结构。这所大学有一些系(系),每个系都有一些班级。有一条规则,每个部门都必须是唯一的,所以每个班级都必须是唯一的。例如,类的名称需要是唯一的。如果我理解正确,那么“大学”似乎是我的聚合根,“系”和“类”是这个聚合中的实体
还有另一个聚合根“Professor”,因为它们可以在全球范围内访问。他们将被分配到一个班级。我不确定它是否被允许,因为聚合根应该只指向另一个聚合根,而不是它的内容
如何处理
一段时间以来,我一直在处理领域驱动的设计。不幸的是,我在总量方面有一些问题
比如说,我喜欢模拟一所大学的结构。这所大学有一些系(系),每个系都有一些班级。有一条规则,每个部门都必须是唯一的,所以每个班级都必须是唯一的。例如,类的名称需要是唯一的。如果我理解正确,那么“大学”似乎是我的聚合根,“系”和“类”是这个聚合中的实体
还有另一个聚合根“Professor”,因为它们可以在全球范围内访问。他们将被分配到一个班级。我不确定它是否被允许,因为聚合根应该只指向另一个聚合根,而不是它的内容
如何处理?
谢谢你的帮助,
提前谢谢 问问自己以下问题:
- 你们系统中有多少所大学?如果这只是一个,那么它不是聚合根
- 如果你的系统中有多所大学,会有人跨大学工作吗?也许大学是你的系统租户
- 如果某个部门解散了,班级会怎么样?它会立即消失吗?我对此表示怀疑
- 大学与系的关系同上
对于一个部门来说,将其类的引用作为包含类聚合根id和类名的值对象列表来保存并不是问题。这同样适用于处理课程的部门
Vernon's可能也有帮助。我在DDD方面也不是很有经验,但这里有一些我常用的技巧:
- 有没有可能在没有指定部门的情况下上课?如果是这种情况,那么Department是聚合根,Class是另一个聚合,引用根Department。您甚至可以使用需要创建类的信息在部门内定义工厂方法“addClass()”,因此不允许任何人在没有部门的情况下创建类李>
为什么将类定义为聚合而不是值对象?因为价值对象是通过其属性的值而不是ID来区分的。我想说的是,即使有两个具有相同名称、相同学生、相同信息等的类,企业仍然希望区分每个类。这与1美分硬币不同,1美分硬币只关心其价值(由颜色、大小、重量等给出),但你总是可以用另一枚具有相同属性价值的硬币代替,即1美分。另外,如果将另一个教授分配给该类,则该类保持不变,它并不像值对象应该是不变的
- 我想一个教授必须是独一无二的,他可能被分配到不同的班级,甚至是不同的系。所以对我来说,这是另一个与部门分离的聚合根李>
比如说,我喜欢模拟一所大学的结构。这所大学有一些系(系),每个系都有一些班级。有一条规则,每个部门都必须是唯一的,所以每个班级都必须是唯一的。例如,类的名称需要是唯一的
真的吗?为什么?这条规则的商业价值是什么?如果碰巧有两个同名的班级,企业(大学)的成本是多少。这是指在任何时候,还是在某个学期,都使用同一个名字
DDD的一部分要点是,解决方案的设计需要探索“无处不在的语言”,以充分理解需求
换言之,您可能在设计中很难找到适合此需求的实体,因为您尚未找到使其按业务专家期望的方式工作所需的所有实体
指出唯一性规则可能根本不属于域:
他建议,不属于真正域逻辑的规则不必在域模型中实现,因为它们不为域建模
因此,如果您有这样的约束,但约束不是域本身的结果,那么该约束可以在其他地方正确实现
Greg Young还写了一篇文章,专门讨论了对最终一致性的担忧
但从广义上讲,是的——如果您确实有一个实体集合,并且域规则跨越集合中的多个元素,那么您需要一些集合来维护集合所在边界的完整性
实体不一定是你所想的。例如,如果您需要名称是唯一的,而类实体的其余部分只是顺其自然,那么您可以通过创建名称注册表聚合来简化规则;教授为他们的类保留名称,如果保留可用,则可以将保留名称应用于类实体
如果你的核心业务真的命名了事物,有很多特殊的不变量要考虑,那么你可以在这周围建立一个大的模型。但这不太可能;也许您可以将一两个表插入到关系数据库中——这是解决一组验证问题的好办法——然后继续进行项目中有价值的部分
还有另一个聚合根“Professor”,因为它们可以在全球范围内访问。他们将被分配到一个班级。我不确定它是否被允许,因为聚合根应该只指向另一个聚合根,而不是它的内容
这是这里常见的答案——传递标识聚合根的代理键。域中的每个实体都应该有一个
这里有几个注意事项:我发现现实世界中的实体(尤其是人)并不是计算聚合的有用起点。Primaril
class.assign(professorId);