DDD 与 CQRS 才是黄金组合( 二 )


DDD 与 CQRS 才是黄金组合

文章插图
这样做可以避免很多不必要的麻烦 , Command 和 Query 存在较大的区别 , 具体如下:
DDD 与 CQRS 才是黄金组合

文章插图
回想开篇时提到的场景 , 完成应用层拆分,就不再为使用错组件而烦恼:
  • CommandService 的 Repository 不使用缓存,仅操作数据库
  • QueryService 的 Repository 可以使用缓存,以提升访问性能
除此之外,针对统一的操作流程,还可以进一步抽象来消除重复的“模板代码”,比如:
1.引入“模板方法设计模式” 以达到核心逻辑的复用
  • 抽象出 BaseCommandService 和 BaseQueryService 两个父类用于统一核心流程
  • 子类实现 BaseCommandService 和 BaseQueryService 的抽象方法完成功能扩展
2.基于“约定优于配置” 使用 Proxy 模型,只定义接口不写实现代码
  • 按规范定义 CommandService 和 QueryService 接口,通过注解完成相关配置
  • 自动生成 Proxy 实现类,完成流程编排
四、模型层冲突与拆分
模型层是系统的核心,它的设计直接影响整个系统的质量 。作为承接业务逻辑的核心,比较流程的实现策略包括:
  • DDD 领域驱动设计,其核心是使用面向对象的高级特性(封装、继承、多态、组合等)来进行设计,非常适合复杂的业务场景 。其体现就是存在很多高内聚低耦合的对象组(聚合根) , 业务逻辑由这些小对象相互协作共同完成;
  • 事务脚本 , 使用过程式思维,将数据操作编织到流程中,比较适合并不复杂的业务场景 。其体现就是存在很多“上帝 Service”,Service 中存在很多非常长的方法,业务逻辑由这些方法完成 。
关于哪个才是最优解,网上已经争论多年,最终也没有结论 。但我始终认为“没有业务场景就讨论方案,就是在耍流氓” 。
从不同应用场景出发便可得到如下结论:
  • Command 场景需要保障严谨的业务逻辑,通常复杂性偏高,所以DDD 是最优解
  • Query 场景需要更灵活的数据组装能力作为支持,通常比较简单 , 所以 事务脚本 是最优解
我经常说:“最简单的“写”也是复杂 , 最复杂的“读”也是简单”,其背后逻辑是基于对 Command 和 Query 的场景判断 。
将模型拆分为 Command 和 Query,具体如下:
DDD 与 CQRS 才是黄金组合

文章插图
完成模型拆分后,新模型具有以下特征:
  • Agg 也就是 DDD 中聚合根,主要用于处理复杂的 Command 逻辑,由具有大量业务操作的"富对象"构成;
  • View 是标准的 POJO , 主要充当 Query 结果对象,典型的“贫血对象”,仅作为数据的载体,根据展示需求对数据进行组装;
  • View 没有自己的 Repository , 只能依赖 CommandRepository 获取数据,Converter 组件负责将 Agg 模型转换为 View 模型 。
这块是拆分的重点,为了方便理解,简单举个例子:
比如在电商的订单模块:
  • 生单流程,由 Order 作为聚合根对内部 OrderItem 和 PayInfo 进行统一协调
  • 订单列表页 , 只需展示 Order 和 User 信息
  • 订单详情,需要展示Order、User、Address、OrderItem、PayInfo、Product等信息
如果让一个模型同时支持着三个场景,那模型自己就变得非常复杂,很难判断某个方法、某个字段究竟属于哪个场景 。
此时,应该根据场景对模型进行拆分:
  • OrderBO 以 DDD 方式进行建模 , 对外提供统一的业务操作,对内协调 OrderItem 和 PayInfo 等多个实体对象;
  • OrderListVO 以 POJO 方式进行建模,属性中包含 Order 和 User 信息;
  • OrderDetAIlVO 以 POJO 方式进行建模,属性中包括 Order、User、Address、OrderItem、PayInfo、Product 等信息;
三个模型相互独立 , 互不影响 。
当然,由于使用统一的 Repository 还需提供对应 VO 的 Converter:
  • OrderListVOConverter 将 OrderBO 转换为 OrderListVO 对象
  • OrderDetailVOConverter 将 OrderBO 转化为 OrderDetailVO 对象
五、仓库层冲突与拆分
仓库层拆分也是非常有必要的,在这一层主要有几项冲突:
DDD 与 CQRS 才是黄金组合

文章插图
仓库拆分后整体架构如下:


推荐阅读