领域服务和领域事件如何取舍?或共存?

14-06-26 wilsonp
各位大大,当业务功能涉及到多个聚合的时候,有多种方式进行处理,其中有两种方式使用比较普遍,一种是领域服务,另一种是领域事件,也不排除两种同时存在的情况,那如何取舍呢?

一个系统中很多业务功能都会涉及到2个或多个聚合,如果使用领域服务,将会导致在领域层会存在大量的领域服务类,这种方式实现的效果同传统的三层框架中的服务层实现的效果差不多,唯一区别只在于领域服务是将具体的业务逻辑放到领域对象中,而服务层是将所有的业务逻辑直接写在服务层中;

更好的方式是采用发送领域事件的方式,即没有领域服务,当一个业务功能涉及到多个聚合的时候,通过同步事件来进行聚合之间的交互,拿CQRS来说,领域对象中的业务逻辑是由命令处理器来调用的,当一个业务设计到聚合A-->聚合B-->聚合C三个聚合,但聚合A处理完相应的业务逻辑后,修改自身状态,然后发送领域事件到事件总线,然后由事件总线将这个事件立即分发到聚合B,并依次到聚合C,那就意味这在聚合A执行业务逻辑之前,必须手动地将聚合B和C同时注册到事件总线中(这个注册必须在之前的命令处理器中进行),当所有业务逻辑都处理完成之后再将其进行反注册,以取消B和C对A产生事件的关注。

不知以上我的理解有无问题?欢迎大家批评指正

[该贴被wilsonp于2014-06-26 15:56修改过]

sinaID09784
2014-06-26 18:00
按照楼主描述的方式 来使用领域事件,那不可避免的会遇到一个问题:事务

使用事件总线的方式,一般都是追求最终一致性。但是最终一致性是否需要取决于业务,取决于基础设施是否能够完美支持。

目前,我的方式是采用事务一致性,并两者共存,但是需要削弱领域服务和领域事件的职责。

领域服务:协调多个聚合,完成业务。

领域事件:所有的命令处理器共享一个事务,一个线程,所有的命令处理器都在一个事务内部,事件总线也只在一个线程内共享。

wilsonp
2014-06-26 18:20
关于事务的问题,如果是应用层事务的话,(注意和数据库事务分开),可以简单采用工作单元来实现事务一致性,就像你说的,”所有命令处理器共享一个事务“,但进入一个命令处理器的时候,就开始了一个工作单元,且所有的事件都实现存储起来,当业务处理完成之后有工作单元来进行统一提交或回滚...

[该贴被wilsonp于2014-06-26 18:20修改过]

wilsonp
2014-06-26 18:28
2014-06-26 15:56 "@wilsonp"的内容
当一个业务设计到聚合A-->聚合B-->聚合C三个聚合,但聚合A处理完相应的业务逻辑后,修改自身状态,然后发送领域事件到事件总线,然后由事件总线将这个事件立即分发到聚合B,并依次到聚合C,那就意味这在聚合A执行业务逻辑之前,必须手动地将聚合 ...

其实这里我已经潜在的将B和C当作事件处理器来使用,如果是另外一个专门针对A发出的事件的事件处理器(不是B或C),而事件中只包含事件源A,聚合B的ID,聚合C的ID,那如何来尽心接下来的业务呢?这个问题的讨论请移至这里:事件处理器对领域的操作

tangxuehua
2014-06-27 22:53
可以看一下我写的银行转账的例子,思路是领域事件+流程管理器(cqrs架构中的saga)

https://github.com/tangxuehua/BankTransferSample

猜你喜欢