Spec 是源代码,代码是编译产物。意图永远先行。
一、核心叙事线
时代 0 古法时代:你和代码打交道
↓
时代 1 对话时代:你和 AI 打交道
↓
时代 2 Agent 时代:你和 AI 一起和代码打交道
↓
时代 3 SDD 时代:你和需求打交道,AI 替你和代码打交道
二、一句话定义
Spec 是源代码,代码是编译产物
| 概念 | 含义 |
|---|---|
| Spec | 描述系统"应该是什么"(what should be)= 意图 |
| Code | 描述系统"现在是什么"(what is)= 事实 |
过去的问题:AI 负责生产代码,但意图散落在聊天记录里,这才是根本问题。
三、传统开发 vs SDD
| 维度 | 传统开发 | SDD |
|---|---|---|
| 流程 | 需求 → 直接写代码 | 需求 → Spec → Plan → Tasks → Code |
| 意图存放 | 散落在聊天记录、口头沟通里 | 永远在 Spec 文件里,可追溯 |
| 需求变更 | 找代码猜逻辑,改一处漏一处 | 改 Spec → AI 重新生成,有据可查 |
| 多人协作 | 风格不统一,靠 CR 靠沟通 | 共享 Spec,风格天然一致 |
| 新人接手 | 读代码猜意图,至少一周 | 读 Spec,5 分钟上手 |
| 程序员角色 | 手工编码者 | 系统定义者 |
核心能力变化:写代码 → 定义约束 + 建模系统 + 控制演化
四、时代 2 遗留三大问题(为什么需要 SDD)
| 问题 | 具体表现 |
|---|---|
| Review 疲劳 | AI 写代码速度已超过人类 review 速度 |
| 意图丢失 | 需求藏在 Cursor Chat、Claude 对话、聊天记录里,不在 Git 里 |
| 一致性崩塌 | 同一需求,不同人问,不同实现,不同风格,系统开始熵增 |
五、面试话术:四个前端实战案例
案例 1 — 搜索组件开发
面试话术
"以前开发搜索组件,直接打开 IDE 开始写,遇到问题就问 AI,复制粘贴进来调。改成 SDD 后:先写 search.spec.md,定义 Props / 防抖时间 / 三种状态的 UI 行为 / 边界场景。Spec 写完喂给 Claude Code,组件一次生成,符合预期。三个月后再改需求,只改 Spec,意图不会丢。"
实操步骤
- 写
search.spec.md(Props / Emits / 状态机 / 边界场景) @search.spec.md喂给 AI → 生成组件- AI 读同一份 Spec → 生成单元测试
- 需求变更只改 Spec,再跑一次
Spec 示例
# search.spec.md
## Props
- modelValue: string — 当前搜索词(v-model)
- placeholder?: string — 默认"请输入关键词"
- debounce?: number — 防抖时间,默认 300ms
## Emits
- search(keyword: string) — 触发搜索
- clear() — 清空输入框
## 状态定义
| 状态 | 触发条件 | UI 表现 |
| ------- | ------------- | ---------------- |
| idle | 初始/清空后 | 显示 placeholder |
| loading | search 触发后 | 输入框右侧转圈 |
| empty | 返回结果为空 | 显示"暂无结果" |
| error | 接口报错 | 显示错误提示 |
## 边界场景
- 输入纯空格 → 不触发 search
- 连续输入期间只取最后一次(防抖)
案例 2 — API 接口字段变更
面试话术
"后端把 userName 拆成 firstName + lastName。传统做法全局搜索、一个个改、还怕漏。SDD 做法:先更新 user-api.spec.md,让 AI 重新读 Spec 生成 service 层。跑 tsc --noEmit,所有还在用旧字段的地方报类型错误,一个不漏。"
实操步骤
- 项目初期建
user-api.spec.md(接口路径 / 请求结构 / 响应结构 / 错误码) - 字段变更 → 先改 Spec(diff 清晰可见)
- AI 读新 Spec 重新生成 service 层 + TypeScript interface
tsc --noEmit→ 漏改的地方全部暴露
案例 3 — 多人协作大型表单
面试话术
"三个人分别写表单模块,最后风格不一:有人用 ElForm、有人手写校验。改成 SDD:先写共享 form.spec.md,校验时机 / 错误提示格式 / 提交规范全部定好。各自让 AI 读同一份 Spec 生成模块,风格天然一致。Code Review 对着 Spec 逐条验收,不靠个人风格争论。"
实操步骤
- 负责人写共享
form.spec.md(校验时机 / 错误格式 / 提交规范) - 各开发者补充自己模块字段 Spec,PR 合入后再写代码
- 各自让 AI 读同一份 Spec 生成模块 → 风格天然一致
- Code Review 标准:对着 Spec 逐条验收
案例 4 — AI 客服 Agent 系统(最有说服力)
面试话术
"做极速购 AI 客服系统时,早期 Agent 逻辑都在 Cursor 对话里迭代,意图散落在聊天记录里。改成 SDD:先写 agent-flow.spec.md,定义意图分类(查订单 / 退款 / 问产品)、每种意图对应哪个 Tool、失败时的 fallback 策略。这份 Spec 成为 Agent 的说明书,需求一变改 Spec 就行,AI 重新生成有理有据。"
实操步骤
- 写
agent-flow.spec.md(意图分类表 / Tool 路由 / fallback 策略 / Memory 轮次) - AI 读 Spec → 生成所有 Tool + Agent 骨架代码
- 新增功能 → Spec 加一行 → AI 生成新 Tool,自动接入路由
- Spec 即文档,直接发给后端 / 产品对齐
Spec 示例
# agent-flow.spec.md
## 意图分类与路由
| 用户意图 | 关键词示例 | 调用 Tool |
| ------------- | ------------------ | ----------------- |
| 查订单状态 | 我的订单、物流在哪 | queryOrderTool |
| 申请退款 | 退款、不想要了 | refundApplyTool |
| 商品咨询 | 这个多少钱、有没有 | productSearchTool |
| 闲聊/无法识别 | 其他 | fallbackTool |
## Fallback 策略
1. Tool 调用失败(网络/超时)→ 重试 1 次
2. 重试仍失败 → 回复"稍后再试",不暴露错误详情
3. 意图置信度 < 0.6 → 转人工客服
## Memory 设计
保留最近 6 轮对话作为上下文,避免用户重复说订单号
六、面试追问应答
| 追问 | 答法 |
|---|---|
| Spec 谁来写,写多细? | 负责人开工前写,细到能让 AI 直接生成可运行代码。不够细说明自己也没想清楚需求。 |
| Spec 和注释有什么区别? | 注释解释"怎么做",Spec 定义"应该做什么"。意图不能丢在代码里,代码随时会被重写。 |
| 实际团队推广难不难? | 难点在习惯不在技术。先在自己模块跑通,拿量化结果说话——接口改字段那次,传统方式半天,SDD 方式 10 分钟跑完 tsc 全部暴露。 |
| 和 TDD 什么关系? | TDD 是"先写测试再写代码",SDD 是"先写 Spec 再生成一切(含测试)"。SDD 包含 TDD 思想,粒度更粗,更适配 AI 时代。 |