Spec Coding:AI 编程的正确打开方式
很多人用 AI 写代码,习惯一句话甩过去:"帮我做个登录页面。"然后等 AI 生成,不满意再改,改了又不对,最后越改越乱。
问题不在 AI,而在你没给它足够清晰的约束。
这篇文章讲一种更成熟的 AI 编程方式:先写 Spec,再让 AI 按 Spec 实现。
什么是 Spec
Spec 是 Specification(规格/规范)的缩写。在 AI 编程里,它是一份结构化的自然语言契约,用来告诉 AI:
- 这次到底要做什么
- 做成什么样才算对
- 哪些边界不能碰
- 最后怎么验证结果
Spec 不是灵感,不是随口一句需求,而是一份可执行的规范文档。
你可以把它理解为:
- 对产品需求的定义
- 对实现方式的约束
- 对结果质量的验收标准
- 对测试方式的明确说明
代码不再是凭感觉生成的东西,而是 Spec 的衍生结果。
Vibe Coding vs Spec Coding
Vibe Coding:凭感觉开发
用户:帮我做个登录页面
AI:(生成代码)
用户:不对,再改
AI:(改了但又引入新问题)
用户:越改越乱...特点:
- 上手快,适合小 demo
- 不稳定,每次产出不一样
- 难协作,难维护
- 容易越做越乱
Spec Coding:先写规范再实现
用户:(写好 Spec:需求、边界、验收标准)
AI:(按 Spec 生成代码)
用户:(按 Spec 验证,通过)特点:
- 稳定,有约束就可控
- 可复用,Spec 可以沉淀成模板
- 可协作,团队共享同一份规范
- 可验证,有明确的完成标准
类比:Vibe Coding 像即兴弹琴,Spec Coding 像先写好总谱,再让乐手按谱演奏。
一份好的 Spec 长什么样
很多人听到"规范文档"就觉得复杂。其实一份有用的 Spec 不一定很长,但一定要清晰。通常包含 6 个部分:
1. 需求目标:明确"要做什么"
不是只说"做个页面",而是说明:
- 解决什么问题
- 给谁用
- 触发场景是什么
- 最终希望达成什么结果
## 需求目标
为内部员工提供一个请假申请入口,支持:
- 按钮点击发起请假
- 选择请假类型(事假/病假/年假)
- 填写起止日期和事由
- 提交后进入审批流程2. 行为要求:明确"系统应该怎么做"
用结构化的方式描述:
- 在什么条件下
- 系统应该执行什么动作
- 出现异常时怎么处理
- 不允许发生什么情况
## 行为要求
- 用户点击"提交"按钮后,前端校验必填项
- 校验通过后调用 POST /api/leave/apply 接口
- 接口返回 200 时显示"提交成功"提示
- 接口返回 400 时显示具体错误信息
- 网络异常时显示"网络错误,请重试"
- 提交过程中按钮置灰,防止重复提交3. 验收标准:明确"做到什么程度才算完成"
这是最关键的部分,必须明确告诉 AI:
## 验收标准
- [ ] 选择请假类型后,日期选择器自动限制最长天数
- [ ] 起始日期不能晚于结束日期
- [ ] 事由为空时,提交按钮禁用
- [ ] 提交成功后,列表页自动刷新
- [ ] 连续点击提交按钮不会重复调用接口
- [ ] 所有表单字段有中文 placeholder
- [ ] 移动端适配,输入框不会被键盘遮挡4. 技术约束:明确"怎么做才不跑偏"
防止 AI "会做,但做法不符合你的体系":
## 技术约束
- 使用 Vue 3 Composition API + setup 语法糖
- 表单使用 uView 的 u-form 组件
- API 请求统一走 src/utils/request.js
- 日期处理使用 day.js
- 不引入新的 UI 框架
- 不使用 Options API5. 数据模型 / API / 边界条件
让 AI 少踩坑的关键区域:
## 数据模型
请假申请表单字段:
- type: string, 枚举 ["sick", "personal", "annual"], 必填
- startDate: string, ISO 格式, 必填
- endDate: string, ISO 格式, 必填, 必须 >= startDate
- reason: string, 最长 500 字, 必填
## 边界条件
- 年假剩余天数不足时,提示"年假余额不足"
- 起止日期跨月时,按自然月分别计算
- 同一天不能提交多条请假申请6. 测试策略:明确"怎么验证它真的符合 Spec"
## 测试策略
- 提交空表单,验证必填校验
- 提交合法数据,验证接口调用和成功提示
- 选择病假类型,验证日期限制
- 快速连续点击提交,验证防重复提交
- 断网状态下提交,验证错误提示Spec 工作流
一套成熟的 Spec 驱动开发流程:
┌─────────────┐
│ 1. 定义 Spec │ ← 先把目标、需求、边界、验收标准写清楚
└──────┬──────┘
↓
┌─────────────┐
│ 2. 制定 Plan │ ← 让 AI 基于 Spec 输出技术方案和任务拆分
└──────┬──────┘
↓
┌─────────────┐
│ 3. 按 Spec │ ← AI 按规范生成代码
│ 实现 │
└──────┬──────┘
↓
┌─────────────┐
│ 4. 按 Spec │ ← 对照验收标准逐项检查
│ 验证 │
└─────────────┘第一步:定义 Spec
先写清楚你要什么。如果脑子里只有一个粗糙想法,也可以先让 AI 帮你把想法扩写成更完整的规范草案。
第二步:制定 Plan
有了 Spec 之后,让 AI 基于 Spec 输出:
- 技术方案
- 模块拆解
- 实施顺序
- 风险点
- 任务清单
第三步:按 Spec 实现
AI 开始写代码。但这时它不是在"猜你的意思",而是在"执行一个已经约定好的规范"。
第四步:按 Spec 验证
对照验收标准逐项检查:
- 功能是否齐全
- 边界是否覆盖
- 测试是否通过
- 是否与技术约束一致
实际对比
不写 Spec
Prompt: "帮我做个用户列表页,支持分页和搜索"
结果:
- AI 用了 Options API(不符合项目规范)
- 搜索框没有防抖
- 分页组件样式和项目其他页面不一致
- 没有 loading 状态
- 没有空数据提示
- 没有错误处理写了 Spec
Prompt: "帮我做个用户列表页,要求:
- 使用 Composition API + setup 语法糖
- 搜索框使用 u-search 组件,300ms 防抖
- 分页使用 u-pagination 组件,样式和现有页面一致
- 加载中显示 u-loading
- 空数据显示 '暂无数据' 提示
- 接口异常显示错误提示并提供重试按钮
- 列表项包含:头像、姓名、手机号、部门、状态"
结果:
- 代码完全符合项目规范
- 交互体验完整
- 边界情况都处理了
- 可以直接提 PR什么时候写 Spec
| 场景 | 是否需要 Spec |
|---|---|
| 写一个小 demo | 不需要,Vibe Coding 就够了 |
| 原型验证想法 | 不需要,快速试错 |
| 正式项目开发 | 需要,稳定性很重要 |
| 团队协作 | 需要,统一标准 |
| 复杂功能 | 需要,防止遗漏边界 |
| 重复性任务 | 需要,沉淀成模板复用 |
实用建议
1. 别再只给一句模糊需求
至少补上:
- 目标用户是谁
- 主要流程是什么
- 成功标准是什么
- 哪些情况必须处理
- 哪些实现方式不能用
哪怕只多写 10 行,质量都会明显提升。
2. 把"验收标准"单独写出来
这是最值钱的动作。很多人写需求会写很多背景,但不写"什么叫完成"。一旦把验收标准写出来,AI 的方向会立刻稳定。
3. 把反复强调的约束沉淀成模板
如果你总要反复提醒 AI:
- 用某个技术栈
- 遵守某种目录结构
- 统一异常处理
- 不要引入新依赖
那说明这些内容应该固化成一份长期复用的 Spec 模板。
4. 复杂任务先让 AI 帮你补全 Spec
脑子里没想清楚时,最好的做法不是逼 AI 直接写代码,而是先让 AI 帮你一起把 Spec 补完整:
- 需求有没有漏洞
- 边界条件漏了没有
- 验收标准是否可测试
- 技术方案是否冲突
当 Spec 清楚了,后面实现会顺很多。
小结
- AI 写代码已经够强了,真正稀缺的是"约束能力"
- Spec 是给 AI 写的施工图 + 验收合同
- 核心六要素:需求目标、行为要求、验收标准、技术约束、边界条件、测试策略
- 工作流:定义 Spec → 制定 Plan → 按 Spec 实现 → 按 Spec 验证
- 未来最重要的编程能力,不只是 coding,而是 specification
参考来源: