DDD - 执行需要了解多个聚合根的规则

Stu*_*ffe 5 domain-driven-design aggregateroot

我是DDD的新手,目前正在寻找重建现有应用程序的方法,先从一些概念证明开始,而我仍然在寻找DDD的方法.我的问题只涉及领域模型的一小部分,所以它在某一刻似乎过于简单化了.

这是一个为在家中探望病人的护士安排的应用程序.因此,很明显"Patient"是一个AggregateRoot,而"Nurse"是另一个AggregateRoot.除了指派护士使用"预约"实体访问患者之外,患者与护士没有直接联系.

现在,约会实体可以很容易地属于患者或护士AR,或者甚至两者都认为预约是两者之间的联系.因此,我也将任命变为AR.所以第一个问题是:

1)这种建模听起来不错吗?我原本试图在患者/护士AR下添加一组约会实体,但由于它确实属于两者,因此它是自己的AR是有意义的.我当时正考虑在护士/病人AR下添加一个约会ID列表以链接到他们的约会,但这意味着保存约会的交易需要同时影响多个AR,这可以从我所知道的建议糟糕的聚合设计.

假设到目前为止这种建模是有意义的,我现在需要找出执行业务规则的最佳方法,这些规则涉及当前AR的所有3个.例如,护士不能同时在一个以上的地方,因此我们不能与分配给同一护士的另一个同时创建预约.每位患者也只能预约一次.所以第二个问题是:

2)你将如何执行这些涉及多个不同AR的规则?显然,如果约会是患者或护士AR下的嵌套集合,则规则将易于实施,并且非常自包含.现在这让我怀疑我的建模是否正确.

我已经在不列颠哥伦比亚省和佐贺县/流程经理周围阅读了很多内容,但对我而言,这是同一个BC的一部分,因此不确定我是否需要任何复杂的东西.简单地使用CommandHandler来加载多个AR对象并使用它们的状态来确定是否可以创建约会是否可以接受?

如果是这样,并且与上面的Q1重叠(假设我没有在护士/患者AR下存储预约ID列表),阅读模型是轻松找到属于相应护士/患者的预约的唯一方法 - 那么基于读取模型的状态而不是存储库中的AR来强制执行业务规则也是可以接受的吗?

希望这是有道理的,并提前感谢!

Voi*_*son 5

这个建模听起来对吗?

不(但这不是你的错——文学很烂)。你的聚合将是信息的表示,而不是在现实世界中走来走去的人。轮换时间表,值班名单,这些都是可以汇总的东西。

例如:

一名护士不能同时在多个地方,因此我们不能与分配给同一名护士的另一名护士同时创建预约

这不是对护士的限制,而是对时间表的限制。

“上午 9 点,护士 (id:12345) 将访问患者 (id:67890)”是一个时间表条目。将所有计划条目一起管理是非常直接的。 日程表的视图可能还需要包括有关护士或患者的附加信息,因此视图可能会加入附加信息。

该计划成为它自己的“聚合”,使用相关 ID 来启用与其他信息的连接。

时间表是“NurseSchedule”还是系统范围的“Schedule”?

这可能是调度护士用例的特定内容。根据域的不同,给定的时间表可能会涉及许多护士和患者。


Con*_*enu 1

简单地使用一个 CommandHandler 来加载多个 AR 对象并使用它们的状态来确定是否可以创建约会是否可以接受?

不,如果您想遵循 DDD 方法,则不需要。Aggregate 不应小于事务,Aggregate 是事务边界。

据我所知,您有以下业务不变量:

  1. 一名护士不能同时出现在多个地点,因此我们无法在为同一护士分配另一个预约的同时创建预约

  2. 每个患者只能有一个待处理的预约

仅当护士和患者属于同一聚合时,这两条规则才能得到严格执行。也就是说,如果您希望无论如何都遵守这两条规则,则应该有一个大聚合。

但拥有如此大的聚合可能会让人感觉不对。您可以做一些事情:权衡:两条规则中哪一条可以以最终一致的方式执行?在与业务专家讨论并向他/她展示业务影响后,您选择一个,然后创建一个 Saga/Process 管理器来检测此类无效状态并纠正它和/或通知某人手动纠正它。

如果是这样,并与上面的 Q1 联系起来(假设我没有在护士/患者 AR 下存储预约 ID 列表),读取模型是轻松找到属于相应护士/患者的预约的唯一方法 -那么基于读取模型的状态而不是存储库中的 AR 来执行业务规则是否也可以接受?

Saga/Process 管理器使用数据(最终一致的更新数据)向聚合发送正确的命令,就像 Readmodel 一样。因此,您可以让 Saga 维护私有状态(更安全/更干净的解决方案),或者让我们查询规范的 Readmodel 以查找无效案例(更快/更脏的解决方案)。