Skip to content

Policy 监听器

Policy是领域服务吗?

是的。无状态,封装一段领域逻辑的领域对象,正是领域服务。

Policy必须异步吗?

不是。在事件风暴建模的时候,Policy代表一个对象,它监听事件,触发命令。但建模的时候并没有说明事件的发出者是否要等待Policy的监听动作完成,也没有说明Policy是否要等待命令的执行完成。这些同步异步,都是技术实现的细节,只要符合领域模型的意义,能够解决领域问题,都是可选择的技术时间方式。具体使用哪种方式,取决于非功能性的约束,比如技术框架的支持能力,开发成本,易维护性,响应时间,等等。

建模得到的Polilcy必须实现成事件监听器吗?

大部分情况下是的。如果监听事件的方式确实不容易实现,或者不利用理解流程,在实现的时候改成由CommandHandler负责去协作执行多个命令,也是可以的。一般来说监听事件方式更灵活,代码更简单,更容易扩展;用CommandHandler去显式的协作,则更直观,更容易理解,但耦合性更强,容易形成大泥球。

如何确保Policy触发的命令影响到的聚合,和发出领域事件的聚合的一致性?

如果发出事件的过程,和Policy触发的命令的执行过程,都在一个数据库事务中,则可以通过这个数据库事务实现强一致。绝大部分情况下,都应该使用这种简单有效的方式。

如果不在一个事务内,那只能采用最终一致性了。具体办法参看 发件箱 和 事务 章节,或者搜索更多有关最终一致性的资料。记住,最终一致性是一种不得以才采用的方式,并不应该成为首选的方式。换句话说,只要强一致性够用,就不要用最终一致性。

Policy可以载入发出事件的聚合来获取信息,以决定触发命令逻辑吗?

不推荐这么做,参看 实现领域事件 一节的内容。尽量让领域事件携带足够多的业务信息,减少Policy再次查询聚合。

Policy的逻辑要有状态,这个状态放到哪里?

这种情况可以把功能委托给一个有状态的对象。为了确保下次事件到来的时候,能够找到之前的这个有状态的对象,则需要给这个对象设计一个id。可见,这个有状态的对象就是一个聚合。这个聚合专门负责事件命令的协作,又被称为SAGA。Policy要根据领域事件,去决定要初始化或者载入哪个SAGA,然后由SAGA去决定该如何触发命令,控制业务流程的走向。

所以SAGA是一种聚合?

是的。它承担了协作职责,有状态长期存在,要存起来再载入,有id,都符合对聚合的定义。

所以聚合可以触发命令的执行?

是的。当然可以。

Policy触发命令执行,命令执行产生事件,事件又被Policy监听,岂不是可能递归?

是的。这是一个递归的过程。因此设计的时候确保整个过程能够结束,而不是无限递归下去。