【问题标题】:How to decide whether one object should be part of an aggregate or not如何决定一个对象是否应该是聚合的一部分
【发布时间】:2012-02-18 22:01:42
【问题描述】:

在我开始阅读有关 DDD 和聚合的内容后,我似乎试图将所有内容都放入聚合中。几乎每篇博客文章或教程等都使用相同的示例,这并没有任何帮助:Order 和 orderlines。

一个对象可以独立存在或不存在是什么意思?这是否意味着它不能在我的领域建模中独立存在,还是意味着它不能在现实世界中独立存在?

我正在开发一个应用程序,用户可以在其中跟踪他们的驾驶情况。比如,持续时间,距离等等。

我已经创建了一个StudentDriver 类用于对人进行建模,一个DrivingLog 用于对“书”进行建模,并创建了一个DrivingRecords 用于对用户在他/她时所做的每个“行”/记录进行建模已经开车了。这包含持续时间、距离等。

所以现在的问题是:StudentDriver 是否应该被视为所有这些类的聚合根并且每个操作都经过StudentDriver?还是应该StudentDriver 是一个根,DrivingLog 是另一个根,然后StudentDriverDrivingLog 之间会有关联?

很高兴听到您如何决定这一点?无论是在这个例子中,还是在一般情况下。

【问题讨论】:

    标签: java jakarta-ee domain-driven-design


    【解决方案1】:

    DDD 是一本很棒的书,我也很喜欢阅读 Evans 所说的关于聚合模式的内容。不过,我认为你可能做得有点过火了。

    据我了解,聚合模式的目的是:

    当程序的每个部分都与其他部分交互时,就变得难以理解(和调试),因为您无法孤立地理解任何一个部分;要了解任何一部分,您必须了解所有内容。

    此外,当交互发生在各个方向时,破坏对象状态的错误很难追踪,因为您必须到处查看。如果可以修改某个对象的代码有限,那么保证它始终使该对象处于正确状态会容易得多。

    使用聚合模式,您有一个对象是聚合“根”,而其他对象则被根“包含”。只有根可以“触摸”包含的对象,这减少了交互可以通过的路径数量。

    这是您概念性“工具包”中的一个有用的想法,但您不需要仅仅为了这样做而使用它。与其担心“一个对象可以独立生存”意味着什么,不如看看你真正想用StudentDrivers 和DrivingLogs 做什么,然后思考:

    如果我允许其他类直接使用DrivingLogs,或者如果我要求它们调用StudentDriver 上的方法来检索或修改该数据,这段代码会更简单、更易于管理吗?想象一下代码将如何读取任何一种方式。在一种情况下,您可能正在“外部”类中编写drivingLog.mileage();另一方面,你会写studentDriver.loggedMileage()

    DDD 提出的最佳观点之一是匹配模型和实现的重要性,其中甚至包括选择真正有意义的标识符(在您的代码中)之类的事情。与此一致,您还可以查看您的代码正在执行的操作,并思考:如果我考虑这个操作实际上代表什么,它是对驱动程序执行的操作,还是对日志执行的操作?如果实际上该操作是对记录簿进行的操作,那么不要让它使用委托给DrivingLogStudentDriver 方法,只是因为您想使用聚合模式。

    【讨论】:

    • 所以聚合模式更好地应用于类,以便客户端(用户等)更容易理解程序中的各个部分?在这种情况下,驾驶日志可以是驾驶记录的聚合,但学生司机不需要是所有三个类的聚合根吗?当拥有这两个聚合根时,客户端可以轻松理解这两个实体。这个对吗?或者如果不是你的意思,你能解释一下吗?
    • @Bob,对于什么时候使用某种设计模式“更好”,没有简单、简单的答案。任何设计选择(例如是否使用聚合模式)都有优点和缺点,您必须根据具体情况的细节权衡这些优点和缺点。简单的规则,例如“如果 A 在现实世界中不能没有 B,那么它们应该被建模为聚合”并没有任何帮助。您需要了解模式的目的并判断它是否适合您正在做的事情,而不是机械地遵循这些规则。
    • 我对您所做工作的细节了解得不够多,无法就聚合模式是否对您有帮助提供意见。我的印象是您编写此代码是为了练习使用聚合模式——对吗?如果是这样,您为什么不尝试使用 Aggregates 同时编写 withwithout,将两个版本都发布到 codereview.stackexchange.com,并询问 cmets 哪种方式“更好” “在这种情况下?
    【解决方案2】:

    聚合是具有整体/部分关系的两个类之间的关系。例如。汽车是整体,轮子是它的一部分。

    在您的情况下,您可以让 StudentDriver 成为 DrivingLog 的所有者,如果它属于他的话。如果没有现有的学生,那么保留驾驶日志是没有意义的。因此,DrivingLog 不能单独存在。

    StudentDriver 应该是 root 并且知道 DrivingLog。但是DrivingLog不应该知道StudentDriver。(就像单向关联一样)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-06-20
      • 2020-11-16
      • 2014-12-06
      • 1970-01-01
      • 1970-01-01
      • 2016-12-29
      • 2021-09-22
      • 2017-05-05
      相关资源
      最近更新 更多