domain-driven-design - DDD 聚合中的对象引用与 Id 引用

标签 domain-driven-design

在 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/

相关文章:

domain-driven-design - DDD 中的聚合根之间允许哪种级别的通信?

hibernate - DAO 和 Repository 模式有什么区别?

oop - 如何优雅地避免使用 DDD 对域实体的基础设施服务的依赖?

java - DDD 示例应用程序 - hsqldb 在哪里?

java - DDD - 在拥有映射器类时不暴露 setter/getter

events - 这个进程管理器状态应该被持久化吗?

rest - 在领域驱动设计中可以调用另一个限界上下文的应用程序服务吗?

domain-driven-design - 聚合为服务

domain-driven-design - 领域驱动设计中的模型应该有多现实?

asp.net-core - 暴露应用程序命令的强类型 ID?