Spec 驱动开发:AI 时代的需求工程
AI 能写代码后,程序员的瓶颈从"写"转移到"想清楚要什么"。Spec 驱动开发(先写规格再让 AI 实现)正是为此而生。本文讲清什么是 spec 驱动、spec 该写什么(需求/约束/验收/不要做的)、spec→plan→iterate 工作流,以及 spec 作为文档、测试、契约的多重价值。
本文要点
- 主题聚焦:AI、TypeScript
- 适合人群:独立开发者、全栈工程师、AI 应用开发者
- 核心价值:快速理解背景、实践路径、常见误区和工程建议
AI 能写代码之后,一件有意思的事发生了:"把需求变成代码"这件事变得几乎免费,但"想清楚需求到底是什么"反而成了最贵的环节。 你让 AI 写一个"用户上传头像"的功能,它能三分钟给你写完——但写出来的八成不是你想要的,因为你没说清大小限制、格式、失败重试、要不要裁剪。Spec 驱动开发(Spec-Driven Development)就是为这个时代生的需求工程。
一、瓶颈转移:写代码变便宜,想清楚变贵
传统软件工程,程序员的瓶颈是"实现"——你得亲手把逻辑翻译成代码,慢且累。需求想得糙一点,反正写的时候会边写边发现问题。
AI 编程改变了一件事:实现成本趋近于零。AI 一分钟能写 500 行,但如果你给的指令是"做个上传功能",它写出的 500 行大概率要返工——不是它能力不够,是你没告诉它边界。
于是瓶颈从"写"转移到了"想清楚要什么"。一个模糊的需求,过去会变成一个粗糙但能跑的实现;现在会变成一个精致但跑偏的实现。返工的代价没变,只是从"手写"变成了"重写一遍 + review"。
这就是 spec 重要性上升的根本原因:当实现便宜,规格就成了杠杆点。spec 清楚,AI 一次过;spec 模糊,来回拉扯。
二、什么是 Spec 驱动开发
Spec 驱动开发核心一句话:先写规格(spec),再实现。
这里的"spec"不是瀑布流时代那种几百页的需求文档,而是一份人和 AI 都能读懂、紧凑的需求描述——通常一两百行的 markdown,说清"要什么、约束、怎么算完、不要做什么"。写完 spec,人或 AI 都可以照着实现,并照着验收。
它和传统"需求文档"的区别在于密度和可执行性:不是写给评审委员会看的散文,而是写给执行者(AI 或人)的契约。它和"直接让 AI 写"的区别在于顺序:先把脑子里模糊的意图落到纸上,逼自己想清楚,再让 AI 实现。
一个判断标准:如果把你写下的 spec 交给一个完全不懂业务的人,他能照着验收吗? 能,spec 就及格了。
三、Spec 该写什么:四要素
一份合格的 spec,至少包含四块:
1. 要实现什么(What)。 功能的目标,用用户的语言描述,不要直接跳到实现方案。例:"支持用户上传头像,服务端裁剪为方形存储。"
2. 约束(Constraints)。 性能、兼容性、技术栈等硬约束——这是 AI 最需要的护栏。例:"图片 ≤ 5MB;支持 jpg/png/webp;裁剪用 sharp;Node 20。"
3. 验收标准(Acceptance)。 可验证、可勾选的清单,是 spec 和测试的桥梁。例:"上传超过 5MB 返回 413;非图片类型返回 415;成功返回裁剪后的 URL。"
4. 不要做的(Non-goals)。 明确划出边界,防止 AI 自由发挥。例:"不做客户端裁剪;不支持 gif 动图;不做多图批量。" 这条最容易被忽略,也最值钱。
下面是一个真实可用的 spec 模板,对应"头像上传"功能:
# Spec: 用户头像上传
## 目标
用户能上传一张图片作为头像,服务端裁剪为 256x256 方形存储。
## 约束
- 大小: ≤ 5MB
- 格式: jpg / png / webp
- 技术栈: Next.js Route Handler + sharp(Node 20)
- 存储: 写入 /avatars/<userId>.webp
- 性能: 单次处理 < 500ms(5MB 内)
## 验收标准
- [ ] 超过 5MB → 返回 413
- [ ] 非允许格式 → 返回 415
- [ ] 成功 → 200,返回 { url, width, height }
- [ ] 鉴权失败 → 401
- [ ] 同用户重复上传覆盖旧文件
## 不要做的(Non-goals)
- 不做客户端裁剪 UI
- 不支持 gif / 视频帧
- 不做上传进度条(本轮)
- 不接入对象存储(先用本地磁盘)
这份 spec 拿去给 AI,它几乎不会跑偏;拿去给一个新同事,他也能照着验收。
四、Spec → Plan → Iterate 工作流
写完 spec 不是直接"让 AI 一把梭",而是走一个稳定的三段式:
1. Spec(写规格)。 把上面四要素写清,存成 SPEC.md 放进任务目录,或直接贴进对话。
2. Plan(让 AI 先出计划)。 别让它上来就写代码。先喂 spec,问"你打算分几步实现、会动哪些文件、有哪些风险"。一份像样的 plan 能让你在动手前发现跑偏,比写完再推翻便宜得多。Claude Code 的 plan mode、Codex 的 plan 阶段都是干这个的。
3. Iterate(小步实现 + 按验收检查)。 按 plan 逐步推进,每一步对着 spec 的验收标准检查:跑测试、看 diff、确认过了再走下一步。
实际协作里,第一轮对话长这样:
# 给 AI 的指令(粘贴 SPEC.md 内容后)
这是头像上传的 spec。请先只产出实现 plan:
1. 列出要改/新增的文件
2. 每个步骤对应 spec 的哪条验收
3. 标出你认为有风险或需要我确认的点
先不要写实现代码,等我确认 plan。
这步把"AI 的自由发挥"关进笼子。确认 plan 后再让它实现,质量稳得多,返工也少。
五、Spec 的多重价值
一份好 spec,不只是写给 AI 看的,它同时是四样东西:
- 是文档。半年后回来看,比翻代码快十倍。新人 onboard 直接读 spec。
- 是 AI 的上下文。后续改动把 spec 喂进去,AI 立刻知道功能边界,不会去碰不该碰的地方。
- 是验收清单。验收标准直接可以转成测试用例,spec 和测试同源。
- 是团队契约。PM、前端、后端对一个功能的理解可能各歪 15 度,spec 是把大家对齐到同一基准。评审吵的不是"我觉得",而是"spec 怎么写的、要不要改 spec"。
一份 spec 同时服务四个用途,是它投入回报高的根本原因。 写一次,到处用。
六、怎么写好 Spec:正例 vs 反例
写好 spec 的要点:清晰、可验证、给例子、写边界。 反面教材最能说明问题。
反例(模糊 spec,必翻车):
做一个搜索功能,要快,支持模糊搜索,体验要好。
这条 spec 每个词都是雷:"搜索"搜什么?"快"是 50ms 还是 500ms?"模糊"是前缀、子串还是拼音?"体验好"是防抖、高亮还是联想?AI 照这个写,你会得到一个它"觉得好"的搜索——大概率不是你要的。
正例(同一功能,可执行的 spec):
# Spec: 文章标题搜索(suggest)
## 目标
输入框输入时,实时返回匹配的文章标题(最多 10 条)。
## 约束
- 数据源: 现有 articles 表(约 5 万行)
- 匹配: 前缀匹配(不区分大小写)
- 延迟: 输入后 300ms 防抖,接口 P95 < 100ms
- 前端: React,已有输入框组件
## 验收标准
- [ ] 输入 "next" 返回所有标题以 next 开头的文章
- [ ] 结果 ≤ 10 条,按更新时间倒序
- [ ] 空输入不请求
- [ ] 大小写不敏感: "Next" 和 "next" 结果一致
## 不要做的
- 不做全文搜索(本轮只搜标题)
- 不做拼音/分词
- 不做高亮(下轮)
差别一目了然:反例写的是感受,正例写的是可勾选的事实。 写 spec 的本质,就是把脑子里那些"大家都懂"的默认假设,一个一个揪出来写成字。揪不出来的那部分,就是日后返工的地方。
七、Spec 的粒度
spec 太大会失控,太小会碎片化。原则:按"可独立验收的单元"切。
- 一个 spec 对应一个可独立交付、可独立验收的功能切片。头像上传是一个 spec;头像上传 + 裁剪 UI + CDN 分发是三个。
- 太大(如"整个用户系统"):AI 在一个超大上下文里会迷失方向,验收也难一次性过。
- 太小(如"加一个字段"):spec 写作的开销超过收益,直接在对话里说清即可。
经验法则:一个 spec 的验收标准,通常 3-8 条。 多于 10 条说明该拆,少于 2 条说明可能不值得单独写 spec。
粒度对了,spec 才能既约束 AI、又不拖慢节奏。
小结
Spec 驱动开发是 AI 时代的需求工程:
- 瓶颈转移:写代码变便宜,"想清楚要什么"变贵,spec 是新的杠杆点。
- 四要素:要实现什么、约束、验收标准、不要做的——"不要做的"最值钱。
- 工作流:spec → 让 AI 先 plan → 小步 iterate,每步按验收检查。
- 一 spec 四用:文档、AI 上下文、验收清单、团队契约。
- 粒度:按可独立验收的单元切,验收 3-8 条为宜。
记住一句:AI 时代,能写代码的人不稀缺,稀缺的是能把需求想清楚的人——而 spec,就是"想清楚"这件事的产物。 你愿意在 spec 上多花半小时,AI 就能在实现上给你省下三小时的返工——这笔账,怎么算都赚。
Related