领域事件就字面理解为,领域内已发生的活动,这是一个有具体状态的事件。工具
将领域中所发生的活动建模成一系列的离散事件。每一个事件都用领域对象来表示。领域事件是领域模型的组成部分,表示领域中所发生的事情。字体
要点:“领域事件是领域模型的组成部分”,经过这句话能够得知,领域事件不会是领域模型,那么在具体代码中领域事件是做为实体仍是值对象呢?中间件
事件直接的理解是“已经”发生的活动,是不变,因此值对像是比较好的选择。对象
领域事件是一个领域模型中极其重要的部分,用来表示领域中发生的事件。忽略不相关的领域活动,同时明确领域专家要跟踪或但愿被通知的事情,或与其余模型对象中的状态更改相关联。事件
要点:事务
领域事件做为领域模型的重要部分,是领域建模的工具之一。it
领域建模即分析业务,而领域事件是领域中一种状态的反应,例如肚子饿了,会经过神经感受反馈给身体饿了这个信息。而这个信息可让咱们得知领域会作哪些业务。支付
用来捕获领域中已经发生的事情。数据
已发生的事情才被称之为事件。语言
并非领域中全部发生的事情都要建模为领域事件,要忽略无业务价值的事件。
例如人的身体不会告诉人自己指甲太长了,可是却会通知身体肚子饿了,由于指甲长不影响人的存货,而饿肚子却会被饿死。即有价值才值得建模事件。
领域事件是领域专家所关心的(须要跟踪的、但愿被通知的、会引发其余模型对象改变状态的)发生在领域中的一些事情。
同第三点所述同样,有价值才会被关心才能做为领域事件。
简而言之,领域事件是用来捕获领域中发生的具备业务价值的一些事情。它的本质就是事件,不要将其复杂化。在DDD中,领域事件做为通用语言的一种,是为了清晰表述领域中产生的事件概念,帮助咱们深刻理解领域模型。
上述中
领域事件是领域专家所关心的(须要跟踪的、但愿被通知的、会引发其余模型对象改变状态的)发生在领域中的一些事情。
从这句话能够知道,领域事件所作的是跟踪事件和通知,也就是当发生了某件事情,才去作某一个操做。
例如:
当用户下单,扣除库存。
当用户支付,扣除用户余额。
当用户签收包裹,订单状态变动已签收。
那么,这些都是领域事件吗?回到刚才的话中,“须要跟踪的、但愿被通知的、会引发其余模型对象改变状态的” 用户下单扣除库存是即时的操做,不知足加粗字体句中的三个条件。 用户支付扣除余额同理。用户签收包裹变动订单状态,知足会引发其余模型对象改变状态这个条件,因此是领域事件。
因此只有须要被跟踪、被通知、会改变其余模型状态的业务,才须要建立领域事件。
接上面签收例子,当订单状态变动后,商家从第三方平台收到货款,这个时候领域中是最终一致性的。因此部分领域事件是能够保持领域最终一致性。
上述多个例子中能够分析出,不管是变动订单状态,仍是商家收到货款,这些都不是具体业务,既然如此,在使用领域事件时应该是可以保持原代码不作业务改变的,保证业务不变,只是对业务结果作出处理。
再者应当是能够解决领域的聚合性问题。DDD中的聚合有一个原则是,在单个事务中,只容许对一个聚合对象进行修改,由此产生的其余改变必须在单独的事务中完成。若是一个业务跨多个聚合对象,领域事件会是一个不错的工具来解决这个问题。经过领域事件的方式能够达到各个组件之间的数据一致性,经过最终一致性取代事务一致性。
那么如何建模领域事件呢?
事件存储,顾名思义,即事件的持久化。那为何要持久化事件?
简单来讲就是记录当时的领域状态。
当事件发布失败时,可用于从新发布。
经过消息中间件去分发事件,提升系统的吞吐量。
用于事件溯源。
源代码管理工具咱们都用过,如Git、SVN等,经过记录文件每一次的修改记录,以便咱们跟踪每一次对源代码的修改,从而咱们能够随时回滚到文件的指定修改版本。
事件溯源的本质亦是如此,不过它存储的并不是聚合每次变化的结果,而是存储应用在该聚合上的历史领域事件。当须要恢复某个状态时,须要把应用在聚合的领域事件按序“重放”到要恢复状态对应的领域事件为止。
通过上面的分析,咱们知道引入领域事件的目的主要有两个,一是解耦,二是实现数据的最终一致性。
最后,对于领域事件,咱们能够这样理解:
经过将领域中所发生的活动建模成一系列的离散事件,跟踪事件执行相应的业务逻辑。
也能够简要理解为:领域事件 = 事件发布 + 事件存储 + 事件分发 + 事件处理。