规范驱动编程(Spec-Driven Development)
引言
在 AI 编程的时代,最大的挑战不是"AI 能不能写代码"——它显然可以。真正的挑战是:
如何确保 AI 写出的代码,是你真正想要的?
传统的做法是"边做边改":你描述需求,AI 生成代码,你发现不对,再修改描述,AI 再生成……这个循环可能重复十几次,最终你得到的代码勉强能用,但谁也不敢说它"正确"。
规范驱动编程(Spec-Driven Development, SDD) 正是为解决这个问题而生。它的核心理念只有一个:
与其在错误的方向上快速前进,不如花时间把方向写清楚。
一、从第一性原理思考
1.1 软件开发的本质是什么?
让我们回到最根本的问题:软件开发的本质是什么?
不是写代码。代码只是最终产物。软件开发的本质是:
将人类的意图,转化为机器可执行的指令。
这个转化过程有两个关键环节:
人类意图 → [需求理解] → 规范文档 → [代码生成] → 可执行程序
传统开发中,两个环节都由人类完成。AI 时代,第二个环节可以交给 AI。但第一个环节——从意图到规范——仍然是人类的核心价值。
1.2 Vibe Coding 的根本问题
Vibe Coding(凭感觉编程)跳过了第一个环节:
人类意图 → [直接跳过] → AI 猜测 → 代码 → 发现不对 → 重来
这就像你让一个非常能干的助手"帮我准备一个会议",但不告诉他是哪种会议、多少人、什么主题。他可能会准备一个完美的技术分享 PPT,但你需要的是一个客户提案。
Vibe Coding 的根本问题不是 AI 不够聪明,而是你没有把意图说清楚。
1.3 Spec Coding 的解法
Spec Coding 补上了缺失的环节:
人类意图 → [写规范] → 规范文档 → [AI 生成] → 代码 → 验证(对照规范)
关键变化:
- 规范成为"可执行的源代码"——AI 直接根据规范生成完整代码
- 维护软件 = 维护规范——改规范,代码自动重新生成
- 调试 = 修复规范——不是修代码,而是修规范中描述错误的部分
- 重构 = 重构规范——规范变了,代码跟着变
二、Vibe Coding vs Spec Coding
2.1 详细对比
| 维度 | Vibe Coding | Spec Coding |
|---|---|---|
| 定义 | 凭感觉/氛围编程 | 以规范文档驱动编程 |
| 输入 | 自然语言描述 | 结构化规范文档 |
| 输出质量 | 不可预测 | 可预测、可验证 |
| 适用场景 | 小玩具、原型验证 | 复杂业务、企业级、长期维护 |
| 团队协作 | 困难(谁知道"感觉"是什么?) | 自然(规范就是沟通语言) |
| 可追溯性 | 无(对话历史不可靠) | 完整(规范就是历史) |
| 维护成本 | 高(改代码 → 重新理解 → 改更多代码) | 低(改规范 → 代码自动重新生成) |
| 关系 | 过渡形态 | 最终形态(企业级范式) |
2.2 一个真实的例子
Vibe Coding 方式:
你:帮我做一个用户注册功能
AI:好的(生成了邮箱+密码注册)
你:要支持手机号注册
AI:好的(加了手机号,但邮箱注册的验证逻辑被改坏了)
你:邮箱验证怎么坏了?
AI:抱歉,让我修复(修复了邮箱,但手机号的短信发送又出问题了)
...
Spec Coding 方式:
## 用户注册功能规范
### 支持的注册方式
1. 邮箱注册:邮箱 + 密码 + 邮箱验证码
2. 手机号注册:手机号 + 短信验证码
### 验证规则
- 邮箱格式校验(RFC 5322)
- 密码强度:8位以上,含大小写和数字
- 验证码有效期:5 分钟
- 同一邮箱/手机号 1 分钟内只能发送 1 次验证码
### 接口定义
POST /api/auth/register
Body: { type: "email" | "phone", identifier: string, password: string, code: string }
Response: { code: 201, data: { userId: string, token: string } }
AI 一次性生成完整、正确的代码。没有来回修改。
三、Spec-Kit 工作流
Spec-Kit 是 GitHub 开源的规约编程工具,提供 8 个核心命令,形成完整的规范驱动工作流:
constitution → specify → clarify → plan → tasks → analyze → implement
↓ ↓ ↓ ↓ ↓ ↓ ↓
项目原则 → 功能规范 → 需求澄清 → 实现计划 → 任务分解 → 一致性审核 → 代码实现
3.1 Constitution(项目宪法)
项目宪法定义了整个项目的核心原则和约束。它是一切规范的"元规范"。
# 项目宪法
## 核心原则
1. 用户体验优先于技术实现
2. 安全性不可妥协(OWASP Top 10 全覆盖)
3. 代码可读性 > 性能优化(可读的慢代码 > 不可读的快代码)
## 技术约束
- 前端:React 18 + TypeScript + Tailwind CSS
- 后端:Node.js + Express + Prisma
- 数据库:PostgreSQL(主库)+ Redis(缓存)
- 部署:Docker + Kubernetes
## 编码规范
- 测试覆盖率 > 80%
- 所有 API 必须有 OpenAPI 文档
- 错误处理必须完善(不允许未捕获异常)
- 日志必须结构化(JSON 格式)
## 禁止事项
- 不使用 any 类型
- 不在组件中直接调用 API(使用 hooks/services 层)
- 不使用 console.log(使用 logger 服务)
- 不硬编码密钥(使用环境变量)
为什么需要项目宪法?
没有宪法,每个功能的规范可能相互矛盾。比如一个功能用 MongoDB,另一个用 PostgreSQL;一个用 RESTful,另一个用 GraphQL。项目宪法确保所有功能在统一的技术框架下工作。
3.2 Specify(功能规范)
为每个功能编写详细的规范文档:
# 用户认证模块 - 功能规范
## 背景
平台需要支持用户注册、登录、登出功能。当前无用户系统。
## 用户故事
- 作为新用户,我可以通过邮箱注册账号
- 作为新用户,我可以通过手机号注册账号
- 作为已注册用户,我可以通过邮箱+密码登录
- 作为已登录用户,我可以登出当前会话
## 技术要求
- 密码使用 bcrypt 加密(salt rounds: 12)
- 登录成功返回 JWT token(有效期 7 天)
- 注册需要验证码确认(邮箱/短信)
- 同一 IP 每小时最多注册 10 个账号(防刷)
## 接口定义
### POST /api/auth/register
请求:
{
"type": "email",
"identifier": "user@example.com",
"password": "SecurePass123",
"code": "123456"
}
成功响应(201):
{
"code": 201,
"data": { "userId": "uuid", "token": "jwt..." }
}
错误响应:
- 400: 参数缺失或格式错误
- 409: 邮箱/手机号已注册
- 429: 验证码发送过于频繁
## 验收标准
- [ ] 邮箱注册 → 收到验证码 → 输入验证码 → 注册成功
- [ ] 手机号注册 → 收到短信 → 输入验证码 → 注册成功
- [ ] 重复邮箱注册 → 返回 409
- [ ] 错误验证码 → 返回 400
- [ ] 密码强度不足 → 返回 400 + 具体提示
3.3 Clarify(需求澄清)
AI 会根据规范提出澄清问题:
AI: 关于验证码的重发机制,规范中提到"1分钟内只能发送1次",
但还需要确认:
1. 验证码重发次数限制:
A) 无限制(只要间隔1分钟)
B) 每天最多 10 次
C) 每小时最多 5 次
2. 验证码输入错误的处理:
A) 无限次尝试(直到过期)
B) 连续错误 5 次后锁定 15 分钟
C) 连续错误 3 次后作废,需要重新获取
3. 注册成功后的跳转:
A) 直接跳转到首页
B) 跳转到个人资料完善页
C) 跳转到登录页(需要重新登录)
为什么要这一步? 因为规范再详细,也不可能覆盖所有细节。AI 的澄清问题往往涉及你没考虑到的边界情况。
3.4 Plan(实现计划)
实现计划:
1. 数据模型设计(30分钟)
- 创建 User 模型(Prisma schema)
- 创建 VerificationCode 模型
- 运行数据库迁移
2. 验证码服务(45分钟)
- 邮件验证码生成与发送
- 短信验证码生成与发送(接入腾讯云 SMS)
- 验证码校验逻辑
3. 注册接口(30分钟)
- 参数校验
- 重复检查
- 密码加密
- 用户创建
4. 登录接口(20分钟)
- 邮箱+密码验证
- JWT token 生成
5. 登出接口(10分钟)
- Token 失效处理
6. 安全加固(20分钟)
- IP 限流
- 验证码错误次数限制
- 密码强度校验
7. 测试(45分钟)
- 单元测试
- 集成测试
- 边界情况测试
总计:约 3.5 小时
3.5 Tasks(任务分解)
Task 1: 创建 Prisma schema(User + VerificationCode)
依赖:无
预计:10 分钟
Task 2: 实现验证码服务(生成 + 发送 + 校验)
依赖:Task 1
预计:30 分钟
Task 3: 实现注册接口
依赖:Task 2
预计:20 分钟
Task 4: 实现登录接口
依赖:Task 1
预计:15 分钟
Task 5: 实现登出接口
依赖:Task 4
预计:10 分钟
Task 6: 安全加固(IP限流 + 错误次数限制)
依赖:Task 3, Task 4
预计:20 分钟
Task 7: 编写测试
依赖:Task 3, Task 4, Task 5
预计:30 分钟
3.6 Analyze(一致性审核)
AI 检查规范之间是否一致:
一致性审核结果:
✅ 注册接口与数据模型一致
✅ 密码加密方式与项目宪法一致(bcrypt)
⚠️ 警告:规范中提到"JWT 有效期 7 天",但项目宪法中建议"敏感操作需要二次验证"
→ 建议:登录后 7 天内可访问普通功能,但修改密码/绑定手机需要重新验证
✅ 所有接口都有错误码定义
✅ 验收标准覆盖了主要场景
⚠️ 警告:验收标准缺少"并发注册"场景
→ 建议:添加"同一邮箱并发注册只创建一个账号"的测试
3.7 Implement(代码实现)
AI 根据规范自动生成完整代码:
// src/modules/auth/register.ts
import bcrypt from 'bcrypt';
import { prisma } from '@/lib/prisma';
import { sendVerificationCode } from '@/services/verification';
import { ApiError } from '@/lib/errors';
export async function register(req: Request, res: Response) {
const { type, identifier, password, code } = req.body;
// 参数校验
if (!type || !identifier || !password || !code) {
throw new ApiError(400, '参数缺失:type, identifier, password, code 均为必填');
}
if (!['email', 'phone'].includes(type)) {
throw new ApiError(400, 'type 必须为 email 或 phone');
}
// 密码强度校验
if (password.length < 8 || !/[A-Z]/.test(password) || !/[a-z]/.test(password) || !/[0-9]/.test(password)) {
throw new ApiError(400, '密码必须8位以上,含大小写字母和数字');
}
// 验证码校验
const isValid = await verifyCode(identifier, code);
if (!isValid) {
throw new ApiError(400, '验证码错误或已过期');
}
// 重复检查
const existing = await prisma.user.findUnique({
where: type === 'email' ? { email: identifier } : { phone: identifier }
});
if (existing) {
throw new ApiError(409, type === 'email' ? '邮箱已注册' : '手机号已注册');
}
// 创建用户
const hashedPassword = await bcrypt.hash(password, 12);
const user = await prisma.user.create({
data: {
...(type === 'email' ? { email: identifier } : { phone: identifier }),
password: hashedPassword,
}
});
// 生成 token
const token = generateJwt({ userId: user.id });
return res.status(201).json({
code: 201,
data: { userId: user.id, token }
});
}
四、Vibe Coding → Spec Coding 的演进路径
4.1 四个阶段
阶段 1: 纯 Vibe Coding
"帮我做一个登录页面"
→ 适合:个人项目、原型验证
→ 问题:代码不可控、难以维护
阶段 2: 轻量 Spec
写 1-2 页的需求文档,AI 根据文档生成代码
→ 适合:小团队、MVP 阶段
→ 改进:有文档可追溯
阶段 3: 完整 Spec-Kit
Constitution → Specify → Clarify → Plan → Tasks → Analyze → Implement
→ 适合:正式项目、团队协作
→ 改进:全流程规范化
阶段 4: Spec as Code
规范文件纳入版本控制,修改规范 = 修改软件
→ 适合:企业级、长期维护
→ 改进:规范即代码,代码即规范
4.2 什么时候用什么方式?
| 场景 | 推荐方式 | 原因 |
|---|---|---|
| 学习新技术 | Vibe Coding | 快速试错,不需要规范 |
| 个人小工具 | 轻量 Spec | 有个文档记录就够了 |
| 团队项目 | 完整 Spec-Kit | 需要多人协作、代码审查 |
| 企业级系统 | Spec as Code | 长期维护、合规要求 |
| 生产环境修复 | Vibe Coding | 紧急修复,先解决问题 |
| 新功能开发 | 完整 Spec-Kit | 需要充分的需求分析 |
五、实战案例:从零到一的 Spec 驱动开发
5.1 场景:开发一个任务管理应用
第 1 步:写 Constitution(10分钟)
# 任务管理应用 - 项目宪法
## 核心原则
1. 简洁优先:功能不多但每个都好用
2. 离线可用:核心功能不依赖网络
3. 数据安全:任务数据本地加密存储
## 技术栈
- 前端:React + IndexedDB(离线存储)
- 后端:Supabase(同步服务)
- 部署:Vercel
第 2 步:写功能规范(20分钟)
# 任务创建功能规范
## 用户故事
- 作为用户,我可以快速创建任务(标题 + 描述)
- 作为用户,我可以为任务设置截止日期
- 作为用户,我可以为任务添加标签
## 验收标准
- [ ] 输入标题后按 Enter 即可创建
- [ ] 截止日期支持自然语言("明天"、"下周五")
- [ ] 标签支持自动补全
- [ ] 离线创建的任务在联网后自动同步
第 3 步:AI 澄清 → 确认 → 实现
AI 提问后确认方案,然后一次性生成完整代码。
结果:2 小时完成一个可工作的任务管理应用,代码质量远高于 Vibe Coding 的结果。
六、概念体系总结
规范驱动编程涉及的完整概念链:
Constitution(宪法)
↓ 定义原则
Specification(规范)
↓ 描述需求
Rules(规则)
↓ 约束行为
Skills(技能)
↓ 武装能力
Memory(记忆)
↓ 积累知识
Spec-Kit(工具链)
↓ 编排流程
Sub-agents(子代理)
↓ 并行执行
Hooks(钩子)
↓ 质量保障
| 概念 | 角色 | 类比 |
|---|---|---|
| Constitution | 项目宪法 | 国家宪法 |
| Specification | 功能规范 | 法律条文 |
| Rules | 约束行为 | 规章制度 |
| Skills | 武装能力 | 专业培训 |
| Memory | 积累知识 | 经验传承 |
| Spec-Kit | 编排流程 | 司法程序 |
| Sub-agents | 并行执行 | 专业部门 |
| Hooks | 质量保障 | 监察机构 |
七、常见陷阱与最佳实践
陷阱 1:过度设计
❌ 花 3 天写规范,然后用 1 小时写代码
✅ 花 1 小时写规范,然后用 3 小时写代码
规范的目的是提高效率,不是成为负担。
陷阱 2:规范不更新
❌ 规范写完就放着,代码改了规范没改
✅ 每次代码变更都同步更新规范
过时的规范比没有规范更危险。
陷阱 3:规范太模糊
❌ "系统要快" → 什么是快?1秒?100ms?
✅ "首屏加载时间 < 2 秒(Lighthouse 评分 > 90)"
规范必须是可验证的。
最佳实践 1:先写验收标准
## 验收标准
- [ ] 用户输入邮箱后,60秒内收到验证码
- [ ] 验证码输入正确后,跳转到首页
- [ ] 验证码输入错误 5 次后,锁定 15 分钟
验收标准是规范的灵魂——它定义了"什么算完成"。
最佳实践 2:用示例驱动规范
## 请求示例
curl -X POST /api/auth/register \
-H "Content-Type: application/json" \
-d '{"type":"email","identifier":"user@example.com","password":"SecurePass123","code":"123456"}'
## 成功响应示例
{"code":201,"data":{"userId":"abc-123","token":"eyJ..."}}
## 错误响应示例
{"code":409,"message":"邮箱已注册"}
示比文字描述更清晰。
八、动手实验
实验 1:用 Spec-Kit 流程开发一个功能
- 选择一个你想开发的功能(如"密码重置")
- 花 10 分钟写功能规范(用户故事 + 验收标准 + 接口定义)
- 让 AI 提出澄清问题并回答
- 让 AI 生成实现计划和任务分解
- 执行实现,验证是否符合规范
- 对比与直接 Vibe Coding 的差异
实验 2:为现有项目补充 Constitution
- 选择一个你正在开发的项目
- 写一份项目宪法(核心原则 + 技术约束 + 编码规范)
- 用这份宪法指导下一个功能的开发
- 观察 AI 的输出质量是否有提升
总结
规范驱动编程不是要增加你的工作量,而是要改变你的工作方式:
- 以前:你写代码,AI 帮你写代码
- 现在:你写规范,AI 根据规范写代码
你的核心价值从"写代码"变成了"写规范"——而这恰恰是人类最擅长的事情:理解需求、定义标准、做出决策。
记住:AI 可以写代码,但只有你能定义"什么是正确的代码"。这就是规范驱动编程的本质。