DDD落地实践-战术实现心得

前言

战术设计要比战略设计好理解,而且粒度针对单个微服务/上下文。关键是对聚合、富血模型、仓储本质、事件的理解。这将是全新的编码风格。

共享大聚合包的落地方案

  • 大聚合包(共享jar)
    • 聚合包中包含所有业务对象、值对象、业务枚举、行为接口等,它们应该是具有合理行为的富血模型
    • 聚合包应该相对“纯粹”,没有杂的第三方依赖(lombok、hutool、校验注解等基本支持除外),以便被“纯净地”共享。
    • 推荐的工程和package结构
      • 工程:-aggr
      • 包名:com...aggr.
        • project是项目名,context是其他模块/微服务/上下文
        • context包下看复杂度决定是否继续分包,比如可以有bo(业务对象)、vo(界面对象)、ao(api响应对象)等子包、info(值对象)等
    • 不同聚合的业务实现交由其对应所属上下文工程实现
  • 上下文/微服务工程
    • 应用接口层 controller
    • 服务层 service
      • 应用/用例服务 applicationService/usecaseService
      • 领域服务 domainService - 看情况简化可省略
      • 其他服务
    • 仓储层 repo
      • 实体对象 eo/po
      • 仓储接口:getById,saveOrUpdate
    • 基础设施层 infrastructure
      • 对象转换器(比如eo->bo,bo->vo,bo->ao)、工具类、基础实现等
    • 事件和监听器 event/listener
      • 应用内事件在上下文工程中即可
      • 应用间事件建议放到共享大聚合
      • 监听器 XxxEventListener
    • 其他
  • 聚合的设计
    • 尽量采用小聚合,有可能一个聚合只有聚合根,大聚合不好维护
    • 聚合根应该是该业务用例中关键性的业务对象
  • 仓储设计
    • 某些信息如只用来进行页面展示,可以用值对象,一个json文本字段即可
    • 某些字段只进行页面展示但是会进行单个检索,可以单独看情况加字段
    • 状态等枚举字段建议直接“见名知意”,不要用0 1 2 3..查表时看不懂
    • 记住:仓储本质是高效存取数据,尽量不要附带业务逻辑痕迹到表设计里
    • 仓储设计应该ORM技术无关化,上层服务层不需要知道orm实现机制,其他层也是如此,面向接口编程
  • 应用/用例服务直面用户/客户/运营/系统用例,注重事务单元,且只关心输入输出
  • 什么时候需要加事件
    • 重要业务对象的关键“状态”发生变更时 - 里程碑事件
    • 上下文之间业务关联采用异步通信时
    • 上下文内降低复杂度、解耦、异步时
  • 聚合和仓储
    • 聚合和仓储独立设计
      • 聚合中不出现仓储相关行为
      • 用例服务等自行调用repo进行获取和更新
    • 聚合和仓储结合
      • 聚合有仓储行为,可提供抽象
      • 一般搭配buildBy静态方法(or lombok开放setter和chain,慎用)
      • getById,saveOrUpdate 为实例方法
      • 入参是repo

结语

  • 接近半年的DDD探索与实践告一段落
  • 成果
    • 理论消化
    • 实际工作中实践(大需求独立上下文)
    • 同行交流
    • 公司分享
  • 最后
    • DDD坑太多了,没有做好准备,不要轻易尝试
    • 理解业务很重要,技术是手段
    • DDD是解决复杂业务系统痛点的手段之一,不要为了DDD而DDD,具体问题具体分析
    • 自顶向下开发,面向抽象编程!

参考

posted @ 2021-09-17 15:11  summaster  阅读(316)  评论(0编辑  收藏  举报