SDD + Harness 四周学习计划 · Week 1 · Day 3(认知打底第 3 课)
今日主题:spec 的七要素——背景、目标、用户故事、验收标准、非目标、边界条件、验证方式;全程对照「优化订单查询」正反例
建议用时:60–90 分钟 | 参考文章:Day 2 精读的《SDD 和 Harness》相关章节 + 各开源 spec 模板(见文末延伸阅读)
输出物:一张「七要素骨架卡」+ 用正反例方法挑出自己一句话需求里最容易写坏的 2–3 个要素——这是 Day 5 动手写 spec 的脚手架
0. 一句话剧透
Day 2 你学会了「spec 管做什么」。但「管做什么」得写成什么才算合格? Day 3 给的答案是:一份 spec 至少要回答七个问题——为什么做(背景)、要达成什么(目标)、给谁用、怎么用(用户故事)、做到什么程度算完(验收标准)、明确不做啥(非目标)、边界和意外怎么办(边界条件)、怎么证明做到了(验证方式)。
七个问题少了任何一个,AI 都会在你没写的地方替你猜——而它猜的方向,八成不是你想要的。今天学会用一个正例(合格 spec)和一个反例(你大概现在正在写的那种 spec)去对照,你一眼就能看出「AI 为什么老跑偏」其实有一半是 spec 自己写歪了。
1. 今日目标(学完你能做到)
- 能背出 spec 七要素,并用一句话说出每个要素回答哪个问题
- 能区分三对容易混的词:目标 vs 用户故事、验收标准 vs 验证方式、非目标 vs 边界条件
- 能从「优化订单查询」反例中,指出它至少踩了哪 4 个坑(含一条「伪验收」)
- 能说出 spec 写作的第一铁律:只写「做什么」,不写「怎么做」
- 能对着一个真实需求,快速判断它「哪个要素最缺」
目标对应计划「评估标准」第 1 条(七要素完整、验收标准可量化)的前半段。今天只要求能拆、能判;把它写成完整句子是 Day 5。
2. 学习动线(建议时间分配)
| 步骤 | 内容 | 用时 |
|---|---|---|
| 1 | 先看「3」:为什么 spec 是契约、不是作文 | 5 分钟 |
| 2 | 精读「4」:七要素逐个拆(每要素配好坏例句) | 25 分钟 |
| 3 | 精读「5」:「优化订单查询」反例 vs 正例全文对照 | 20 分钟 |
| 4 | 精读「6」:正反例逐条解剖 + 五条写作铁律 | 10 分钟 |
| 5 | 当日自测 + 打卡(填七要素骨架卡) | 10–15 分钟 |
今天信息密度高但都是「识别」型知识:目标是看完能判好坏,不是能默写定义。判得多了,Day 5 自然写得出来。
3. 先立个认知:spec 是「契约」,不是「作文」
先破除一个普遍误解:spec 不是给上级看的工作汇报,也不是给 AI 的「详细需求说明书」。它是一份人机之间的验收契约。
判断标准只有一句话:人和 AI 读了同一份 spec,对「什么叫完成」能得出完全一致的判断吗?
- 如果能——这份 spec 合格,因为它把「完成」钉死了,AI 无法在你看不见的地方「自由发挥」。
- 如果不能——它不合格。你写的不是 spec,是一段看起来像 spec 的模糊需求。AI 会用它的想象力填上你没写的空白,然后信誓旦旦地告诉你「做完了」。
这也解释了为什么七要素一个都不能少:每一个要素都是在堵一个 AI 会「自由发挥」的空白点。
| 你没写哪一要素 | AI 会替你猜什么 |
|---|---|
| 背景 | 猜「这个需求到底为什么存在、为谁服务」,可能做出方向相反的东西 |
| 目标 | 猜「做到什么程度算好」,做出「能跑但没达到目的」的东西 |
| 用户故事 | 猜「谁、在什么场景下怎么用」,交互和文案全凭想象 |
| 验收标准 | 猜「什么叫完成」,然后自己定义完成(这是最危险的) |
| 非目标 | 猜「顺手能多做点啥」,于是范围悄悄膨胀,还自认为贴心 |
| 边界条件 | 猜「异常和极限怎么办」,于是边界情况全裸奔 |
| 验证方式 | 猜「怎么证明做对了」,用「我觉得好了」代替客观证据 |
4. spec 七要素逐个拆
统一例句场景:优化订单查询——电商后台订单列表,数据量大了之后打开很慢。
4.1 背景(回答:为什么现在要做这个?)
作用:把「这个需求为了解决什么现状」讲清楚,让 AI(和未来的你)理解动机,而不是只看到一条指令。有了背景,AI 在遇到方案分叉时,能用「是否服务这个动机」来做取舍,而不是瞎撞。
1
2
3
4
5
6
写得好(反例——只有指令,没有动机):
「把订单查询优化一下,太慢了。」
写得好(正例——量化现状 + 点出代价):
「订单表已 3000 万行。后台『订单查询』页 P95 打开耗时约 2.1s,运营每次筛选要等 2 秒以上,
日均约 800 次查询,累计等待浪费约 0.5 人日/周,且高峰期偶发超时。需要把查询速度降下来。」
检验一句话:把背景删掉,读者还知道「为什么现在非做不可」吗? 正例里「2.1s、800 次/日、0.5 人日/周」就是非做不可的证据。
4.2 目标(回答:做成什么样,才算「值得做」?)
作用:给「完成」定一个可量化的方向性结果。目标不等于功能列表,它是结果(outcome),不是动作(output)。
1
2
3
4
5
6
写得好(反例——把「动作」当目标):
「目标:给订单查询加个 Redis 缓存、建几个索引、重构 Controller。」
写得好(正例——目标是最迟要达成的结果):
「目标:订单查询页 P95 从 2.1s 降至 ≤300ms;接口契约与返回字段保持完全不变;
现有功能(筛选/分页/导出)不回归。」
看出来了吗?反例写的是「怎么做」(Redis、索引、Controller)——那是 plan.md 的事,写进 spec 等于提前把方案焊死,既越权又挡路:万一更好的方案不是加缓存呢?正例只锁定结果(快、不变、不回归),方案留给 plan 阶段。
4.3 用户故事(回答:谁、在什么场景下、想干什么、图什么?)
作用:把「抽象的优化」翻译成具体的人 + 场景,让验收标准有「使用者视角」的落点。格式是经典三段式:
作为 [某种角色],我想要 [做某件事],以便 [获得某价值]。
1
2
3
4
订单查询的用户故事(示意,可多写几条):
- 作为运营,我想要按「下单时间 + 订单状态」组合筛选订单,以便快速定位某批订单。
- 作为客服,我想要查看单个大客户的近期全部订单,以便处理售后而不翻几十页。
- 作为运营,我想要导出筛选结果,以便做月度对账(导出量与筛选响应脱钩)。
反例是什么样?——没有用户故事,只有一句「订单查询要支持常见筛选」。于是 AI 不知道「常见」是给谁、什么时候算「够用」。每条用户故事最好能对应到至少一条验收标准,故事是「场景」,验收是「这个场景下的及格线」。
4.4 验收标准(回答:做到什么程度,这次就算「完成」了?)
作用:这是七要素里最核心的一个——它把「完成」从形容词变成可测试的条件。写法上尽量用 Given-When-Then(给定…当…则…)这类可观测句式。
1
2
3
4
5
6
7
8
9
写得好(反例——不可测的形容词):
「验收标准:订单查询要变得很快,体验要流畅,功能要正常。」
写得好(正例——每条都是可测条件):
- 前置条件:订单表 3000 万行、含 200 万笔待发货订单。
- AC-1 性能:Given 上述数据量,When 运营按「状态=待发货」查询并翻到第 20 页,Then P95 响应 ≤300ms。
- AC-2 契约:When 调用查询接口,Then 返回字段与响应结构改动前后完全一致(diff 为空)。
- AC-3 数据正确:When 用已知的 100 笔样本订单反复查询,Then 结果集与改动前逐条一致。
- AC-4 回归:When 执行既有订单模块回归用例(筛选/分页/导出),Then 全部通过。
检验一句话:这条验收标准能不能直接转成一条自动化测试? 不能,就说明它还是个形容词(快、流畅、正常),必须重写。形容词是验收标准的死敌。
4.5 非目标(回答:这次明确不做啥?)
作用:堵住范围蔓延(scope creep)。AI 天然有「顺手多做点」的倾向——你以为它贴心,其实是它在替你悄悄改契约。非目标就是在开工前把这些「顺手」全部钉死。
1
2
3
4
5
订单查询的非目标(示意):
- 不做订单数据的全文搜索(那是另一个需求)。
- 不新增/不修改任何对外接口签名(本次只允许内部优化)。
- 不做订单写入路径的任何改动(只动查询)。
- 不重构订单模块整体架构(仅针对慢查询这一条链路)。
注意「非目标」和「边界条件」的区别:非目标是「范围」——这次不做的事;边界条件是「极限/异常」——做了的事在极端情况下怎么办。 见 4.6 对照。
4.6 边界条件(回答:极端情况、异常、极限数据下怎么办?)
作用:显式声明错误与极限行为,防止 AI 做出与意图不符的假设。一句话版本:没有边界条件的 spec 只是一个愿望(a wish)。
1
2
3
4
5
6
订单查询的边界条件(示意):
- 数据规模边界:数据量再翻 10 倍(3 亿行)时,允许 P95 上升,但不得发生 OOM 或超时抛错。
- 空结果:筛选无匹配时,返回空列表 + 正常状态码(不许报错)。
- 超大结果集:单次「全量导出」命中超过 50 万行时,改为异步生成(本次先留接口位,不实现)。
- 超时/降级:缓存或索引不可用时,必须回退到可用路径并返回 5xx 明确的错误,不得静默返回脏数据。
- 并发:同一运营连续快速翻页时,不得出现顺序错乱或重复。
边界条件写得好不好,有个试金石:把它删掉,AI 会不会在「翻 10 倍数据」「空结果」「并发翻页」上自由发挥? 会——那就必须写。
4.7 验证方式(回答:用什么客观手段证明验收标准成立了?)
作用:很多模板把「验收标准」和「验证方式」混成一个。本计划把它们拆开,因为它们是两个不同的问题:验收标准 = 声明「应该怎样」;验证方式 = 声明「拿什么证据证明」。前者是契约,后者是取证手段。
1
2
3
4
5
6
订单查询的验证方式(示意):
- 性能:用与线上同构的压测脚本(注明机器规格与并发数),对比改动前/后 P95;基线数据存档可复现。
- 契约:对改动前后接口响应做结构化 diff,输出空 diff 报告。
- 正确性:跑样本订单断言脚本(100 笔已知结果),输出 100/100 通过。
- 回归:跑订单模块既有自动化用例集。
- 可观测:查询接口已埋 P95 指标,上线后 7 天在监控面板核对真实 P95,异常即回滚。
记忆:验收标准回答「好」的定义,验证方式回答「怎么证明好」。 写 spec 时先写验收标准,再问自己一句「这我能用脚本证明吗」——证明不了,通常是验收标准本身不够具体。
4.8 七要素速记表
| # | 要素 | 回答的问题 | 一句话试金石 |
|---|---|---|---|
| 1 | 背景 | 为什么现在做? | 删掉它,还有人知道非做不可吗? |
| 2 | 目标 | 做成什么样算值得? | 是「结果」还是「动作」?(后者是 plan 的事) |
| 3 | 用户故事 | 谁、何时、为何用? | 能对应到人 + 场景 + 价值吗? |
| 4 | 验收标准 | 做到什么程度算完成? | 能直接转成一条自动化测试吗?(形容词=死敌) |
| 5 | 非目标 | 这次明确不做啥? | 有没有把「顺手多做」钉死? |
| 6 | 边界条件 | 极端/异常/极限怎么办? | 删掉它,AI 会不会在这里自由发挥? |
| 7 | 验证方式 | 拿什么证据证明做到了? | 每条验收标准都有对应取证手段吗? |
5. 一镜到底:「优化订单查询」反例 vs 正例
下面是同一需求的两种 spec。先自己读,给反例挑毛病、给正例找亮点,再翻到第 6 节对照。
5.1 反例 spec(很像你现在会写的那种)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
## 需求:优化订单查询
### 目标
把订单查询做快,用户体验提升。
### 功能描述
- 订单查询现在太慢,要优化。
- 列表页要支持按状态筛选、按时间筛选、分页,导出也顺便优化下。
- 最好加缓存,建索引,重构一下 controller,代码写得干净点。
### 验收标准
1. 查询速度明显变快,用户觉得流畅。
2. 功能都正常,不能有 bug。
3. 代码质量要好,便于以后维护。
5.2 正例 spec(七要素齐全)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
## Spec:优化订单查询接口(后台列表页链路)
### 1. 背景
订单表已 3000 万行。后台订单查询页 P95 打开约 2.1s,日均 800 次筛选,
累计等待约 0.5 人日/周,高峰期偶发超时。业务上订单增速约 30%/年,不处理会继续恶化。
### 2. 目标
查询页 P95 从 2.1s 降至 ≤300ms;对外接口契约保持不变;订单模块既有功能零回归。
(本 spec 只锁定结果;技术方案在 plan.md 决定。)
### 3. 用户故事
- 作为运营,我想按「状态 + 下单时间」组合筛选,以便快速定位一批订单。
- 作为客服,我想查看单个客户近期全部订单,以便处理售后不翻几十页。
- 作为运营,我想导出筛选结果,以便对账(导出允许慢,但不能卡死页面)。
### 4. 验收标准
- AC-1(性能):前置数据 3000 万行 + 200 万笔待发货;按「状态=待发货」查第 20 页,P95 ≤300ms。
- AC-2(契约):接口返回字段与结构改动前后完全一致(diff 为空)。
- AC-3(正确性):100 笔已知样本订单反复查询,结果与改动前逐条一致。
- AC-4(回归):订单模块既有筛选/分页/导出用例全部通过。
### 5. 非目标
- 不做订单全文搜索;不新增/修改对外接口签名;不动写入路径;不重构整体架构。
### 6. 边界条件
- 数据量再翻 10 倍:允许 P95 上升,但不许 OOM / 静默超时。
- 空结果:返回空列表 + 200,不报错。
- 导出命中 >50 万行:本次仅预留异步占位,不实现。
- 缓存/索引不可用:必须回退并返回明确 5xx,不得返回脏数据。
- 并发快速翻页:顺序不得错乱、不得重复。
### 7. 验证方式
- 压测脚本(注明并发/机器规格)对比改动前后 P95,基线存档可复现。
- 接口响应结构化 diff 报告(空 diff 通过)。
- 100 笔样本断言脚本(100/100 通过)。
- 订单模块自动化回归集。
- 上线后监控真实 P95 7 天,异常即回滚。
6. 正反例解剖:反例到底踩了哪几个坑
| 反例的症状 | 缺了/坏了哪一要素 | 为什么 AI 会跑偏 |
|---|---|---|
| 「太慢、要优化」没给数据 | 缺背景 | AI 不知道「多慢算必须做」,无法判断优化是否值得 |
| 「做快、体验提升」 | 目标写成形容词,缺量化 | AI 自己定义「快 = 1s 内?」它猜什么就是什么 |
| 只有功能列表,没有用户 | 缺用户故事 | AI 不知道「筛选是给运营/客服的」,交互凭想象 |
| 「明显变快、功能正常、代码质量好」 | 伪验收(验收标准全是形容词) | 最致命:AI 宣布「完成」时你无法反驳——它说快了,你没有测量依据 |
| 「顺便优化导出、代码写干净点」 | 缺非目标 + 越权(说了怎么做) | 范围悄悄膨胀:导出、重构、整洁全被「顺手」卷进来 |
| 「加缓存、建索引、重构 controller」 | 把 HOW 写进 spec | 提前焊死方案:更好的方案被排除,且 plan 阶段没法改 |
| 全程没有异常/极限 | 缺边界条件 | 空结果、超时、并发翻页…… AI 全按最乐观假设处理 |
| 没有「怎么证明」 | 缺验证方式 | 验收标准即便写了也没配套取证,最后仍回到「人眼验收」 |
6.1 由此提炼的五条写作铁律(Day 5 直接照着写)
- 只写 WHAT,不写 HOW:Redis、索引、重构、Controller——这些词一出现就划掉。技术方案属于 plan.md。检验:换一个技术栈(Redis→别的缓存),spec 是否依然成立? 成立才合格。
- 验收标准必须可测:把「快、流畅、正常」翻译成 Given-When-Then + 数字。每条 AC 都能变成一条自动化测试。写不出测试的验收标准 = 伪验收。
- 目标写「结果」,用户故事写「场景」:结果是终点(P95 ≤300ms),场景是人(运营要按状态筛)。两者互补,别混成一个。
- 非目标至少写三条:范围蔓延是 AI 的默认倾向,非目标就是预先画好的「到此为止」线。凡是你心里想着「这个别顺手做了」的,都写进非目标。
- 先写验收标准,再问「我怎么证明」:证明不了,就回头把验收标准写得更具体。这条循环做完,spec 基本就合格了。
7. 当日自测
先合上讲义作答,再对照文末「参考答案」。
选择题(单选)
- 下列哪一句写进 spec 最合适?
- A. 「用 Redis 缓存 + 复合索引来优化订单查询」
- B. 「订单查询 P95 从 2.1s 降至 ≤300ms,接口契约保持不变」
- C. 「把 controller 代码重构得干净一点」
- D. 「先建个索引看看效果,不行再想别的办法」
- 「非目标」与「边界条件」的区别是?
- A. 两者相同,只是叫法不同
- B. 非目标 = 本次明确不做的范围;边界条件 = 做了的事在极端/异常情况下怎么办
- C. 非目标针对性能,边界条件针对功能
- D. 非目标是给 AI 看的,边界条件是给人看的
- 下列哪一条是「伪验收」(不可测的验收标准)?
- A. 「按状态=待发货查第 20 页,P95 ≤300ms」
- B. 「接口返回字段改动前后 diff 为空」
- C. 「查询速度明显变快,用户体验流畅」
- D. 「100 笔样本订单结果与改动前逐条一致」
- 「验收标准」与「验证方式」的正确关系是?
- A. 两者是一回事
- B. 验收标准 = 声称「应该怎样」的契约;验证方式 = 用什么客观证据证明该契约达成
- C. 验证方式应该在写代码之后才补
- D. 只有验收标准重要,验证方式可有可无
- spec 写作第一铁律是?
- A. 写得越长越详细越好
- B. 只写「做什么」,不写「怎么做」;技术方案留给 plan
- C. 把可能的实现方案都列出来供 AI 选择
- D. 用名词术语越多越专业
简答题
- 给出下面这句话需求的「缺口清单」:「把用户搜索也优化一下,支持模糊查询和分词,结果按热度排序。」——指出它缺了七要素里的哪些,各会造成什么后果。
- 为什么说「目标」写成了动作(如『给订单查询加缓存』)就等于把方案焊死了?请说明它同时侵犯了七要素中的哪两个要素。
8. 今日打卡输出
建议新开一个文件(同一目录,命名如 Day3-七要素骨架卡.md),做两件事:
- 填七要素骨架卡:拿一个你真实想做的微需求(哪怕一句话),按下面骨架填空,每个要素只写要点、不用写完整句:
1
2
3
4
5
6
7
8
# 七要素骨架卡(微需求:________)
背景:现状是… 代价是…
目标:做成…(量化:____→____)
用户故事:作为____,我想____,以便____
验收标准:AC-1(____,Given…When…Then…)
非目标:不做 / 不改 / 不重构…
边界条件:空 / 极限 / 超时 / 并发 时…
验证方式:____脚本 / diff / 回归 / 监控
- 标记「高危空白」:对照第 3 节表格,标出你这份骨架里最容易让 AI 猜的 2–3 个空(通常是最缺「非目标」「边界条件」)。Day 5 正式写 spec 时,优先把这些空补严。
这张骨架卡是 Day 5 实操与 Day 7 复盘的第二份素材,和 Day1/Day2 的草稿放一起。
9. 术语速查卡(Day 3 版)
| 术语 | 一句话解释 |
|---|---|
| spec | 结构化、可验收的规格文档,管「做什么」;人机之间的验收契约 |
| 背景 | 回答「为什么做」——用量化现状点出非做不可的动机 |
| 目标 | 回答「做成什么样算值得」——写结果(outcome),不写动作 |
| 用户故事 | 「作为[角色],我想[做啥],以便[图啥]」——把需求落到人+场景 |
| 验收标准 | 回答「做到什么程度算完成」——可测条件,多用 Given-When-Then |
| Given-When-Then | 验收句式:给定前置 → 当执行动作 → 则可观测结果 |
| 伪验收 | 由形容词写成的验收标准(快/流畅/正常),无法转成测试 |
| 非目标 | 本次明确不做的范围,用来钉死 AI「顺手多做」的默认倾向 |
| 边界条件 | 极限数据/空结果/超时/并发等异常情形下的明确行为 |
| 验证方式 | 证明验收标准成立的客观取证手段(脚本/diff/回归/监控) |
| 范围蔓延 | 需求在执行中悄悄扩大(AI 常「顺手多做」),靠非目标+边界拦截 |
| Out of scope | 非目标的英文说法,与 In scope(范围内)相对 |
10. 延伸阅读
今日精读(可选,模板对照)
- 计划主文件 Day 3 主题没有绑定单篇文章,但七要素可对照多个真实 spec 模板验证自己没跑偏:
- Microsoft Learn《Spec-Driven Development with GitHub Spec Kit》工作流章节(Given-When-Then 验收写法):https://learn.microsoft.com/zh-cn/training/modules/spec-driven-development-github-spec-kit-greenfield-intro/5-examine-spec-driven-development-workflow-phases
- SAE Framework 的 SDD Spec Template(含「edge cases are the spec」与「THE SYSTEM SHALL NOT…」禁止性句式):https://github.com/Passion4Architecture/sae-framework/wiki/SDD-Spec-Template
- openSDD 的 L1-FEATURE_SPEC 模板(Summary/Purpose/Out of scope/Edge cases 分组,与七要素同构):https://raw.githubusercontent.com/my-ai-test/openSDD/main/templates/spec/L1-FEATURE_SPEC.md
复习(把 Day 2 的闭环图接上)
- 资源 1《SDD 和 Harness:AI 编程的两大支柱》(CSDN)——重点回看「spec 管做什么」那一节,今天学的七要素就是「spec 管做什么」的可操作版本
- https://blog.csdn.net/qq_43284469/article/details/164267908
进阶(SDD 工程法实战,读它的「支付幂等」Spec 示例,看七要素如何落到真实业务)
- 《SDD 工程法实战:用 AI 按规格开发一个真实项目》(腾讯云):https://cloud.tencent.com.cn/developer/article/2731297
- 《三个月从多耗时 30% 到节省 40%:SDD 落地真正卡在哪里》(李福春,讲分级规格 L1/L2/L3):https://cloud.tencent.com.cn/developer/article/2731959
完整八条资源清单见计划主文件《SDD+Harness四周学习计划.md》。
附录 A:参考答案
选择题
- B —— A/C/D 都在写「怎么做」(技术方案/实现细节),属于 plan 阶段;B 只锁定可量化的结果与约束,是 spec 该写的。
- B —— 非目标管「范围」(这次不做什么),边界条件管「极限与异常」(做了的事在极端下怎么办)。A 混淆;C/D 都是编造的区分。
- C —— 「明显变快、流畅」是形容词,无法转成测试,是伪验收;A/B/D 都有可量化的断言方法。
- B —— 验收标准是「应该怎样」的契约,验证方式是「拿什么证据证明」。两者是声明与取证的关系,C/D 都错误地矮化了验证方式。
- B —— 只写 WHAT 不写 HOW 是第一铁律;「长」「多术语」都不是目标,列实现方案供 AI 选择恰恰是把 HOW 提前焊死。
简答题(要点,供自评)
- 缺「背景」(为什么现在做/数据现状?)「目标」(量化到什么程度算完成?)「验收标准」(模糊查询/分词的判定边界?热度排序的规则?),且「支持模糊和分词」容易滑向 HOW。后果:AI 自己定义「够快、够好」、把搜索范围与排序规则按想象实现,最后验收无从对质。
- 把「加缓存」写进目标,等于在 spec 层就把技术方案定为唯一解,plan 阶段无法再选更优方案——它侵犯了「目标(应写结果)」与「非目标/HOW 分离(实现手段应留给 plan)」两个要素。检验法:换一个技术栈 spec 若不再成立,就说明混入了 HOW。