2. 领域驱动设计基础:通用语言、限界上下文、实体与值对象、聚合与聚合根

在数据库迁移流水线架构设计中,领域驱动设计(DDD)提供了一套从业务逻辑出发、对抗复杂性的建模方法论。本章聚焦 DDD 的四个核心构造块:通用语言、限界上下文、实体与值对象、聚合与聚合根。这些概念是后续进行数据库迁移领域建模、定义接口契约的基石。

2.1 通用语言:团队沟通的契约

通用语言(Ubiquitous Language)是 DDD 的起点。它要求开发团队、领域专家、测试人员、运维人员使用同一套术语来描述业务规则和系统行为。在数据库迁移场景中,如果开发说“Schema 变更”,DBA 说“DDL 执行”,业务方说“表结构调整”,则沟通成本急剧上升。

实践要点:通用语言必须固化在代码、文档、测试用例和日常讨论中。例如,在迁移流水线中统一使用“变更单元(ChangeUnit)”而非“脚本”或“补丁”,确保每个角色理解一致。
角色 旧术语(歧义) 通用语言(统一)
开发工程师 改表脚本 变更单元(ChangeUnit)
DBA DDL 执行 变更单元执行(ChangeUnit Execution)
测试工程师 数据库补丁验证 变更单元验证(ChangeUnit Validation)
运维工程师 上线操作 变更单元部署(ChangeUnit Deployment)

2.2 限界上下文:划分模型边界

限界上下文(Bounded Context)定义了模型生效的边界。每个上下文内部有独立的通用语言和模型实现,上下文之间通过上下文映射进行集成。在数据库迁移流水线中,至少存在三个核心限界上下文:

  • 变更编排上下文:负责变更单元的顺序编排、依赖解析、执行计划生成。
  • 变更执行上下文:负责与目标数据库交互,执行 DDL/DML,记录执行状态。
  • 变更审计上下文:负责记录变更历史、审批流程、合规检查。
数据库迁移流水线 — 限界上下文划分 变更编排上下文 编排引擎 依赖解析器 执行计划生成 回滚策略 通用语言:变更单元、 执行计划、依赖图 变更执行上下文 连接管理器 DDL/DML 执行器 状态记录器 锁与并发控制 通用语言:连接、 执行状态、事务 变更审计上下文 审批工作流 变更历史仓库 合规检查器 通知服务 通用语言:审批单、 审计日志、合规 每个限界上下文拥有独立的通用语言和模型,通过上下文映射(如事件、RPC)集成

2.3 实体与值对象

实体(Entity)拥有唯一标识,其状态会随时间变化;值对象(Value Object)通过属性值定义自身,没有唯一标识,且不可变。在数据库迁移领域,区分两者至关重要:

概念 示例(数据库迁移) 特征
实体 ChangeUnit(变更单元) 有唯一 ID(如 CU-20250321-001),状态可变迁(待执行→执行中→成功/失败)
实体 ExecutionRecord(执行记录) 有唯一 ID,记录每次执行的时间、结果、日志
值对象 DatabaseConnection(数据库连接) 由 host、port、dbName、user 等属性构成,无独立 ID,替换即新建
值对象 ChangeScript(变更脚本内容) 纯文本内容 + 哈希校验,不可变,两个脚本内容相同则视为相等
建模原则:优先使用值对象描述属性、配置、度量等无生命周期概念;实体只用于需要跟踪身份和状态变化的业务对象。例如,SchemaName 是值对象,SchemaVersion 是实体。

2.4 聚合与聚合根

聚合(Aggregate)是一组相关对象的集合,外部只能通过聚合根(Aggregate Root)访问内部成员。聚合根是实体,负责维护聚合内部的不变规则。在数据库迁移流水线中,一个典型的聚合设计如下:

聚合示例:变更单元聚合(ChangeUnit Aggregate) 聚合根:ChangeUnit ID, 状态, 版本号, 依赖列表 实体:ExecutionRecord executionId, startTime, endTime, status, errorLog 值对象:ChangeScript content, checksum, language (SQL/NoSQL) 值对象:RollbackScript content, checksum, rollbackStrategy 聚合不变规则(Invariants) 1. 一个 ChangeUnit 只能关联一个 ChangeScript 和一个 RollbackScript 2. 状态变迁必须遵循:待执行 → 执行中 → 成功/失败 外部只能通过 ChangeUnit 聚合根访问内部实体和值对象,保证数据一致性

2.5 聚合设计原则与数据库迁移实践

在数据库迁移流水线中,聚合设计需要遵循以下原则:

  1. 聚合要小:一个聚合通常只包含一个聚合根和少量内部对象。例如,ChangeUnit 聚合只包含执行记录和脚本内容,不包含审批信息(审批信息属于审计上下文)。
  2. 通过聚合根访问:所有对聚合内部对象的修改必须通过聚合根的方法。例如,changeUnit.execute() 内部会创建 ExecutionRecord 并更新状态。
  3. 事务边界:一个事务只修改一个聚合。跨聚合的最终一致性通过领域事件实现。
常见误区:不要将整个数据库迁移流水线建模为一个巨大的聚合。例如,将“变更单元”、“执行记录”、“审批单”、“数据库连接”全部塞入一个聚合,会导致事务范围过大、并发冲突严重、性能急剧下降。正确的做法是每个限界上下文内设计 2-3 个小型聚合。

2.6 小结:DDD 构造块在迁移流水线中的映射

DDD 构造块 数据库迁移流水线映射 关键作用
通用语言 统一术语:变更单元、执行计划、依赖图、回滚策略 消除沟通歧义,对齐业务与技术
限界上下文 变更编排、变更执行、变更审计 划分模型边界,降低耦合
实体 ChangeUnit、ExecutionRecord、ApprovalOrder 跟踪身份和状态变化
值对象 ChangeScript、DatabaseConnection、SchemaName 描述属性,不可变,可共享
聚合 & 聚合根 ChangeUnit 聚合(根:ChangeUnit) 保证数据一致性和不变规则