域事件是传播某些事情发生的好方法,以便以后可以发生其他事情。据我了解,跨边界上下文使用域事件非常棒。
假设我们正在创建一个像Stack Overflow这样的问答站点。有users
发布questions
,问题可以closed
。
以下是此类应用程序中的一些可能命令:
- 提出问题
- 关闭问题
- 禁止用户
域要求规定,如果用户被禁止,则必须关闭其所有问题。
当欺诈检测服务检测到用户是欺诈时,应禁止该用户并关闭其所有问题。这fraud detection service
调用ban user service
,而又调用close all of user's questions
服务吗?
我们不想复制我们已经做过的所有"关闭"逻辑。是否只建议调度像"UserBannedEvent"这样的事件,并让侦听器调用close all of user's questions
应用程序服务?或者一个人可以打电话给另一个人吗?
域事件是在聚合上触发副作用的好方法。它允许您通过分离职责来创建细粒度和解耦的实现。也就是说,如果要遵守 DDD。
你可能会问"那为什么不命令呢?好吧,您可以使用命令,但这种情况在语义上是错误的(在我看来(。命令是关于你想要发生的事情,但欺诈检测只是发生了,你应该这样声明它。
如果需要,您可以将命令作为副作用运行,由事件触发(注意不要过度设计(。
是否只建议调度像"UserBannedEvent"这样的事件,并让侦听器调用关闭所有用户的问题应用程序服务?或者一个人可以打电话给另一个人吗?
- 运行
DetectFraudCommand
命令来检测欺诈 fraud detection service
生成FraudDetectedEvent
事件ban user service
由FraudDetectedEvent
触发并调用CloseQuestionsCommand
命令close all of user's questions service
封禁用户
这使得它松散耦合,并清楚地描述了业务逻辑。此外,它的扩展性更好:您可以挂接任何其他侦听器进行FraudDetectedEvent
,而无需触摸fraud detection service
,如果您直接运行命令,这是不可能的。
如果您需要事务一致性,它会变得更加棘手,但可以通过适当的事件调度程序设计来解决。
这里有一个很好的相关阅读 Vaughn Vernon 的聚合设计:链接。