本文转载自【何以解耦】:https://codedecoupled.com/eve…
Martin Fowler 在 2017 年做了一次对于事件驱动模式的演讲【The Many Meanings of Event-Driven Architecture】。此文是自己观看演讲后的一篇总结。因为视频在油管,无奈翻墙的同学可浏览文字版。
当不同的开发者提及事件驱动时,他们可能意味着齐全不一样的概念。Martin Fowler 将不同的事件驱动模式进行梳理,细分为以下四种。
事件告诉(Event Notification)
事件告诉模式是指发送方通过事件的形式告诉接管方本身畛域的状态更改。大部分状况下发送方不须要期待任何回应。
用一段简略的 PHP 代码展现事件告诉模式:
class OrderShipped
{
private int $orderId;
public function __construct(int $orderId)
{$this-> orderId = $orderId;}
}
class SendShipmentEmail
{
private int $orderId;
public function handle(OrderShipped $event)
{// 查问 Order 详情,而后发送邮件}
}
// 公布 OrderShipped 事件
OrderShipped::dispatch($order);
事件告诉模式可升高代码的耦合性,SendShipmentEmail
通过监听 OrderShipped
事件独立工作,耦合性升高,单元测试不便且间接。
同时也留神事件自身并不携带很多信息,接管方需通过查问源数据来获取所需数据。
防止陷阱
尽管应用事件告诉模式可升高代码耦合性,而且高内聚低耦合是优良软件设计的规范,可是适度应用或者不正确应用事件告诉模式,可能会导致代码逻辑凌乱,难以了解,给 debug 制作很多麻烦。
因为事件告诉模式个别是通过观察者模式实现,在代码层面无奈直观的看出一个事件公布当前所造成的影响。比方在上文中,OrderShipped
公布当前,代码流程是看不出 SendShipmentEmail
将被触发的。
携带状态事件转移(Event-Carried State Transfer)
在事件告诉模式中,因为事件自身的信息比拟少,所以接管方往往须要再次通过拜访发送方来获取业务所需的信息。在绝对独立的零碎中,这种形式效率低且等待时间过长。这时咱们能够将接管方须要的所有信息都加载至事件中,发送方和接管方各自维持本人的状态。这种事件驱动模式,咱们称其为携带状态事件转移模式。
长处还是毛病
这种模式的成果是接管方将呈现大量的数据正本,而且接管方须要维持其版本的秩序。保护数据正本的老本用来换取提早升高的益处,长处还是毛病,因利用需要而异。
事件溯源(Event Sourcing)
将每个状态变动存储为一个独自事件,利用状态通过播放事件来获取,这样一种数据长久化计划叫做事件溯源。与面向状态的长久化计划相比,事件溯源提供了一些不言而喻的益处:
- 自带审计跟踪性能。每一个状态变动都追加至存储器中,存储器中自然而然造成了一个审计日志。
- 易于排查 bug。这是集体认为事件溯源提供的最大益处,有序浏览事件能够直观地剖析出状态是如何的造成。
- 事件旅行。历史记录以及历史状态都能够不便地通过重播事件来获取。
挑战
事件溯源也有本身的挑战,比方当利用与第三方产生交互,当重播时,如何解决数据的一致性,如何保障第三方的稳定性,这是在应用事件溯源时,须要面临的挑战。
命令查问职责拆散(CQRS)
严格来说命令查问职责拆散模式不属于事件驱动模式,因为它常常与事件溯源混同,所以 Martin Flow 将它归类其中。简略来说,命令查问职责拆散是指将数据的写入以及读取彻底离开,这和数据库的读写拆散十分相似,但它是一种利用架构模式,大部分状况下,它的写入(命令)局部应用事件溯源来实现。
总结
应用事件驱动编程时,只有了解其本质能力防止囫囵吞枣,画蛇添足。
本文转载自【何以解耦】:https://codedecoupled.com/eve…,如果你也对 TDD,DDD 以及简洁代码感兴趣,欢送关注公众号【何以解耦】,一起摸索软件开发之道。