DDD:大学作为聚合根

时间:2016-03-13 18:25:36

标签: domain-driven-design

有一段时间我正在处理域驱动设计。不幸的是,我在聚合方面遇到了一些问题。

说,我喜欢模拟大学的结构。大学有一些部门(院系),每个部门都有一些课程。有一条规则,即每个部门都需要独特,因此每个部门都需要。例如,类的名称必须是唯一的。如果我理解正确,那么“大学”似乎是我的聚合根,“部门”和“类”是这个聚合中的实体。

还有另一个聚合根“教授”,因为它们是全球可访问的。他们将被分配到一个班级。我不确定它是否被允许,因为聚合根应该只指向另一个聚合根而不指向其内容。

如何处理? 感谢您的帮助, 提前谢谢!

3 个答案:

答案 0 :(得分:3)

  

说,我喜欢模拟大学的结构。大学有一些部门(院系),每个部门都有一些课程。有一条规则,即每个部门都需要独特,因此每个部门都需要。例如,类的名称必须是唯一的。

真的?为什么?该规则的商业价值是什么?如果碰巧有两个同名的班级,那么企业(大学)的成本是多少。这是指所有时间都是同一个名字,还是只是在给定的学期内?

DDD的部分要点是解决方案的设计需要探索“无所不在的语言”以充分了解需求。

换句话说,您可能无法在设计中找到适合此要求的因素,因为您尚未发现所需的所有实体,使其按照业务专家的预期运作。

Udi Dahan指出唯一性规则可能根本不属于域名:

  

不是必须在域模型中实现不属于真正域逻辑的规则,因为他们不对域建模。

因此,如果您有这样的约束,但约束不是域本身的结果,那么约束可以在其他地方正确实现。

Greg Young还撰写了关于set validation的文章,专门解决了对最终一致性的担忧。

但广泛地说,是的 - 如果你真的拥有一组实体,并且一个域规则跨越集合中的多个元素,那么你需要一些聚合来保持集合所在边界的完整性。

实体不一定是你的想法。例如,如果您需要名称是唯一的,并且类实体的其余部分仅用于搭载,那么您可以通过创建名称注册表聚合来简化规则;教授为其班级保留名称,如果保留可用,则保留名称可以应用于班级实体。

如果您的核心业务确实在命名,需要考虑许多特殊的不变量,那么您可以围绕这个构建一个大型模型。但那并不是特别可能;也许你可以把一两个表打成一个关系数据库 - 这是设置验证问题的一个很好的解决方案 - 并继续使用项目中有价值的部分。

  

还有另一个聚合根“教授”,因为它们是全球可访问的。他们将被分配到一个班级。我不确定它是否被允许,因为聚合根应该只指向另一个聚合根而不指向其内容。

class.assign(professorId);

通常是这里的答案 - 您传递标识聚合根的代理键。您域中的每个实体都应该有一个。

这里有一些注意事项:我发现现实世界的实体(特别是人)并不是一个有用的起点,可以确定聚合的用途。主要是因为它们最终是表示在域模型之外强制执行不变量的数据。

另外,我发现从名词班,系,教授开始,往往把重点放在CRUD上,这通常不是一个非常有趣的问题。

相反,我建议考虑做一些有用的事情 - 一个有强制执行业务规则的用例,当业务模型说“不,业务不会让你现在就这样做”。

答案 1 :(得分:0)

问自己这些问题:

  • 您的系统中有多少所大学?如果这只是一个,则它不是您的聚合根。
  • 如果您的系统中有多所大学,那么跨大学的人会是谁?可能大学是你的系统租户吗?
  • 如果某个部门解散,课程会怎么样?它会立即消失吗?我对此表示怀疑。
  • 与上述大学与部门关系相同

部门将引用其类作为包含Class聚合根id和类名的值对象列表并不是问题。对于处理班级的部门来说,这同样有效。

弗农的Effective Aggregate Design也可能会有所帮助。

答案 2 :(得分:0)

我对DDD也不是很有经验,但这里有一些我用过的技巧:

  • 是否有可能没有指定部门的班级?如果是这种情况,则部门是聚合根,而类是另一个聚合,其中引用了根,即部门。您甚至可以在Department中定义一个工厂方法“addClass()”,其中包含需要创建Class的信息,因此不允许任何人创建没有Department的Class。

为什么将类定义为聚合而不是值对象?因为值对象通过其属性的值而不是ID来区分。我会说,即使有两个具有相同名称,相同学生,相同信息等的课程,企业仍然希望区分每一个。它与1美分硬币不同,你只关心价值(由颜色,大小,重量......给出),但你总是可以用另一个具有相同属性值的硬币替换它,即1分。同时将另一位教授分配给该类,该类保持不变,它不是一个值对象应该是不可变的。

  • 我想教授必须具有独特的识别能力,他可以被分配到不同的班级甚至是部门。所以对我而言,这是另一个与部门分离的聚合根。