Domain driven design 每笔交易总计一笔,并加上;“一”;或;“多重”;有界上下文

Domain driven design 每笔交易总计一笔,并加上;“一”;或;“多重”;有界上下文,domain-driven-design,Domain Driven Design,按照Vaughn Vernon的建议,为了实现高度的解耦和单一责任,每个事务只需更改一个聚合 在红皮书的第8章中,沃恩·弗农(Vaughn Vernon)演示了两个聚合如何通过域事件相互“交谈”。在第13章中,两个不同的有界上下文中的不同聚合如何通过通知相互“对话” 我的问题是,如果这两种情况都发生在不同的交易中,为什么我要以不同的方式处理它们?如果只是一个或多个有界上下文,那么可能的问题就不一样了 例如,如果应用程序在同一个有界上下文中的两个域事件之间崩溃,我将像在两个有界上下文中一样以不一致

按照Vaughn Vernon的建议,为了实现高度的解耦和单一责任,每个事务只需更改一个聚合

在红皮书的第8章中,沃恩·弗农(Vaughn Vernon)演示了两个聚合如何通过域事件相互“交谈”。在第13章中,两个不同的有界上下文中的不同聚合如何通过通知相互“对话”

我的问题是,如果这两种情况都发生在不同的交易中,为什么我要以不同的方式处理它们?如果只是一个或多个有界上下文,那么可能的问题就不一样了

例如,如果应用程序在同一个有界上下文中的两个域事件之间崩溃,我将像在两个有界上下文中一样以不一致告终


似乎处理两个聚合异步“对话”的最安全方法是在其中设置一个过渡状态,在发送事件之前保留事件(以避免丢失事件),在可能的情况下,当不可能以幂等的方式执行操作时,在接收端进行幂等运算,并对事件进行去重。

< P>我在你的问题中看到两个方面:

  • DDD方面:事件类型以及如何处理它们

  • 技术方面:如何可靠地实现它

  • 关于事件的类型,我想说的是,停留在有界上下文边界内的事件(通常称为域事件)通常携带大量信息。这可能是总体状态的很大一部分。如果使用CQR,则它们用于创建读取模型。跨越BC边界的事件有时称为集成事件,它们应该携带尽可能少的数据(可能只携带全局ID,如CustomerId、OrderId)。原因是您添加的每个额外属性都是发布服务器BC和订阅服务器BC之间的额外耦合,这是您希望最小化的

    我想说的是,正是这两种事件类型之间的区别可能导致不同的技术解决方案,但我同意你的观点,如果你找到一种对这两种情况都有效的解决方案,就不必这样

    你提出的解决方案是正确的。它看起来非常类似于,它基本上为您解决了所有这些问题


    如果您的MessageBroker支持,我使用的另一种方法是Azure Service Bus调用的方法。使用此功能,您可以通过自己的队列发布事件,但发送将以事务方式提交,并从队列中删除传入消息。这意味着,如果由于某种原因,您正在处理的消息没有成功地从队列中删除(DB update exception、broker unavailable等),因此将重试该消息,那么您肯定知道不会发送事件,并且可以在重试期间安全地再次发布它们。这使得幂等运算更简单,并避免发布重影消息

    我更感兴趣的是潜在的不一致性,无论是在相同的有界上下文中还是在不同的有界上下文中。考虑到这一点,我可以得出结论,我应该以同样的方式处理它们,以避免“真正的”不一致。(i) 总体上处于过渡状态;(ii)在发送事件之前保留事件(以避免丢失事件);(iii)在接收端,尽可能以幂等方式执行“域操作”。如果不可能,请消除事件的重复数据,以检查在处理域操作之前是否已收到该事件。谢谢是的,这个解释是我对为什么它们被分开呈现的理解,但我同意,理想情况下,你对待这两种类型的事件的方式是一样的。你当然可以这样做。这就是我链接的发件箱功能所做的,它工作得很好。这种方法唯一的“不便之处”是,您需要确保所有订户都实施了重复数据消除,否则在某些地方会导致双重处理。Francesc Castells,考虑到这种情况,即使是内部事件也会通过总线。我认为我的结论是,总线将像数据库一样被要求(甚至更多),这一点没有错,对吗?我的意思是,公共汽车成了一个关键部件。再次感谢!