想用好 DDD 必须先过 Spring Data 这关

1. 面向对象设计是 DDD 的核心

DDD 着重于将业务领域中的概念和对象映射到对象中 , 使对象模型能够更好地反映业务的真实情况 , 从而使设计更具可理解性和可维护性 。
 
DDD 是一种领域驱动的设计方法 , 旨在通过建立对领域模型的清晰理解来解决业务问题 。和事务脚本不同 , DDD 使用面向对象设计来应对复杂的业务场景 。
简单来说 , DDD 是由领域对象承载业务逻辑 , 所有的业务操作均在模型对象上完成 , 同一对象上不同的业务操作构成了对象的生命周期 。
我们以订单为例 , 如下图所示:
想用好 DDD 必须先过 Spring Data 这关

文章插图
 
 
  1. 首先 , 用户操作下单 , 使用提交数据为其创建一个 Order 对象 , 版本 V1;
  2. 随后 , 用户进行改地址操作 , 调用 Order 对象的 modifyAddress 方法 , Order 从原来的 V1 变成 V2;
  3. 用户完成支付后 , 调用 Order 对象的 paySuccess 方法 , Order 从 V2 变成 V3;
 
从图上可见 , 在 DDD 设计中 , 所有的业务逻辑均由业务对象完成 , 所以面向对象是 DDD 设计的核心 。
2. 为什么需要 Repository?
假设 , 有一台非常牛逼的计算机 , 计算资源无限、内存大小无限、永不掉电、永不宕机 , 那最简单高效的方式便是将模型对象全部放在内存中 。
但 , 现实不存在这样的机器 , 我们不得不将内存对象写入磁盘 , 下次使用时 , 在将其从磁盘读入到内存 。
整体结构如下图所示:
想用好 DDD 必须先过 Spring Data 这关

文章插图
 
和上图相比 , 具有如下特点:
 
  1. 业务操作没变 , 仍旧依次完成 下单、改地址、支付等操作
  2. 引入持久化存储(MySQL) , 可以将 Order 对象存储于关系数据库
  3. 配合 Order 的生命周期 , 操作中增加 save、load 和 update 等操作
    1. 用户下单创建 Order 对象 , 通过 save 方法将 Order 对象持久化到 DB
    2. 接收到业务操作 , 需执行load , 从 DB 加载数据到内存 并对 Order 对象的状态进行恢复
    3. 在业务操作完成后 , 需执行update , 将 Order 对象的最新状态同步的 DB
 
相对全内存版本确实增加了不小的复杂性 , 为了更好的对这些复杂性进行管理 , 引入 Repository 模式 。
 
在领域驱动设计(DDD)中 , Repository 是一种设计模式 , 它是用来存储领域对象的容器 。它提供了一种统一的方式来查询和存储领域对象 。Repository提供了对底层数据存储的抽象 , 允许应用程序在没有直接与数据存储技术交互的情况下访问数据 , 同时该抽象允许在不修改应用程序代码的情况下更改数据存储技术 。
3. 什么才是好的 Repository ? 
好的 Repository 应该在满足业务需求的前提下 , 具备以下特性:
 
  1. 高内聚:好的 Repository 应该满足单一职责原则 , 每个 Repository 只关注一种领域对象的存储;
  2. 松耦合:好的 Repository 应该通过抽象接口与其他层进行交互 , 保证它们之间的耦合度低;
  3. 简单易用:好的 Repository 应该提供一组易于使用的方法 , 方便开发人员使用;
  4. 可维护性:好的 Repository 应该易于维护 , 维护人员不需要长时间阅读代码才能了解它的工作原理;
 
说的太官方了 , 用人话就是:
 
  1. 需要一个统一的 Repository 接口 , 用于对易用方法save、load、update进行管理
  2. 为每个聚合根创建一个 Repository 接口 , 继承自 统一Repository , 只关注该聚合根的存储
  3. Repository 的实现尽可能的简单 , 最好不用实现(人都是懒的)
4. 初始 Spring Data
Spring Data是一个框架 , 旨在简化数据访问层的开发 。它通过抽象和模板化方法 , 使得与各种数据存储(如关系型数据库 , 文档数据库 , 图形数据库 , 缓存等)的交互变得更加简单和标准化 。


推荐阅读