在 Pluralsight 类(class)中 Domain-Driven Design Fundamentals ,有一个例子说明聚合的设计是如何形成的。
该示例涉及诊所的患者预约。任命有关系,例如去看医生,或者去检查室。
该示例之前进行了分析,得出的结论是 Appointment 不应是 Doctor 和 ExamRoom 的聚合根。
设计演变的一个步骤是从 Appointment 具有对 Doctor 和 ExamRoom 对象的对象引用,到持有这些其他实体的原始 id,DoctorId 和 ExamRoomId。
他们通过说:
“通过简单地包含相关概念的 id 而不是对象引用,我们能够确保当我们坚持我们的约会时,创建和更改约会对我们的系统的影响最小”
我的第一个问题:这是一种常见的设计模式吗?如果我理解正确,它会概括为:如果对象 A 与对象 B 相关,但对 A 进行操作永远不应该对 B 进行更改,然后通过它的 id 引用它,而不是 B 本身。这是你会推荐的东西吗?
我的第二个问题:这与 DDD 有什么关系?我的意思是 Appointment 不应该是医生的聚合根,并不意味着它不能保存对它的对象引用,或者我错过了什么?
最佳答案
是的,Appointment
不应该是 Doctor
的 AR和 ExamRoom
因为这并不构成被建模业务的最佳边界。
例如,创建约会不应该负责验证包括医生和检查室(业务不变量/规则)在内的整个模型。
其他两个实体最好被建模为它们自己的独立 AR。这将系统解耦并允许三个模型单独运行,从而在同时处理所有三个模型时允许更好的并发性,例如由 3 个不同的用户在 3 个不同的方面(即模型)同时工作。
还记得他们问客户一次是否会有多人安排约会吗?她说不,但不排除在不久的将来某个时候,他们也希望允许这样做。
这给了史蒂夫和朱莉从简单开始的动机,使用域模型的初始版本将所有内容建模在一个巨大的聚合中......也许是故意的,所以他们以后可以为 DDD 提出两个重要的观点:重构和设计小型聚合。
所以要回答你的第一个问题,Appointment
会更好。 (一个 AR)持有一个 Id 作为对 Doctor
的引用(作为 AR),而不是对象引用。
虽然持有对象引用一开始看起来不错,因为毕竟 Doctor
,在这种情况下,是一个 AR 并且被封装并负责它自己的不变量,很容易导致医生对象不再是对外部实体的引用,而是在 中的实体。整体预约 AR 的一部分,因为很容易开始调用它的方法并将内部(Appointment
)逻辑链接到它,期望某种形式的状态一致性。
如果另一个 AR 也拥有对同一位医生的引用并开始做同样的事情,认为它是唯一负责该医生状态的 AR,会发生什么?好吧,您将拥有一个紧密耦合、损坏、不一致的模型。
但在一种情况下,Appointment
(AR) 可以持有对 Doctor
的对象引用如果医生被建模为约会集合的内部(即一部分)。但是,外面的任何东西都不能(也不应该!)引用医生!
回答你的第二个问题,这现在应该很明显了:当然它与(正确的)DDD 有关。操作 Appointment
也不应该对 Doctor
进行操作因为这将跨越聚合边界(您在一个事务中保存多个聚合根)。那时您可能应该认为,当前模型可能不是最好的模型,或者可能存在一些您尚未发现的隐藏业务规则。
但是约会可以包含对医生的引用(当然是通过 ID)。您的这部分假设是不正确的。但我想现在已经很明显了。这是第一个问题的一部分。
我在学习 DDD 时看到了这个问题,发现它是从 2015 年开始的,它还没有得到你对 @mdo 答案的第一条评论的答案,所以我想我也应该尝试回答这个问题,但尽量不要那么简洁。也许@mdo 认为您评论的答案也在他对您问题的回答中。我明白为什么了。 DDD 令人困惑且难以掌握。我自己还在学习。无论如何,希望我做对了……对于我和其他阅读此答案的人。 😅
关于domain-driven-design - DDD 聚合中的对象引用与 Id 引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32417657/