知识卡片
设计职责决定用命令还是事件:试金石与混合案例
内容
判断该用事件还是命令,一个好用的试金石是问:”如果这个事件被忽略、导致某个组件遗漏了要做的事,这种情况可以接受吗?”能接受就是事件,不能接受就该用命令——比如订单履约里的通知邮件,用户没收到会不高兴,但这不是大问题,用事件让通知服务自己决定何时发即可,这不再是订单履约团队的问题;但如果是法律要求必须发出的通知,订单履约团队就可能要为此负责,这促使他们改用命令。用命令重构本章反复出现的订单履约事件链正是这个原则的应用:先厘清订单履约在整个流程中的职责(很可能是一个独立的订单履约微服务,因为这个职责不适合塞进支付/库存/结算/发货任何一个服务),结算服务照常发出下单成功事件(结算团队本来就不负责保证订单交付,用事件没问题),但订单履约服务订阅这个事件后就要主动负责后续一切:先向支付服务发送确认支付的命令并等待结果,再向库存服务发送提货命令——由此把顺序控制权完全收归订单履约服务,支付服务只需要”安全可靠地收款”,完全不用理解”下单成功”这类外部事件的含义;这个设计还带来额外好处:如果未来出现不需要发货的订阅制或数字商品业务,完全不需要改动支付服务本身,而基于事件的API几乎无法做到这一点。设计职责从来不是固定的,而是组织可以、也应该主动去设计的——通知发送这类例子里,如果发送方(如通知团队)无须为后续负责,用事件就很合适;如果发送方(如用户入网团队对欢迎信)必须为结果负责(可能出于法律要求,CEO会直接找上门),就必须用命令,只有发出命令后才能真正把责任移交给下游。忽视职责设计的后果是团队之间相互指责、协作成本飙升,这正是微服务架构要极力避免的。
参考来源
- 位置:《流程自动化实战:系统架构和软件开发视角》第8章《平衡编排与编制》"8.2.4 使用命令来避免事件链""8.3.1 选择使用命令还是事件""8.3.3 设计职责"(源文件:_epub-src/EPUB/xhtml/Section0001_0012.xhtml)
- 结论依据:原文给出"事件被忽略是否可接受"的试金石标准,用订单履约服务重构为主动发命令给支付/库存服务的案例说明职责收拢的设计思路,并用用户欢迎信必须用命令(法律责任)对比忠诚度计划可用事件(无须负责)的对照,直接支撑本卡片结论。
- 原始内容:如果一个事件被忽略,导致组件遗漏了一件事,这种情况是可接受的吗?这个问题是个不错的试金石……订单履约服务首先必须确保此订单支付成功。将意图转化为命令……在这种情况下,我认为用户入网团队有责任确保这封信真的被寄出。