在CQRS + ES和DDD中,将聚合小读取模型从其他聚合或有界上下文中获取数据是一件好事吗?
例如,在订单验证(按订单汇总)中,有一个业务规则仅在客户未被标记时验证订单。标志信息通过同步域事件放入读模型(特定于聚合)。
您如何看待这个?
答案 0 :(得分:3)
将聚合小读取模型从其他聚合或有界上下文中获取数据是一件好事吗?
这不太理想。由于其性质,聚合体不善于强制执行涉及国家之外的状态的一致性。
这通常意味着当两个聚合产生不可接受的状态时,企业需要某种方式来应对。
在聚合上运行placeOrder
命令之前,您还可以选择检查标志。对该标志的检查可以在命令处理程序中完成,也可以在客户端中完成 - 基本上,您已经“验证”该命令在将其传递给聚合之前应该成功。
也就是说,如果在处理命令时尝试查阅读取模型是至关重要的,那么使用“域服务”的方法就是这样;您将服务提供程序作为命令的一部分传递给聚合,并让接口抽象出运行查询需要在聚合之外查看的事实。
这为您提供了保持聚合可测试所需的一些解耦。
答案 1 :(得分:0)
它是可行的,但不是读取模型的形式,而是聚合中的值对象(因为我们在写入方面)。
如果CustomerId
中已有Order
,您只需要与它和Flagged
成员组成一个VO。
当然,由于数据来自Customer
,因此仍然存在交叉聚合通信的所有问题。 Order
必须与其客户的已标记状态保持同步,这可能需要相当多的工作。
在任何情况下,您可能首先应与您的域专家确定是否立即一致性是绝对要求(在这种情况下,您必须以某种方式在交易中包装客户+订单)或者您是否可以承受标记新鲜度的小延迟强制执行该不变量时。
如果是后者,你可以选择在Order
聚合中复制Flagged或@VoiceOfUnreason给出的第一个选项 - 主要区别可能是如果数据是聚合的,你可以免费获得它在域级别,如果您需要多次,而不是在应用程序级别复制多个用例/命令处理程序中的检查。