基于DDD重构历史代码有感

业务中常见问题

在业务初期的场景中由于没有明确的模型概念导致代码中大量的持久层引用,这在业务简单的情况下是可以接受的,因为不能预测业务的趋势.随着业务的逐渐扩张,一个service中引入的dao会越来越多,可能多个service中会引用同一个dao,这样如果其中一个dao的表结构变更或者更新逻辑改变则会影响很多地方,导致开发人员在扩展功能的同时要照顾到老的代码引用该dao的地方,所以这时需要引入聚合的概念来清晰的划分出职责.

引入聚合概念

跨聚合的调用一定要通过聚合根来操作,如下图:

img

如要修改A1只可以通过A来修改,这样做的好处既是入口单一,避免失联模型(不通过聚合根修改该聚
合中的属性)的产生.

聚合内保证强一致性

聚合间保证最终一致性

串行流程替换成事件机制

如下图:

img

当确认订单的时候执行了一系列的操作,导致处理的service中引入了大部分与该领域无关的service或dao,使得代码复用率低,引用杂乱,代码维护难度提高.如果业务变更,需要在确认订单的时候加一部分逻辑,则该service会越来越臃肿,所以我们引入事件机制,修改后如下图:

img

通过引入事件的机制我们成功将order和后面一系列的聚合解藕,并提高了代码的复用率.当业务变更时,我只需要新增监听的代码即可,达到了高业务扩展性.

防腐层引入

举个例子:

img

例如:由于业务的变化在生成订单之前需要判断该企业是否有资格创建.我们可能会把校验放到order流程里面,如果业务再次发生变化,根据不同的企业类型去校验不同的属性,则这部分逻辑会严重影响我们下单流程的代码,我们可以将校验这部分抽象化出来,再每次下单之前先去执行相应的校验,成功之后才可以下单.这样校验的逻辑不会影响到我的order代码中,并且可以适应业务后期的校验规则变化.

优势

  • 业务能力高扩展性
  • 业务分库容易,提高系统性能
  • 编译速度提升
  • 解耦系统,减少依赖,开发时不用瞻前顾后
  • 上线时影响部分变小
  • 由于异步的机制,系统吞吐量得到提升

劣势

  • 需要考虑分布式事物问题
  • 由于跨服务交互较多,幂等需要考虑
  • 舍弃了强一致性,可以满足最终一致性
zhang dong wechat
关注我的微信来交流技术问题吧!