Skip to content

设计文档编写规范

本文档定义 Pragmatic DDD 框架下需求 / 迭代设计文档的统一结构与写作约束,基于 订单发货与物流信息修正拆分设计 提炼。设计文档是「改代码之前必须产出的唯一输入」,面向人评审AI 落地两类读者。前置阅读:聚合业务规则(OrderRule 范式) · 应用层落地模式

1. 本质与定位

设计文档用于回答「这次要改什么、为什么这么改、按什么顺序改、改完怎么验证」。它在代码之前产出,是评审依据与实现输入。

  • 解决什么:需求未经分析就动手 → 只修表象;实现细节散落在对话里 → 无法评审、无法交接、无法复现。
  • 两类读者,两种刚性要求
读者需要什么文档必须提供
人(评审者 / 接手者)快速判断方案对不对、边界清不清结论先行、影响面、方案对比、风险清单
AI(执行者)不猜测地改出可编译代码确切文件路径、确切类名 / 常量名、可复制代码骨架、验收测试点

TIP

硬性流程约束:任何代码改动前必须先产出设计文档并确认。分析类请求(未要求输出文档)只输出分析,不改代码。

1.1 与相关文档的区别

文档类型回答什么稳定性位置
最佳实践(本目录其它篇)框架能力怎么用长期稳定,沉淀复用documentation/best-practices/
设计文档这次改什么一次性,随需求迭代docs/design/{模块}/
核心文档框架底层机制是什么随版本演进documentation/core/

设计文档不重复讲解框架机制,只给链接;它引用最佳实践,不替代最佳实践。

1.2 存放位置

范围路径
pragmatic-ddd-core 相关提案与重构计划docs/design/core/
示例工程与其它模块docs/design/{模块}/(如 docs/design/examples/

命名:{主题}-{动作}-design.md,如 order-ship-and-logistics-correction-design.md

2. 文档骨架(固定结构)

一份设计文档由 12 节组成,顺序固定。章节编号与标题名保持一致,便于跨文档定位与 AI 抽取。

#章节必选回答的问题
1背景与问题现在出了什么事 / 要做什么,影响面多大
2根因分析为什么会这样,分几层,本质是什么
3设计目标与原则要达成什么,依据什么原则
4方案(含对比 / 状态矩阵)有哪几种做法,选哪个,边界在哪
5详细设计(分层)每层改什么,代码长什么样
6规则校验设计视场景不变量怎么表达,读当前态还是旧快照
7并发与幂等视场景重复提交、并发提交怎么防
8审计与留痕视场景变更怎么追溯
9时序一次调用的完整执行路径
10改动清单与落地顺序改哪些文件,按什么顺序改
11测试清单怎么验证改对了
12风险与待确认事项有什么坑,什么没定

5 / 6 / 7 / 8 节是否必选取决于场景;1–4、9–12 恒必选。不适用时保留标题并写「本次不适用,原因:……」,不要直接删节——删节会让 AI 误判为遗漏。

3. 各节写作约束

3.1 结论先行(文档最顶部)

正文之前用引用块给出一句话结论,包含「选哪个方案」与「为什么」。评审者只看这一句就能判断方向对不对。

markdown
> 结论先行:**「发货」与「修正物流信息」必须拆成两个操作**
> 现状 `ship()` 一个方法同时承担「推进物流状态」与「录入物流信息」两个职责……

同时标注文档性质:> 本文只做设计,未改动任何代码。

3.2 根因分析:必须三层递进

这是设计文档最容易被跳过、也最有价值的一节。只写表象原因会导致「改了但没改对」。

层级问什么示例(发货重复执行)
直接原因哪行代码没拦住规则没校验 shipmentStatus 维度
深层原因为什么拦不住execute 先跑领域逻辑后校验,当前态已被改过
本质原因为什么会有这个设计两个职责耦合在一个方法上,需求互相冲突

写作要求:

  • 每层都贴真实代码并给文件行号,不写「某某方法有问题」这种无法定位的描述。
  • 引用代码用 \``行号:文件相对路径` 格式,可点击跳转。
  • 本质原因必须落到职责 / 边界 / 模型层面,而不是「忘了写判断」。

3.3 方案:给出允许矩阵而非大段描述

状态类需求用矩阵表表达「什么状态允许什么操作」,比文字严谨且不易遗漏组合:

旧状态操作 A操作 B
PENDING✅ 放行❌ 拒绝(还没发生,谈不上修正)

并显式写出边界澄清:哪些场景不属于本方案(如「发错货重发」属新业务动作,走售后,不是纠错)。明确「不做什么」和明确「做什么」同等重要。

3.4 详细设计:按层组织,代码骨架可直接用

领域层 → 应用层 → 接口层 → 基础设施层 四层展开,每层都要写,包括「零改动」的层:

写什么
领域层聚合方法、值对象、领域事件、规则容器、注册表
应用层Input、Updater、WriteService 入口
接口层HTTP 方法 / 路径 / Request、DTO 是否需改
基础设施层表结构、仓储、投影、Mapper——即使不动也要写「零改动,理由:……」

代码骨架约束(AI 落地质量的关键):

  • 必须是可直接编译的真实代码,含 import 所依赖的完整类名、真实构造签名。
  • 类注释写明「干什么」,作者统一 wizard-lee,不贴大段示例代码。
  • 涉及调用顺序的,在代码后补一段顺序约束说明并解释「为什么不能换」,例如:

previousLogisticsInfo 必须在赋值前暂存:先赋值则拿不到 before,先 collectEvent 则拿不到 after。

3.5 规则校验设计:明确读当前态还是旧快照

凡「判断状态是否被推进过」的规则,必须明确判定依据,这是本框架最高频的坑

判定场景读谁原因
字段值不变量(金额为正、客户非空)当前态与执行顺序无关
状态前置条件(仅待发货可发货、仅待支付可支付)旧快照 oldexecute 先跑领域逻辑,当前态已被改

必须写出激活条件(基于 hasOperation)与新旧读法的对应关系,见 聚合业务规则(OrderRule 范式)

3.6 改动清单:AI 的落地依据

用表格给出确切文件路径 + 动作 + 说明,三列缺一不可:

#文件动作说明
1domain/.../operation/OrderOperationRegistry.java新增 CORRECT_LOGISTICS
2domain/.../event/OrderLogisticsCorrectedEvent.java新增携带改前 / 改后 + 原因

再单独给落地顺序(通常 ≠ 章节顺序),保证每一步都可编译、可单测:

建议按 1→4→5→3→2→6→7→8→9→10 推进:先立规则与操作码,再改聚合,最后接应用层与接口层。

3.7 测试清单:编号 + 用例 + 期望

#用例期望
T2已发货订单再次发货(核心)拒绝,ORDER_SHIP_STATUS_INVALID,DB 不变、不发布事件
  • 期望里写确切的消息码常量名 / 状态枚举值,不写「报错」。
  • 标注哪几条是验收核心(如「T2 / T7 是本次验收核心」)。
  • 区分规则层单测与应用服务集成测。

3.8 风险与待确认事项

风险表要给触发条件与应对,而不只是列问题:

#事项说明建议
R1MyBatis 一级缓存可能让旧快照失效@Transactional 后同一 SqlSession 命中缓存,old == current配置 localCacheScope=STATEMENT 并加测试守住

顺带发现的同类缺口一律记入风险表并标注「不在本次范围」,用于另开文档——不在本次扩大改动范围

4. 完整模板

以下内容可直接复制为新文档的初始骨架:

markdown
# {需求主题}设计

> 结论先行:**{选哪个方案}**。{一句话理由}。
>
> 本文只做设计,未改动任何代码。

## 1. 背景与问题

### 1.1 现象

{当前表现,贴代码 + 行号}

### 1.2 影响面

| 影响 | 说明 |
| --- | --- |

## 2. 根因分析

### 2.1 直接原因:{一句话}

{代码 + 行号}

### 2.2 深层原因:{一句话}

{代码 + 行号}

### 2.3 本质原因:{一句话}

{职责 / 边界 / 模型层面的分析}

## 3. 设计目标与原则

| 目标 | 说明 |
| --- | --- |

## 4. 方案

### 4.1 {操作 / 概念}定义与边界

| 维度 | A | B |
| --- | --- | --- |

### 4.2 状态机与允许矩阵

| 旧状态 | 操作 A | 操作 B |
| --- | --- | --- |

### 4.3 事件与投影

| 事件 | 携带内容 | 订阅者 | 投影影响 |
| --- | --- | --- | --- |

## 5. 详细设计

### 5.1 领域层
### 5.2 应用层
### 5.3 接口层
### 5.4 基础设施层(零改动时写明理由)

## 6. 规则校验设计

### 6.1 旧快照机制的复用
### 6.2 规则清单(本次之后)

## 7. 并发与幂等

## 8. 审计与留痕

## 9. 时序

## 10. 改动清单与落地顺序

## 11. 测试清单

## 12. 风险与待确认事项

## 附:与既有文档的关系

5. AI 落地校验清单

设计文档写完后(或 AI 读取他人文档前),逐项自检。任一项不满足,文档不合格

#检查项不满足的后果
1顶部有结论先行块,含「选哪个 + 为什么」评审方向不明
2根因分析写了三层(直接 / 深层 / 本质)只修表象,同类缺陷复发
3所有代码引用带 文件相对路径 + 行号AI 无法定位,凭猜测改代码
4方案含允许矩阵或等价的穷举表遗漏状态组合
5明确写了「不做什么 / 不属于本方案」范围蔓延
6四层详细设计齐全,零改动层写明理由误判为遗漏而改错地方
7代码骨架可直接编译(真实类名与构造签名)编译失败,AI 反复试错
8状态前置类规则明确标注读旧快照规则写对但拦不住
9改动清单含确切文件路径 + 动作 + 说明AI 找不到文件
10给出落地顺序,且每步可编译中途编译失败堆积
11测试清单含确切消息码 / 枚举值,标出验收核心无法判断改对了没有
12风险含触发条件与应对,同类缺口标注「不在本次范围」踩坑且范围失控

6. 常见反模式

反模式问题正确做法
只有方案没有根因方案看着合理但可能没对症,同类缺陷反复出现必须写三层根因,本质原因落到职责 / 边界
根因只写「忘了加判断」无法沉淀,下次还忘追问到「为什么这个设计允许它被忘」
代码引用不带路径行号评审与 AI 都无法定位统一 \``行号:相对路径` 格式
只在正文里描述改动,无改动清单表AI 只能靠猜文件,易漏改 / 改错独立改动清单表 + 落地顺序
期望写成「报错 / 失败」无法断言,测试形同虚设写确切消息码常量名与状态枚举值
状态前置规则读当前态规则永远通过,缺陷依旧先跑领域逻辑后校验,前置判断必须读 old
基础设施层直接省略读者误判为遗漏,或真的漏掉建表 / 改投影保留标题写「零改动,理由:……」
顺带发现的缺陷顺手一起改范围蔓延,评审与回滚困难记入风险表,标注「不在本次范围,另开」
文档里重复讲解框架机制文档冗长,且与核心文档双份维护只给最佳实践 / 核心文档的链接

下一步