Spec-Driven Development vs 传统 Prompt 工程:AI 编码的两种范式深度对比
如果你已经用 AI 编码工具(Claude Code、Cursor、Codex 等)写过一段时间的代码,应该遇到过这类场景:一句话描述需求,AI 瞬间给出几百行代码,看着没问题,跑起来却缺状态、缺边界、缺异常处理——测试才发现半个功能没实现。
这种”看起来对、用起来错”的体验,根源在于一个核心矛盾:人脑的模糊需求 → AI 的精确输出,中间缺了一个环节。
本文对比两种主流解决思路:传统 Prompt Engineering(堆 prompt 技巧)和 Spec-Driven Development(先写规格再写代码),用真实案例告诉你哪种更适合你的团队。
问题的本质:模糊输入与精确输出的鸿沟
先看一个典型场景。假设你在某 Claude Code 会话(或 Cursor 对话)中输入:
“给用户加个设置页面,能改邮箱”
这段话听起来很清晰,但对 AI 来说,它隐含了大量未定义的问题:
- 改邮箱要验证吗?旧的邮件要不要发确认?
- 改完后其他登录会话怎么处理?
- 新旧邮箱重复怎么办?
- 用户改到一半取消了,界面怎么回退?
传统做法是:AI 猜一个实现 → 你审阅发现不对 → 你加一句 prompt 修正 → AI 重新生成 → 循环。这就是Prompt Engineering 的迭代博弈模式。
Spec-Driven Development 换了一个思路:在写代码之前,先把规格写清楚。不是让 AI 猜,而是让 AI 先问你问题,你再确认,然后再写代码。
传统 Prompt Engineering 方式:灵活但脆弱
典型流程
# Prompt 工程风格:对话式迭代 # User: "写一个设置页面,用户能改邮箱" # Claude: 生成了一个完整的实现 # User: "没加验证码输入框" # Claude: 修改添加 # User: "邮箱改完后没发确认邮件" # Claude: 继续补
优点
- 启动快:一句话就能开始,适合探索性原型
- 灵活:随时可以根据中间结果调整方向
- 工具链零门槛:任何 AI 编码工具都支持
缺点
- 遗漏系统性:每次只能补一个坑,你不知道下一次 AI 会漏什么
- 上下文膨胀:修正 prompt 越多,对话越长,AI 反而容易迷失
- 状态难以复用:同一个需求换个人问,又要重新迭代
- 质量不稳定:同一个 prompt 在不同模型上的结果可能天差地别
适用场景
快速原型、一次性脚本、个人项目探索——你本人就在现场,可以即时发现问题并修正。
Spec-Driven Development 方式:严谨但高效
核心理念
SpecDD 提出了一个六阶段工作流:
Triage(分诊)→ Interview(访谈)→ Spec(规格)→ Plan(计划)→ Tasks(任务)→ Build & Verify(构建验证)
关键是 Interview 和 Spec 阶段写在代码之前。AI 不会直接写代码,而是先跟你确认规格。
典型流程
你用 Claude Code 安装 SpecDD 技能后,输入同样的需求:
You: "给用户加个设置页面,能改邮箱" SpecDD 不会直接写代码,而会问: - Q1: 修改邮箱后是否需要发送验证邮件确认新邮箱? - Q2: 原邮箱是否同样需要通知? - Q3: 用户在多个浏览器登录,改完后其他会话要登出吗? - Q4: 新邮箱重复时的错误提示是什么样的? - Q5: 修改成功后的预期状态是什么? 你确认后,SpecDD 才会: 1. 输出一份纯规格文档(不含技术细节) 2. 输出一份 2 分钟可读完的技术计划 3. 等你确认 → 生成可执行任务清单 4. 按清单逐项实现 5. 最后跑一次生产级检查清单
代码示例对比
传统 Prompt 方式(AI 一次生成):
# settings.py — AI 生成的第一版
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/settings/email', methods=['POST'])
def change_email():
new_email = request.json.get('email')
current_user.email = new_email # ❌ 没有验证
db.session.commit() # ❌ 没有空状态检查
return jsonify({"status": "ok"})
# ❌ 缺少: 新旧邮箱去重、验证邮件、会话登出、错误处理
SpecDD 方式(先确认规格再生成):
# 规格文档节选 # spec-email-change.md # 状态: email_change_form → validation_pending → confirmed → done # 边界: 空邮箱、重复邮箱、未验证、会话冲突 # 异常处理: 验证超时、邮件服务器不可达、用户关闭页面
# settings.py — SpecDD 在确认规格后生成
from flask import Flask, request, jsonify, session
from werkzeug.exceptions import BadRequest
@app.route('/settings/email/request', methods=['POST'])
def request_email_change():
"""Step 1: 请求修改,发送验证码到新邮箱"""
new_email = request.json.get('email', '').strip()
if not new_email:
raise BadRequest("邮箱不能为空")
if new_email == session['user']['email']:
raise BadRequest("新邮箱与当前邮箱相同")
if User.query.filter_by(email=new_email).first():
raise BadRequest("该邮箱已被其他账号使用")
# 发送验证码
send_verification_email(new_email)
return {"status": "verification_sent", "to": mask_email(new_email)}
@app.route('/settings/email/verify', methods=['POST'])
def confirm_email_change():
"""Step 2: 验证确认后执行修改"""
code = request.json.get('code', '')
if not verify_code(session['user']['id'], code):
raise BadRequest("验证码错误或已过期")
old_email = session['user']['email']
session['user']['email'] = request.json['pending_email']
invalidate_other_sessions(session['user']['id']) # 其他会话登出
notify_old_email_changed(old_email, session['user']['email'])
return {"status": "email_updated", "message": "邮箱已更新,其他设备已登出"}
看区别了吗?不是 AI 能力的问题——同样的模型,在 SpecDD 规格约束下,能一次性覆盖所有边界情况。
优点
- 系统性覆盖:Interview 阶段会穷举你遗漏的场景
- 质量可预期:规格确认后,代码质量是可预见的
- 可复用:同类型需求的 Interview 可以积累成模板
- 适合团队协作:规格文档是团队对齐的契约
缺点
- 启动成本:15 分钟以内的简单改动,走 Interview 流程显得过重
- 需要训练:团队需要适应”先写规格再写代码”的节奏
- 对工具要求高:需要 AI 编码工具支持技能/指令文件加载
适用场景
中大型功能、团队协作项目、需要长期维护的生产代码——规格文档本身就是一次性的知识沉淀。
关键指标对比
| 维度 | 传统 Prompt Engineering | Spec-Driven Development |
|---|---|---|
| 首次代码产出速度 | ⚡ 快(秒级) | 🐢 慢(需先确认规格) |
| 边界覆盖完整性 | ❌ 随缘(依赖 AI 模型) | ✅ 系统化(Interview 流程保障) |
| 调试迭代次数 | ❌ 高(每次发现一个漏项改一次) | ✅ 低(规格阶段已对齐) |
| 知识可复用性 | ❌ 低(每次重新引导) | ✅ 高(Interview 模板可积累) |
| 团队协作 | ❌ 差(每个人经验不同) | ✅ 好(规格文档是共同契约) |
| 长期维护友好度 | ❌ 差(对话上下文会丢) | ✅ 好(规格文件不依赖对话) |
实战建议:什么时候选择哪种
选传统 Prompt Engineering
- 写一次性脚本、原型验证、探索性项目
- 你一个人独立开发,对自己要什么很清楚
- 改动范围极小(5-10 行代码以内)
- 时间压力极大,启动速度优先
选 Spec-Driven Development
- 功能涉及多个文件、多个状态变更
- 需要多人协作,或需要交给另一个开发者 review
- 功能有明确的边界条件和异常处理需求
- 代码需要长期维护,日后要回顾设计意图
混合策略(推荐)
Quick 模式(< 15 分钟):直接写,不用全流程。SpecDD 的 Triage 阶段会自动判断这是”Quick”级别,只输出一个 5 行的内联 mini-spec。
Feature 模式(1-4 小时):走完整的 Interview → Spec → Plan → Build 流程。这是最常用的模式——花 3 分钟确认规格,省掉后续 30 分钟的调试。
Project 模式(多天):除了完整流程,还会生成可追踪的任务文件(tasks.md),每个任务有明确的 done-signal。
两个有趣的数据点
- 有人在 HN 上统计了 4 个主流 AI 编码工具(Claude Code、Cursor、Codex、Copilot)的 API 调用行为,发现平均每次对话会发送 3,177 次 API 调用——其中大量上下文都在反复补漏。SpecDD 的核心价值,就是在第一次调用前就把规格对齐。
- SpecDD 的实现本身就是一个 Claude Code Skill(SKILL.md),这个标准由 Anthropic 提出后,已经被 Cursor、Codex、Windsurf 等工具生态广泛采用。这意味着你写一个技能文件,可以跨工具使用。
总结
传统 Prompt Engineering 和 Spec-Driven Development 不是谁替代谁的关系——它们分别适合不同的粒度。
快速原型让 AI 自由发挥没有错,但当你要交付生产级代码时,花 3 分钟先确认规格,比花 30 分钟在 PR review 里发现漏项要划算得多。这其实是软件工程中的一条老经验搬到了 AI 时代:measure twice, cut once(量两次,裁一次)——只是现在”裁”的工作交给了 AI。
如果你是用 Claude Code 的开发者,安装 SpecDD 技能后试试下一个 feature 走一次完整流程。体验过”写完代码就过了所有边界检查”的流畅感,你可能就回不去了。