Spec模式开发

Spec模式开发

Posted by 十渊 on 2026-03-24

Spec 开发模式:完整技术指南

版本: 1.0
最后更新: 2026-03-24
适用对象: 软件工程师、技术负责人、AI 辅助开发实践者


目录


1. 引言

1.1 什么是 Spec 开发模式

Spec 开发模式(Specification-Driven Development) 是一种以"规格说明文档"(Spec)为核心驱动力的软件开发方法论。在这种模式下,开发者不再直接编写代码,而是首先撰写清晰、结构化、机器可读的 Spec 文件来描述"需要构建什么",然后由 AI 编程助手(如 GitHub Copilot、Cursor、Claude 等)根据 Spec 自动生成实现代码。

核心理念

1
人类负责定义 "What"(做什么) → AI 负责实现 "How"(怎么做)

Spec 开发模式代表了 AI 时代软件工程的一次范式转移——开发者的核心工作从"编写代码"转变为"编写精准的意图描述"。这不是简单地用自然语言 prompt 来驱动 AI,而是建立了一套系统化的规格描述框架,使 AI 能够准确理解需求并生成高质量的代码。

1.2 为什么需要 Spec 开发模式

传统开发面临的挑战

挑战 描述
需求失真 从需求文档到代码实现的过程中,信息逐层丢失和变形
上下文断裂 开发者在复杂系统中难以同时把握全局与细节
AI 输出不可控 直接与 AI 对话式编程,结果往往不稳定、不一致
知识流失 技术决策和设计意图分散在代码注释、聊天记录、脑海中
协作瓶颈 多人开发时,对"应该做什么"的理解常有偏差

Spec 开发模式的核心优势

  1. 意图的精确传达:Spec 文件作为"唯一事实来源"(Single Source of Truth),消除了需求传递过程中的信息损耗。
  2. AI 产出的一致性:结构化的 Spec 比自由格式的 prompt 能产生更稳定、更高质量的代码输出。
  3. 可追溯性:每一行代码都可以追溯到对应的 Spec 条目,建立了完整的需求-实现映射链。
  4. 可复用性:Spec 文件可以在不同项目、不同 AI 工具之间复用,不绑定特定技术栈。
  5. 协作效率:团队成员通过 Review Spec(而非 Review Code)就能对齐需求理解。
  6. 知识沉淀:Spec 文件自然形成了项目的活文档(Living Documentation)。

1.3 Spec 开发模式的演进历程

1
2
3
4
5
6
7
8
9
10
传统瀑布模型          敏捷开发              AI 辅助开发           Spec 驱动开发
(Waterfall) (Agile) (AI-Assisted) (Spec-Driven)
│ │ │ │
需求文档 → User Story → 自然语言 Prompt → 结构化 Spec
详细设计 → Task 拆分 → AI 生成代码 → Plan 生成 →
编码实现 编码实现 人工审查 AI 实现 →
自动验证
│ │ │ │
问题:周期长 改进:迭代快 问题:AI 输出 改进:精准控制
变更成本高 响应变化 不可控、不一致 结果一致可靠

Spec 开发模式并非完全取代之前的方法论,而是在 AI 能力成熟的背景下,对需求描述代码生成这两个环节的重新组织和优化。它吸收了:

  • 瀑布模型的严谨性(完整的前期规格定义)
  • 敏捷开发的迭代性(小步快跑、持续反馈)
  • AI 辅助开发的生产力(自动化代码生成)

2. 核心概念

2.1 Spec(规格说明)

Spec(Specification)是 Spec 开发模式中的核心产物。它是一份结构化的文档,精确描述了一个功能、模块或系统的行为、约束和验收标准。

Spec 的本质

Spec 不仅仅是"需求文档",它更像是人类与 AI 之间的合约(Contract)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
┌─────────────────────────────────────────────────┐
│ Spec 文件 │
│ │
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│ │ 目标描述 │ │ 行为定义 │ │ 约束条件 │ │
│ │ (What) │ │ (Behavior)│ │(Constraints│ │
│ └───────────┘ └───────────┘ └───────────┘ │
│ │
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│ │ 验收标准 │ │ 技术决策 │ │ 上下文 │ │
│ │(Criteria) │ │(Decisions)│ │ (Context) │ │
│ └───────────┘ └───────────┘ └───────────┘ │
│ │
└─────────────────────────────────────────────────┘

Spec 的三个层次

层次 名称 描述 示例
L1 系统级 Spec 描述整个系统或子系统的架构和行为 “用户认证系统 Spec”
L2 模块级 Spec 描述单个模块或功能的详细设计 “JWT Token 管理模块 Spec”
L3 任务级 Spec 描述一个具体的开发任务 “实现 Token 刷新接口 Spec”

2.2 Spec 驱动开发的核心原则

原则一:Spec First(规格先行)

在编写任何代码之前,必须先有对应的 Spec。

这不是教条式的流程约束,而是确保:

  • 你真正理解了要构建的东西
  • AI 有足够的上下文来生成正确的代码
  • 团队对交付物有共同的理解

原则二:Spec as Contract(规格即合约)

Spec 是人类与 AI 之间的正式合约。

  • 人类承诺:Spec 中描述的需求是准确和完整的
  • AI 承诺:生成的代码严格遵循 Spec 中的定义
  • 验证标准:代码是否满足 Spec 中的验收条件

原则三:Incremental Specification(增量式规格定义)

Spec 不需要一次性完美,可以逐步细化。

1
草稿 Spec(意图级)→ 详细 Spec(设计级)→ 精确 Spec(实现级)

这类似于敏捷开发中的"渐进式细化"(Progressive Elaboration),但应用于规格描述层面。

原则四:Verifiable Specification(可验证的规格)

每一条 Spec 都必须是可验证的。

  • 避免模糊性描述(“系统应该很快”)
  • 使用具体的量化指标(“API 响应时间 < 200ms”)
  • 定义明确的验收标准(Given-When-Then 格式)

原则五:Context is King(上下文为王)

Spec 必须包含足够的上下文,使 AI 无需猜测。

上下文包括:

  • 技术栈选择及原因
  • 已有代码的结构和约定
  • 外部依赖和集成要求
  • 非功能性需求(性能、安全、可用性)

2.3 角色模型

在 Spec 开发模式中,参与者分为以下角色:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
┌─────────────────────────────────────────────────────────┐
│ 人类角色 │
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Spec Author │ │ Spec │ │
│ │ (规格作者) │ │ Reviewer │ │
│ │ │ │ (规格审查者) │ │
│ │ 负责编写和 │ │ │ │
│ │ 维护 Spec │ │ 负责审查 │ │
│ └──────────────┘ │ Spec 质量 │ │
│ └──────────────┘ │
└─────────────────────────────────────────────────────────┘

Spec 文件(合约)

┌─────────────────────────────────────────────────────────┐
│ AI 角色 │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Planning │ │ Implement. │ │ Verification │ │
│ │ Agent │ │ Agent │ │ Agent │ │
│ │ (规划代理) │ │ (实现代理) │ │ (验证代理) │ │
│ │ │ │ │ │ │ │
│ │ 解读 Spec │ │ 根据 Plan │ │ 检查代码是否 │ │
│ │ 生成执行计划 │ │ 生成代码 │ │ 满足 Spec │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
角色 类型 职责 产出
Spec Author 人类 编写、维护 Spec 文件 Spec 文件
Spec Reviewer 人类 审查 Spec 的完整性和准确性 审查意见
Planning Agent AI 解读 Spec,生成可执行的实施计划 实施计划(Plan)
Implementation Agent AI 根据 Plan 逐步生成代码 源代码
Verification Agent AI 验证代码是否符合 Spec 的验收标准 验证报告

注意: 在实际使用中,这些 AI 角色可能由同一个 AI 工具扮演(如 GitHub Copilot Agent Mode),通过不同的 prompt 阶段来切换职能。

2.4 核心术语表

术语 英文 定义
Spec Specification 结构化的规格说明文档,描述需要构建的功能/系统
Spec 文件 Spec File 承载 Spec 内容的物理文件(通常为 .md 格式)
Plan Implementation Plan 由 AI 根据 Spec 生成的详细执行计划
验收标准 Acceptance Criteria Spec 中定义的、代码必须满足的条件
Spec Review Spec Review 对 Spec 文件进行审查的活动
上下文窗口 Context Window AI 模型单次处理的最大信息量
Spec 链 Spec Chain 多个相互关联的 Spec 之间的依赖关系
活文档 Living Documentation 随项目演进持续更新的文档
意图级描述 Intent-Level Description 描述"要做什么"而非"怎么做"的高层描述
渐进式细化 Progressive Elaboration 逐步深入和完善 Spec 的过程
单一事实来源 Single Source of Truth (SSOT) 某一信息只在一个地方权威定义
反馈循环 Feedback Loop 实现结果反馈给 Spec 进行修正的迭代过程
Spec 漂移 Spec Drift Spec 与实际代码逐渐不一致的现象
Token 预算 Token Budget 考虑 AI 上下文窗口限制时的内容规划策略

3. 工作流程详解

3.1 整体流程概览

Spec 开发模式遵循一个五阶段的闭环流程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
┌──────────────┐
1. 需求分析 │ ← 人类主导
│ 与拆解 │
└──────┬───────┘


┌──────────────┐
2. Spec 编写 │ ← 人类主导,AI 辅助
│ │
└──────┬───────┘


┌──────────────┐
3. Plan 生成 │ ← AI 主导,人类审查
│ │
└──────┬───────┘


┌──────────────┐
4. 代码实现 │ ← AI 主导,人类监督
│ │
└──────┬───────┘


┌──────────────┐ 不通过
5. 验证与 │ ──────────┐
│ 迭代 │ │
└──────┬───────┘ │
│ 通过 │
▼ ▼
┌──────────────┐ ┌──────────────┐
│ 交付完成 │ │ 反馈修正 │
│ │ │ (回到2/3/4) │
└──────────────┘ └──────────────┘

关键特征

  • 每个阶段都有明确的输入输出
  • 人类和 AI 有清晰的职责边界
  • 流程是可迭代的,验证不通过时回到相应阶段修正
  • 整个流程的核心驱动力是 Spec 文件

3.2 阶段一:需求分析与拆解

主导者: 人类 | AI 参与度: 低(可选辅助)

目标

将模糊的业务需求转化为可管理的、可描述的功能单元。

关键活动

  1. 理解业务目标:明确这个需求要解决什么业务问题
  2. 划定范围边界:确定做什么、不做什么
  3. 功能拆解:将大需求拆分为独立的功能模块
  4. 确定优先级:用 MoSCoW 或其他方法排列优先级
  5. 识别依赖关系:明确模块间的依赖和调用关系

拆解策略

1
2
3
4
5
6
7
8
9
大需求(Epic)
├── 功能模块 A(Feature)→ 对应 L1 系统级 Spec
│ ├── 子功能 A1 → 对应 L2 模块级 Spec
│ │ ├── 任务 A1-1 → 对应 L3 任务级 Spec
│ │ └── 任务 A1-2 → 对应 L3 任务级 Spec
│ └── 子功能 A2 → 对应 L2 模块级 Spec

└── 功能模块 B(Feature)→ 对应 L1 系统级 Spec
└── ...

拆解原则

原则 说明 示例
单一职责 每个功能单元只做一件事 ✅ “用户注册” ≠ ❌ “用户注册和登录”
独立可交付 每个单元可以单独完成和验证 ✅ “创建用户 API” 可以独立测试
适当粒度 不过大也不过小,1-3 天可完成 ❌ 太大:“整个认证系统” / ❌ 太小:“添加一行日志”
明确验证标准 能清晰判断"做完了没有" ✅ “API 返回 201 状态码和用户 ID”

输入与输出

内容
输入 业务需求文档、产品设计稿、用户故事、口头沟通
输出 功能拆解清单、优先级排列、依赖关系图、Spec 编写计划

3.3 阶段二:Spec 编写

主导者: 人类 | AI 参与度: 中(可协助生成初稿)

目标

为每个功能单元编写详细的、结构化的 Spec 文件。

关键活动

  1. 选择 Spec 模板:根据功能类型选择合适的模板
  2. 填写元信息:标题、作者、日期、状态、标签等
  3. 描述功能概述:用 1-3 段话说明这个功能是什么、为什么需要它
  4. 定义详细行为:描述系统在各种场景下的具体行为
  5. 列出技术约束:技术栈、性能要求、安全要求等
  6. 编写验收标准:用 Given-When-Then 格式定义验收条件
  7. 标注上下文信息:关联代码、外部依赖、设计决策说明

Spec 编写流程

1
2
3
4
5
6
7
8
9
10
11
12
13
第一遍:骨架(10分钟)
→ 填写标题、概述、核心目标
→ 列出主要功能点(bullet points)

第二遍:充实(20-30分钟)
→ 为每个功能点添加详细行为描述
→ 补充边界情况和异常处理
→ 添加技术约束和依赖

第三遍:锐化(10-15分钟)
→ 编写验收标准(Given-When-Then
→ 补充上下文引用
→ 自查:AI 能否仅凭这份 Spec 完成实现?

AI 辅助 Spec 编写

你可以让 AI 帮助你生成 Spec 初稿,然后人工审查和修正:

1
2
3
Prompt 示例:
"请为一个用户注册功能编写 Spec。技术栈是 Node.js + Express + PostgreSQL。
需要支持邮箱注册和手机号注册,密码需要加密存储,注册后发送验证邮件。"

⚠️ 重要: AI 生成的 Spec 初稿必须经过人工审查。AI 可能遗漏边界情况、做出不合理的技术假设,或者添加不必要的复杂度。

输入与输出

内容
输入 功能拆解清单、技术栈信息、已有代码结构、设计文档
输出 完整的 Spec 文件(.md 格式)

3.4 阶段三:Plan 生成

主导者: AI | AI 参与度: 高(人类审查后确认)

目标

AI 根据 Spec 生成详细的实施计划(Plan),明确实现的步骤、顺序和每一步的具体操作。

关键活动

  1. Spec 解析:AI 阅读并理解 Spec 的全部内容
  2. 代码库分析:AI 分析已有代码库,理解现有架构和约定
  3. Plan 生成:AI 生成分步实施计划
  4. 人类审查:开发者审查 Plan 的合理性
  5. Plan 确认/修正:必要时调整 Plan 后开始执行

Plan 的典型结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
## 实施计划

### 总览
- 涉及文件:5 个新建,3 个修改
- 预计步骤:12 步
- 关键依赖:Express router, bcrypt, PostgreSQL client

### 步骤详解

**Step 1: 创建数据库迁移文件**
- 文件:`migrations/001_create_users_table.sql`
- 操作:创建 users 表,包含 id, email, phone, password_hash, ...
- 依赖:无

**Step 2: 创建用户模型**
- 文件:`src/models/User.ts`
- 操作:定义 User 接口和数据库操作方法
- 依赖:Step 1

**Step 3: ...**

审查 Plan 的关键检查项

  • [ ] Plan 是否覆盖了 Spec 中的所有功能点?
  • [ ] 步骤的执行顺序是否合理?
  • [ ] 是否考虑了已有代码的架构约定?
  • [ ] 是否有不必要的过度设计?
  • [ ] 文件命名和目录结构是否符合项目规范?
  • [ ] 是否遗漏了错误处理和边界情况?

输入与输出

内容
输入 Spec 文件、项目代码库、技术栈配置
输出 结构化的实施计划(Plan)

3.5 阶段四:代码实现

主导者: AI | AI 参与度: 高(人类监督和微调)

目标

AI 按照 Plan 逐步生成代码,开发者实时监督并在必要时介入。

关键活动

  1. 逐步执行:AI 按 Plan 步骤依次生成代码
  2. 实时审查:开发者在每个关键步骤后审查生成的代码
  3. 及时纠正:发现偏差时立即反馈给 AI 进行修正
  4. 上下文维护:确保 AI 在多步骤执行中保持上下文一致性

实现策略

策略 A:全自动(适合简单任务)

1
2
3
让 AI 按 Plan 一口气完成所有步骤
→ 整体审查
→ 必要时调整

策略 B:分步执行(适合复杂任务,推荐)

1
2
3
4
AI 完成 Step 1 → 人类审查 → 确认/修正
AI 完成 Step 2 → 人类审查 → 确认/修正
...
AI 完成 Step N → 人类审查 → 确认/修正

策略 C:骨架优先(适合架构性任务)

1
2
3
4
第一轮:AI 生成所有文件的骨架(接口、类型、函数签名)
→ 人类审查整体架构
第二轮:AI 填充具体实现
→ 人类审查实现细节

实现过程中的关键注意事项

  1. 保持 Spec 可见:确保 AI 在实现过程中始终能引用 Spec 内容
  2. 警惕 AI 漂移:AI 可能在多步骤执行中逐渐偏离 Spec 的要求
  3. 及时保存上下文:对于长流程,定期总结已完成的工作
  4. 不要过度修改:避免在实现阶段引入 Spec 中没有定义的功能

输入与输出

内容
输入 Spec 文件、实施计划(Plan)、项目代码库
输出 源代码、配置文件、测试文件等

3.6 阶段五:验证与迭代

主导者: 人类 + AI 协同 | AI 参与度: 中高

目标

验证生成的代码是否满足 Spec 中定义的所有验收标准。

验证层次

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
┌─────────────────────────────────────────────┐
│ 验证金字塔 │
│ │
│ ╱╲ │
│ ╱ ╲ L4: 用户验收测试(UAT) │
│ ╱────╲ │
│ ╱ ╲ L3: Spec 合规性验证 │
│ ╱────────╲ │
│ ╱ ╲ L2: 集成测试 │
│ ╱────────────╲ │
│ ╱ ╲ L1: 单元测试 │
│ ╱────────────────╲ │
│ ╱ ╲ L0: 静态检查/类型检查 │
│ ╱────────────────────╲ │
│ │
└─────────────────────────────────────────────┘
层次 验证内容 工具/方式 责任人
L0 代码语法、类型正确性 Linter, TypeScript, Compiler AI 自动
L1 单个函数/方法的正确性 Jest, PyTest, JUnit 等 AI 生成 + 人类审查
L2 模块间交互的正确性 集成测试框架 AI + 人类
L3 代码是否满足 Spec 的每一条验收标准 逐条对照检查 人类主导
L4 功能是否满足业务需求 手动测试、演示 人类/产品团队

验证清单模板

1
2
3
4
5
6
7
8
9
10
11
## Spec 合规性验证清单

### Spec: [Spec 标题]
### 验证日期: YYYY-MM-DD

| # | 验收标准 | 状态 | 备注 |
|---|---------|------|------|
| AC-1 | 用户可以使用邮箱注册 | ✅ 通过 | |
| AC-2 | 密码必须加密存储 | ✅ 通过 | 使用 bcrypt, cost=12 |
| AC-3 | 注册后发送验证邮件 | ❌ 未通过 | 邮件模板未实现 |
| AC-4 | 重复邮箱注册返回 409 | ✅ 通过 | |

迭代反馈

验证未通过时,根据问题性质决定回退到哪个阶段:

问题性质 回退到 示例
代码 Bug 阶段四(代码实现) 逻辑错误、遗漏边界处理
Plan 不合理 阶段三(Plan 生成) 实现步骤遗漏、架构不合理
Spec 不完整 阶段二(Spec 编写) 缺少边界情况定义、需求变更
需求理解偏差 阶段一(需求分析) 整体方向错误

4. Spec 文件规范与编写指南

4.1 Spec 文件的标准结构

一份完整的 Spec 文件包含以下结构化组成部分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
---
# ===== YAML Frontmatter(元信息区)=====
title: "功能名称"
spec_id: "SPEC-2026-001"
version: "1.0"
status: "draft | in-review | approved | implemented | deprecated"
author: "作者姓名"
created: "2026-03-24"
updated: "2026-03-24"
tags: ["backend", "auth", "api"]
priority: "P0 | P1 | P2 | P3"
dependencies:
- "SPEC-2026-000"
---

# [功能名称] Spec

## 1. 概述(Overview)
简要说明该功能是什么、为什么需要构建它。
- 1-3 段话
- 包含业务背景和动机

## 2. 目标与非目标(Goals & Non-Goals)

### 目标
- 本次要实现的功能和效果

### 非目标
- 明确不在本次范围内的事项(防止范围蔓延)

## 3. 详细设计(Detailed Design)

### 3.1 功能描述
详细的功能行为描述。

### 3.2 数据模型
数据结构、数据库表设计等。

### 3.3 API 设计(如适用)
接口定义、请求/响应格式。

### 3.4 流程图
关键流程的文字或图形描述。

## 4. 技术约束(Technical Constraints)
- 技术栈要求
- 性能指标
- 安全要求
- 兼容性要求

## 5. 错误处理(Error Handling)
各种异常场景的处理策略。

## 6. 验收标准(Acceptance Criteria)
用 Given-When-Then 格式编写。

## 7. 上下文引用(Context References)
- 关联文件路径
- 依赖的外部服务
- 参考的设计文档

## 8. 开放问题(Open Questions)
尚未确定的事项和待讨论的问题。

## 9. 变更记录(Changelog)
| 日期 | 版本 | 变更说明 | 作者 |
|------|------|---------|------|

4.2 编写原则

原则一:SMART 验收标准

每条验收标准都应该满足 SMART 原则:

字母 含义 说明 ✅ 好的示例 ❌ 差的示例
S Specific(具体的) 明确指出要做什么 “API 返回 JSON 格式,包含 id 和 name 字段” “API 返回用户数据”
M Measurable(可衡量的) 有量化指标 “响应时间 < 200ms(P95)” “系统应该很快”
A Achievable(可实现的) 技术上可行 “支持单张最大 5MB 的图片上传” “支持任意大小的文件上传”
R Relevant(相关的) 与功能目标直接相关 “密码使用 bcrypt 加密存储” “使用最新版数据库”
T Time-bound(有时限的) 有明确的完成定义 “验证邮件在用户注册后 30 秒内发出” “尽快发送验证邮件”

原则二:Given-When-Then 行为描述

使用 Given-When-Then(GWT)格式描述系统行为,这是 BDD(行为驱动开发)的核心模式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
**AC-1: 正常邮箱注册**
- Given: 用户提供有效的邮箱地址和符合规则的密码
- When: 用户提交注册请求
- Then:
- 系统创建新用户记录
- 密码使用 bcrypt(cost=12)加密存储
- 返回 HTTP 201,响应体包含 { id, email, createdAt }
- 异步发送验证邮件到用户邮箱

**AC-2: 重复邮箱注册**
- Given: 数据库中已存在 email = "user@example.com" 的用户
- When: 用户使用 "user@example.com" 提交注册
- Then:
- 返回 HTTP 409 Conflict
- 响应体包含 { error: "Email already registered" }
- 不发送任何邮件

原则三:显式优于隐式

Spec 中不应有任何需要猜测的内容。 以下信息必须显式声明:

1
2
3
4
5
6
7
8
9
10
11
✅ 显式:
- 使用 PostgreSQL 15+ 作为数据库
- 使用 UUID v4 作为用户 ID
- 密码最少 8 个字符,必须包含大小写字母和数字
- 日期时间统一使用 ISO 8601 格式,UTC 时区

❌ 隐式(需要 AI 猜测):
- 使用合适的数据库 (哪个数据库?)
- 使用合理的 ID 方案 (自增?UUID?哪个版本?)
- 密码需要有足够的复杂度 (什么叫"足够"?)
- 日期格式要统一 (统一到什么格式?)

原则四:完整的边界定义

一份合格的 Spec 必须覆盖以下场景:

场景类型 说明 示例
正常路径(Happy Path) 一切正常的标准流程 用户成功注册
边界情况(Edge Cases) 极端输入和临界条件 邮箱长度恰好 254 个字符
异常路径(Error Path) 各种错误情况 数据库连接失败
并发场景(Concurrency) 多个请求同时到达 两个请求同时注册相同邮箱
安全场景(Security) 恶意输入和攻击向量 SQL 注入、XSS 尝试

原则五:上下文自包含

理想状态:一个从未接触过这个项目的 AI,仅凭 Spec 文件就能正确完成实现。

需要包含的上下文信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
## 上下文引用

### 技术栈
- 语言:TypeScript 5.x
- 运行时:Node.js 20 LTS
- 框架:Express 4.x
- 数据库:PostgreSQL 15
- ORM:Prisma 5.x

### 已有代码结构(关键引用)
- 路由定义:`src/routes/index.ts`(参照已有路由注册方式)
- 中间件:`src/middleware/auth.ts`(认证中间件)
- 错误处理:`src/utils/errors.ts`(统一错误处理类)
- 数据库连接:`src/db/prisma.ts`(Prisma client 实例)

### 编码约定
- 文件命名:kebab-case(如 `user-service.ts`
- 导出方式:named export(非 default export)
- 错误处理:使用自定义 AppError 类抛出
- 日志:使用 winston logger

4.3 好的 Spec vs 差的 Spec

❌ 差的 Spec 示例

1
2
3
4
5
6
7
8
9
10
11
12
# 用户注册

实现一个用户注册功能。

需求:
- 用户可以注册
- 需要验证邮箱
- 密码要加密
- 有错误处理

技术:
- 用 Node.js 写

问题分析

  • ❌ 没有元信息(作者、日期、版本、状态)
  • ❌ 没有明确的技术栈版本
  • ❌ "验证邮箱"含义模糊(格式验证?还是发送验证邮件?)
  • ❌ "密码要加密"没有指定算法和参数
  • ❌ "有错误处理"完全没有具体定义
  • ❌ 没有验收标准
  • ❌ 没有上下文引用
  • ❌ 没有边界情况定义

✅ 好的 Spec 示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
---
title: "用户邮箱注册"
spec_id: "SPEC-2026-012"
version: "1.2"
status: "approved"
author: "张三"
created: "2026-03-20"
updated: "2026-03-24"
tags: ["backend", "auth", "user", "api"]
priority: "P0"
dependencies: ["SPEC-2026-010"] # 邮件服务 Spec
---

# 用户邮箱注册 Spec

## 1. 概述

实现用户通过邮箱地址注册账号的功能。这是用户增长漏斗的第一步,
直接影响新用户获取。本功能仅覆盖邮箱注册路径,手机号注册见 SPEC-2026-013。

## 2. 目标与非目标

### 目标
- 用户可以使用有效邮箱地址和密码创建账号
- 注册后发送邮箱验证链接
- 防止重复注册
- 密码安全存储

### 非目标
- 第三方 OAuth 登录(见 SPEC-2026-015)
- 手机号注册(见 SPEC-2026-013)
- 用户个人资料填写(注册后独立流程)
- 邮箱验证链接的点击处理(见 SPEC-2026-014)

## 3. 详细设计

### 3.1 API 端点

**POST /api/v1/auth/register**

请求体:
```json
{
"email": "user@example.com",
"password": "SecurePass123",
"name": "张三"
}

成功响应(201 Created):

1
2
3
4
5
6
7
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "user@example.com",
"name": "张三",
"emailVerified": false,
"createdAt": "2026-03-24T10:30:00.000Z"
}

3.2 数据模型

1
2
3
4
5
6
7
8
9
10
11
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email VARCHAR(254) NOT NULL UNIQUE,
name VARCHAR(100) NOT NULL,
password_hash VARCHAR(60) NOT NULL, -- bcrypt hash
email_verified BOOLEAN DEFAULT FALSE,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE UNIQUE INDEX idx_users_email ON users(LOWER(email));

3.3 密码规则

  • 最少 8 个字符,最多 128 个字符
  • 必须包含至少 1 个大写字母、1 个小写字母、1 个数字
  • 使用 bcrypt 加密,cost factor = 12

3.4 邮箱验证规则

  • 遵循 RFC 5322 格式验证
  • 最大长度 254 个字符
  • 大小写不敏感(存储时转为小写)

4. 技术约束

  • 框架:Express 4.x + TypeScript
  • 数据库:PostgreSQL 15(已有 Prisma 配置)
  • 密码库:bcryptjs
  • 邮件队列:使用已有的 EmailServicesrc/services/email.ts
  • 参数验证:使用 zod schema

5. 错误处理

场景 HTTP 状态码 错误码 错误信息
邮箱格式无效 400 INVALID_EMAIL “Invalid email format”
密码不满足规则 400 WEAK_PASSWORD “Password does not meet requirements”
邮箱已注册 409 EMAIL_EXISTS “Email already registered”
name 为空 400 INVALID_NAME “Name is required”
服务器内部错误 500 INTERNAL_ERROR “An unexpected error occurred”

6. 验收标准

AC-1: 正常注册

  • Given: 数据库中不存在 email = "new@example.com" 的用户
  • When: POST /api/v1/auth/register { email: "new@example.com", password: “Abc12345”, name: “测试” }
  • Then: 返回 201,响应包含用户 ID 和 email,密码以 bcrypt 哈希存储,异步发送验证邮件

AC-2: 重复邮箱

AC-3: 弱密码

  • Given: 请求密码为 “123”
  • When: 提交注册
  • Then: 返回 400,错误码 WEAK_PASSWORD

AC-4: 邮箱大小写

AC-5: 并发注册

  • Given: 两个请求在同一时刻使用相同邮箱注册
  • When: 并发发送
  • Then: 只有一个成功(201),另一个返回 409(数据库唯一约束保证)

7. 上下文引用

  • 路由注册方式参照: src/routes/auth.ts
  • 错误处理规范参照: src/utils/errors.ts 中的 AppError 类
  • Prisma schema 位于: prisma/schema.prisma
  • 邮件服务: src/services/email.tssendVerificationEmail() 方法

8. 开放问题

  • [ ] 是否需要注册频率限制?(建议:同一 IP 每分钟最多 5 次)
  • [ ] 密码存储是否需要加 pepper?(本期暂不处理)

9. 变更记录

日期 版本 变更说明 作者
2026-03-20 1.0 初始版本 张三
2026-03-22 1.1 添加并发场景验收标准 李四
2026-03-24 1.2 补充邮箱大小写处理规则 张三
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

### 4.4 Spec 模板

以下提供三种常用的 Spec 模板,按场景选用:

#### 模板 A:API 端点 Spec 模板

```markdown
---
title: "[API名称]"
spec_id: "SPEC-YYYY-NNN"
version: "1.0"
status: "draft"
author: ""
created: "YYYY-MM-DD"
tags: ["api"]
priority: ""
---

# [API名称] Spec

## 1. 概述
[1-2 段话描述此 API 的用途和业务背景]

## 2. 目标与非目标
### 目标
- ...
### 非目标
- ...

## 3. API 设计

### 端点
**[METHOD] /api/v1/[path]**

### 请求
- Headers: [必要的请求头]
- Body:
```json
{}

响应

  • 成功 ([状态码]):
1
{}
  • 错误 ([状态码]):
1
{}

4. 数据模型

[表结构或数据结构定义]

5. 业务规则

  • 规则 1: …
  • 规则 2: …

6. 错误处理

场景 HTTP 状态码 错误码 错误信息

7. 验收标准

AC-1: …

  • Given: …
  • When: …
  • Then: …

8. 上下文引用

9. 开放问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

#### 模板 B:前端功能 Spec 模板

```markdown
---
title: "[功能名称]"
spec_id: "SPEC-YYYY-NNN"
version: "1.0"
status: "draft"
author: ""
created: "YYYY-MM-DD"
tags: ["frontend"]
priority: ""
---

# [功能名称] Spec

## 1. 概述
[功能描述和用户价值]

## 2. 用户场景
### 场景 1: [场景名称]
- 用户角色: [角色]
- 前置条件: [条件]
- 操作流程:
1. ...
2. ...
- 预期结果: ...

## 3. UI/UX 设计
### 3.1 页面结构
[描述组件层次和布局]

### 3.2 交互行为
- 点击 [元素]: [行为]
- 输入 [字段]: [验证规则]
- 滚动/拖拽: [行为]

### 3.3 状态管理
| 状态 | 触发条件 | UI 表现 |
|------|---------|--------|

### 3.4 响应式设计
- 桌面端(≥1024px): [布局]
- 平板端(768-1023px): [布局]
- 移动端(<768px): [布局]

## 4. API 集成
| 操作 | API 端点 | 触发时机 |
|------|---------|---------|

## 5. 错误与加载状态
- 加载中: [显示方式]
- 空状态: [显示方式]
- 错误状态: [显示方式和重试机制]

## 6. 验收标准
**AC-1: ...**
- Given: ...
- When: ...
- Then: ...

## 7. 上下文引用
- 设计稿: [链接]
- 组件库: [路径]
- 样式规范: [路径]

模板 C:系统重构 Spec 模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
---
title: "[重构名称]"
spec_id: "SPEC-YYYY-NNN"
version: "1.0"
status: "draft"
author: ""
created: "YYYY-MM-DD"
tags: ["refactor"]
priority: ""
---

# [重构名称] Spec

## 1. 概述
### 当前问题
[描述现有代码/架构的问题]

### 重构目标
[描述重构后期望达到的效果]

## 2. 影响范围
### 需要修改的文件
- `path/to/file1.ts` — [修改内容]
- `path/to/file2.ts` — [修改内容]

### 不应修改的文件
- `path/to/stable.ts` — [保持不变的原因]

## 3. 重构方案
### 3.1 Before(当前状态)

[当前的代码结构/调用关系]

1
2

### 3.2 After(目标状态)

[重构后的代码结构/调用关系]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

### 3.3 迁移策略
[渐进式迁移 or 一次性迁移,以及具体步骤]

## 4. 兼容性要求
- [ ] 所有现有测试必须通过
- [ ] API 对外接口不变
- [ ] 数据库 schema 不变
- [ ] [其他兼容性要求]

## 5. 风险评估
| 风险 | 概率 | 影响 | 缓解措施 |
|------|------|------|---------|

## 6. 验收标准
**AC-1: 功能不变**
- Given: 完成重构
- When: 运行所有现有测试
- Then: 全部通过,无新增失败

**AC-2: [性能/可读性/可维护性改进]**
- Given: ...
- When: ...
- Then: ...

## 7. 回滚方案
[如果重构出问题,如何回退]

5. 从零开始的实施步骤

本章以一个完整的端到端案例,手把手演示如何在一个全新项目中落地 Spec 开发模式。

5.1 项目初始化

Step 1:创建 Spec 目录结构

在项目根目录下创建 Spec 专用目录:

1
mkdir -p specs/{system,modules,tasks,templates,archive}

目录说明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
project-root/
├── specs/ # Spec 文件总目录
│ ├── system/ # L1 系统级 Spec
│ │ └── auth-system.md
│ ├── modules/ # L2 模块级 Spec
│ │ ├── user-registration.md
│ │ └── jwt-management.md
│ ├── tasks/ # L3 任务级 Spec
│ │ ├── register-api.md
│ │ └── token-refresh.md
│ ├── templates/ # Spec 模板
│ │ ├── api-spec.md
│ │ ├── frontend-spec.md
│ │ └── refactor-spec.md
│ └── archive/ # 已完成/废弃的 Spec
│ └── ...
├── src/ # 源代码目录
├── tests/ # 测试目录
└── docs/ # 其他文档

Step 2:创建 Spec 索引文件

specs/ 目录下创建索引文件,用于追踪所有 Spec 的状态:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!-- specs/INDEX.md -->
# Spec 索引

## 活跃 Spec

| Spec ID | 标题 | 级别 | 状态 | 优先级 | 负责人 | 链接 |
|---------|------|------|------|--------|--------|------|
| SPEC-001 | 认证系统架构 | L1 | approved | P0 | 张三 | [链接](system/auth-system.md) |
| SPEC-002 | 用户邮箱注册 | L2 | in-progress | P0 | 张三 | [链接](modules/user-registration.md) |
| SPEC-003 | Token 管理 | L2 | draft | P1 | 李四 | [链接](modules/jwt-management.md) |

## 已完成 Spec
| Spec ID | 标题 | 完成日期 | 链接 |
|---------|------|---------|------|

Step 3:配置 AI 工具的 Spec 感知

如果你使用 GitHub Copilot(Agent Mode),可在项目中添加指令文件:

1
2
3
4
5
6
7
8
9
10
<!-- .github/copilot-instructions.md -->
## Spec 开发模式

本项目使用 Spec 驱动开发。在编写或修改代码时:

1. 首先检查 `specs/` 目录下是否存在对应的 Spec 文件
2. 严格按照 Spec 中的定义实现
3. 不要添加 Spec 中未定义的功能
4. 遵循 Spec 中指定的技术约束和编码约定
5. 实现完成后,对照验收标准逐一验证

5.2 目录结构规范

Spec 文件命名规范

1
2
3
4
5
6
[层级标识]-[Spec编号]-[简短描述].md

示例:
L1-001-auth-system.md
L2-002-user-registration.md
L3-003-register-api-endpoint.md

替代命名方式(更简洁)

1
2
3
4
5
6
7
specs/
├── system/
│ └── auth-system.md # 层级由目录体现
├── modules/
│ └── user-registration.md
└── tasks/
└── register-api-endpoint.md

建议: 对于中小型项目,使用目录来区分层级更加简洁。对于大型项目,在文件名中包含 Spec ID 更便于检索。

Spec 状态流转

1
2
3
draft → in-review → approved → implementing → implemented → deprecated
│ │ │
└─────────┴───── (需要修改时回退) ←────────────────┘
状态 含义 可进行的操作
draft 草稿,正在编写 编辑、删除
in-review 等待审查 评论、批准、打回
approved 已批准,可以实现 开始实现
implementing 正在实现中 代码开发
implemented 已实现并验证通过 归档
deprecated 已废弃 移至 archive 目录

5.3 编写第一个 Spec

以下是一个完整的实操演练,展示如何为一个"待办事项 API"编写 Spec。

第一遍:搭建骨架(约 5 分钟)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
---
title: "待办事项 CRUD API"
spec_id: "SPEC-2026-001"
version: "1.0"
status: "draft"
author: "你的名字"
created: "2026-03-24"
tags: ["backend", "api", "todo"]
priority: "P0"
---

# 待办事项 CRUD API Spec

## 1. 概述
实现待办事项的增删改查 RESTful API。

## 2. 目标与非目标
### 目标
- 创建、读取、更新、删除待办事项
- 支持按状态筛选
- 支持分页

### 非目标
- 用户认证(本期不做)
- 标签系统
- 协作功能

## 3. 详细设计
[待填充]

## 4. 技术约束
[待填充]

## 5. 错误处理
[待填充]

## 6. 验收标准
[待填充]

第二遍:充实细节(约 20 分钟)

为每个 [待填充] 区域补充完整内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
## 3. 详细设计

### 3.1 API 端点

| 方法 | 路径 | 描述 |
|------|------|------|
| POST | /api/v1/todos | 创建待办事项 |
| GET | /api/v1/todos | 获取待办事项列表(支持筛选和分页) |
| GET | /api/v1/todos/:id | 获取单个待办事项 |
| PUT | /api/v1/todos/:id | 更新待办事项 |
| DELETE | /api/v1/todos/:id | 删除待办事项 |

### 3.2 数据模型

```sql
CREATE TABLE todos (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
title VARCHAR(200) NOT NULL,
description TEXT,
status VARCHAR(20) NOT NULL DEFAULT 'pending'
CHECK (status IN ('pending', 'in_progress', 'completed')),
due_date DATE,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);

3.3 请求与响应格式

创建待办事项 POST /api/v1/todos

请求体:

1
2
3
4
5
{
"title": "完成项目报告",
"description": "编写 Q1 项目总结报告",
"dueDate": "2026-04-01"
}

成功响应(201):

1
2
3
4
5
6
7
8
9
{
"id": "550e8400-...",
"title": "完成项目报告",
"description": "编写 Q1 项目总结报告",
"status": "pending",
"dueDate": "2026-04-01",
"createdAt": "2026-03-24T10:00:00.000Z",
"updatedAt": "2026-03-24T10:00:00.000Z"
}

获取列表 GET /api/v1/todos?status=pending&page=1&pageSize=20

成功响应(200):

1
2
3
4
5
6
7
8
9
{
"data": [...],
"pagination": {
"page": 1,
"pageSize": 20,
"total": 42,
"totalPages": 3
}
}

4. 技术约束

  • 语言:TypeScript
  • 框架:Express 4.x
  • 数据库:PostgreSQL 15
  • ORM:Prisma
  • 参数验证:zod
  • 分页默认值:page=1, pageSize=20, 最大 pageSize=100
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

#### 第三遍:锐化验收标准(约 10 分钟)

```markdown
## 6. 验收标准

**AC-1: 创建待办事项**
- Given: 请求体包含有效的 title
- When: POST /api/v1/todos
- Then: 返回 201,包含完整的 todo 对象,status 默认为 "pending"

**AC-2: title 为空时拒绝创建**
- Given: 请求体 title 为空字符串或未提供
- When: POST /api/v1/todos
- Then: 返回 400,error code: INVALID_TITLE

**AC-3: 按状态筛选**
- Given: 数据库中有 pending 和 completed 状态的待办
- When: GET /api/v1/todos?status=pending
- Then: 只返回 status = "pending" 的记录

**AC-4: 分页**
- Given: 数据库中有 25 条记录
- When: GET /api/v1/todos?page=2&pageSize=10
- Then: 返回第 11-20 条记录,pagination.total = 25, totalPages = 3

**AC-5: 更新不存在的记录**
- Given: 数据库中不存在 id = "nonexistent-uuid"
- When: PUT /api/v1/todos/nonexistent-uuid
- Then: 返回 404,error code: TODO_NOT_FOUND

**AC-6: 删除后确认**
- Given: 存在一个 id = "xxx" 的待办
- When: DELETE /api/v1/todos/xxx,然后 GET /api/v1/todos/xxx
- Then: DELETE 返回 204,GET 返回 404

5.4 从 Spec 到代码的完整流程

以下是拿着写好的 Spec 文件,与 AI 协同完成代码实现的完整操作流程:

Step 1:将 Spec 提交给 AI

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Prompt 模板:

请阅读以下 Spec 文件,为我生成实施计划(Plan)。

要求:
1. 列出需要创建/修改的所有文件
2. 每个文件需要实现的具体内容
3. 文件之间的依赖顺序
4. 预估每个步骤的复杂度(高/中/低)

Spec 文件内容:
[粘贴或引用 Spec 文件]

项目当前结构:
[提供关键的目录结构信息]

Step 2:审查 AI 生成的 Plan

收到 Plan 后,逐一检查:

1
2
3
4
5
6
7
8
## Plan 审查清单

- [ ] 所有 Spec 中定义的端点都已覆盖
- [ ] 文件命名符合项目约定
- [ ] 没有引入 Spec 中未要求的依赖
- [ ] 实现顺序合理(先模型 → 再服务 → 最后路由)
- [ ] 包含了错误处理和参数验证
- [ ] 测试文件包含在 Plan 中

Step 3:逐步执行 Plan

1
2
3
4
5
6
7
8
9
Prompt 模板(逐步执行):

请按照 Plan 的 Step [N] 执行:
[Plan 中 Step N 的内容]

请确保:
1. 严格遵循 Spec 中的定义
2. 保持与已有代码风格一致
3. 包含必要的错误处理

Step 4:代码审查与验收

每一步完成后,对照验收标准检查:

1
2
3
4
5
6
7
8
9
10
Prompt 模板(验证):

请对照以下验收标准,检查当前代码是否全部满足:

[列出相关的验收标准]

对于每一条标准,请说明:
1. 是否满足(✅/❌)
2. 满足的具体代码位置
3. 如果未满足,需要如何修改

5.5 迭代与反馈循环

场景一:验收标准未通过

1
2
3
4
5
6
流程:
1. 识别未通过的验收标准
2. 分析原因(代码 Bug?还是 Spec 遗漏?)
3. 如果是代码 Bug → 直接修复代码
4. 如果是 Spec 遗漏 → 先更新 Spec,再修复代码
5. 重新验证

场景二:实现过程中发现 Spec 不合理

1
2
3
4
5
6
7
8
流程:
1. 暂停代码实现
2. 记录发现的问题到 Spec 的"开放问题"中
3. 评估问题的影响范围
4. 如果是小问题 → 直接修正 Spec 并继续
5. 如果是大问题 → 与团队讨论后再修正
6. 更新 Spec 版本号和变更记录
7. 重新生成受影响步骤的 Plan

场景三:需求变更

1
2
3
4
5
6
7
8
9
流程:
1. 在 Spec 中标注变更的部分
2. 评估变更对已实现代码的影响
3. 更新 Spec 的"目标与非目标"部分
4. 更新受影响的验收标准
5. 更新 Spec 版本号(如 1.0 → 1.1)
6. 重新生成 Plan 中受影响的步骤
7. 实现变更
8. 重新验证所有验收标准(包括未变更的部分)

反馈循环的可视化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  Spec v1.0                    代码 v1
┌──────────┐ ┌──────────┐
│ │───── Plan ────▶│ │
│ │ │ │
│ │◀── 发现问题 ──│ │
└──────────┘ └──────────┘
│ │
更新 Spec 修复代码
│ │
▼ ▼
Spec v1.1 代码 v2
┌──────────┐ ┌──────────┐
│ │───── Plan ────▶│ │
│ │ │ │
│ │◀── 验证通过 ──│ │
└──────────┘ └──────────┘
│ │
归档 部署

6. 最佳实践

6.1 Spec 粒度控制

Spec 的粒度直接决定了开发效率和 AI 产出质量。粒度过粗,AI 缺少细节无法精确实现;粒度过细,写 Spec 的成本超过直接编码。

粒度评估矩阵

实现复杂度低 实现复杂度高
业务规则简单 L3 任务级即可(简要描述) L2 模块级(注重技术设计)
业务规则复杂 L2 模块级(注重业务规则) L1+L2 组合(系统级+模块级)

粒度的"金发女孩原则"

1
2
3
4
5
6
7
8
9
太粗 ────────────── 恰当 ────────────── 太细

"实现用户系统" "实现用户邮箱注册 "实现邮箱正则
API,包含密码加密、 验证函数,接受
邮箱验证、重复检测" string 参数,
返回 boolean"

AI 需要猜测太多 AI 有足够信息 不如直接写代码
实现细节 精确实现

粒度控制的经验法则

  1. 一个 Spec 对应 1-3 天的开发工作量
  2. 一个 Spec 产生的代码不超过 500 行(超过则考虑拆分)
  3. 一个 Spec 涉及的文件不超过 10 个
  4. 验收标准在 3-10 条之间(少于 3 条可能太粗,超过 10 条考虑拆分)

6.2 上下文管理策略

AI 模型的上下文窗口是有限的。即便是最新的模型,高效地管理上下文依然至关重要。

上下文分层策略

1
2
3
4
5
6
7
8
9
10
11
12
13
┌─────────────────────────────────────────────┐
│ 第 1 层:当前 Spec │ ← 必须完整包含
│ (完整的 Spec 文件内容) │
├─────────────────────────────────────────────┤
│ 第 2 层:直接上下文 │ ← 根据需要引入
│ (Spec 引用的代码文件、类型定义) │
├─────────────────────────────────────────────┤
│ 第 3 层:间接上下文 │ ← 按需提供摘要
│ (项目约定、架构文档、依赖 Spec) │
├─────────────────────────────────────────────┤
│ 第 4 层:全局上下文 │ ← 通过指令文件持久化
│ (编码规范、技术栈决策、团队约定) │
└─────────────────────────────────────────────┘

上下文优化技巧

技巧 1:使用指令文件承载全局上下文

将不随 Spec 变化的全局信息放在指令文件中(如 .github/copilot-instructions.md),避免每次都在 Spec 中重复。

1
2
3
4
5
6
7
<!-- .github/copilot-instructions.md -->
## 全局编码约定
- 使用 TypeScript strict mode
- 文件命名:kebab-case
- 错误使用 AppError 类
- 日志使用 winston
- ...

技巧 2:在 Spec 中使用精确引用而非全文复制

1
2
3
4
5
6
7
8
9
✅ 好的做法:
上下文引用:
- 错误处理方式参照 `src/utils/errors.ts` 中的 AppError 类
- 路由注册方式参照 `src/routes/auth.ts` 第 15-30 行

❌ 差的做法:
上下文引用:
[在这里粘贴了 errors.ts 的全部 200 行代码]
[在这里粘贴了 auth.ts 的全部 150 行代码]

技巧 3:为复杂系统建立"上下文摘要"文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!-- specs/CONTEXT.md -->
# 项目上下文摘要

## 架构概览
- 单体应用,Express + TypeScript
- 三层架构:Controller → Service → Repository
- PostgreSQL + Prisma ORM

## 关键文件索引
| 用途 | 文件 | 说明 |
|------|------|------|
| 路由入口 | src/routes/index.ts | 所有路由在此注册 |
| 数据库连接 | src/db/prisma.ts | Prisma client 单例 |
| 错误基类 | src/utils/errors.ts | AppError 定义 |
| 认证中间件 | src/middleware/auth.ts | JWT 验证 |

## 数据库表概览
| 表名 | 关键字段 | 说明 |
|------|---------|------|
| users | id, email, password_hash | 用户表 |
| todos | id, title, status, user_id | 待办事项表 |

技巧 4:长流程中的"上下文检查点"

在多步骤的代码实现过程中,定期创建上下文检查点:

1
2
3
4
5
6
7
8
每 3-5 步执行一次:

Prompt:
"请总结一下到目前为止已完成的工作:
1. 已创建/修改了哪些文件
2. 已实现了哪些功能
3. 接下来还需要完成什么
4. 当前代码与 Spec 的一致性状态"

6.3 Spec 版本管理

Git 中的 Spec 管理策略

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 推荐的 Git 工作流

# 1. 创建 Spec 分支
git checkout -b spec/user-registration

# 2. 编写并提交 Spec
git add specs/modules/user-registration.md
git commit -m "spec: add user registration spec (SPEC-002)"

# 3. Spec Review(通过 PR)
# 创建 PR,团队成员 review Spec

# 4. Spec 批准后,在同一分支上开始实现
# ... 代码开发 ...
git commit -m "feat: implement user registration (SPEC-002)"

# 5. 合并
git merge spec/user-registration

Spec 提交信息规范

1
2
3
4
spec: add [功能名] spec ([Spec ID])      # 新增 Spec
spec: update [功能名] spec ([Spec ID]) # 修改 Spec
spec: deprecate [功能名] spec ([Spec ID]) # 废弃 Spec
feat: implement [功能名] ([Spec ID]) # 实现 Spec

Spec 与代码的关联

在代码中通过注释关联对应的 Spec:

1
2
3
4
5
6
7
8
9
/**
* 用户注册控制器
* @spec SPEC-2026-002 用户邮箱注册
* @see specs/modules/user-registration.md
*/
export async function registerUser(req: Request, res: Response) {
// AC-1: 正常注册
// ...
}

6.4 团队协作中的 Spec 开发

Spec Review 流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Spec Author 编写 Spec


创建 PR / MR(仅包含 Spec 文件)


Spec Reviewer 审查 ← 关注:完整性、准确性、可实现性

┌────┴────┐
│ │
通过 需修改
│ │
▼ ▼
批准 反馈意见
│ │
│ 修改后重新提交
│ │
▼ │
开始实现 ◄───┘

Spec Review 检查清单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
## Spec Review Checklist

### 完整性
- [ ] 包含完整的元信息(title, id, version, status, author)
- [ ] "目标与非目标"清晰明确
- [ ] 详细设计覆盖了所有功能点
- [ ] 错误处理场景完整(包括网络错误、并发、权限等)
- [ ] 验收标准覆盖正常路径和异常路径
- [ ] 上下文引用充分

### 准确性
- [ ] 技术约束与项目实际一致
- [ ] 数据模型设计合理
- [ ] API 设计符合 RESTful 规范(如适用)
- [ ] 没有与已有功能的冲突

### 可实现性
- [ ] 粒度适当(1-3 天工作量)
- [ ] 依赖关系明确且已满足
- [ ] 技术方案可行
- [ ] 没有过度设计

### 可验证性
- [ ] 每条验收标准都是 SMART 的
- [ ] Given-When-Then 格式清晰
- [ ] 可以编写自动化测试来验证

团队 Spec 协作模式

模式 A:Author-Reviewer 模式(小团队,2-5 人)

1
开发者 A(Author)→ 编写 Spec → 开发者 B(Reviewer)→ 审查 → 开发者 A → 实现

模式 B:Spec Lead 模式(中型团队,5-15 人)

1
2
3
4
5
6
7
Spec Lead 编写 L1/L2 级 Spec


分配给各开发者


各开发者编写 L3 级 SpecSpec Lead 审查 → 各开发者实现

模式 C:Spec Sprint 模式(大型团队)

1
2
3
4
Sprint Planning 中专门安排 Spec 编写时间
Week 1 Day 1-2: 集体编写和审查 Spec
Week 1 Day 3 - Week 2: 按 Spec 实现
Sprint Review: 对照 Spec 验收

6.5 常见反模式与避坑指南

反模式 1:Spec 形式主义

1
2
3
4
5
6
症状:为了写 Spec 而写 Spec,内容流于形式,实际不被参考
原因:团队不理解 Spec 的价值,当作行政负担
解决:
- 从最痛的问题(如 AI 产出不一致)入手引入 Spec
- 在 Spec 中只写真正有价值的内容,不追求格式完美
- 用实际效果说服团队(对比有 Spec vs 无 Spec 的 AI 输出质量)

反模式 2:Spec 瀑布综合征

1
2
3
4
5
6
症状:花几天时间写一份"完美"Spec,迟迟不开始实现
原因:混淆了 Spec 驱动和瀑布模型
解决:
- 采用增量式 Spec 编写(草稿 → 充实 → 锐化)
- 设定时间限制:首版 Spec 不超过 1 小时
- 接受 Spec 不完美,在实现过程中迭代

反模式 3:Spec 漂移(Spec 与代码不一致)

1
2
3
4
5
6
7
症状:代码已经演进了多个版本,Spec 还停留在初始状态
原因:只在开发前写 Spec,开发后不更新
解决:
- 将 Spec 更新纳入 Definition of Done
- 代码 Review 时同步检查 Spec 是否需要更新
- 使用 Spec 状态流转机制追踪
- 定期(如每个 Sprint)清理过期 Spec

反模式 4:巨型 Spec

1
2
3
4
5
6
症状:一份 Spec 长达数十页,覆盖整个子系统
原因:没有正确进行需求拆解
解决:
- 遵循粒度控制原则(1-3 天工作量)
- 使用 L1 → L2 → L3 的层次拆分
- 一份 Spec 的验收标准控制在 3-10 条

反模式 5:忽略非功能性需求

1
2
3
4
5
6
症状:Spec 只定义了功能行为,忽略了性能、安全、可用性等
原因:非功能性需求不如功能需求直观
解决:
- 在 Spec 模板中加入"技术约束"强制填写区域
- 建立团队级别的非功能性需求基线
例:"所有 API 响应时间P95 < 500ms,除非 Spec 中另行说明"

反模式 6:AI 输出不审查

1
2
3
4
5
6
症状:AI 生成了代码就直接合并,不对照 Spec 验证
原因:过度信任 AI,跳过验证环节
解决:
- 实施强制性的 Spec 合规性验证
- 使用验证清单模板逐条对照
- 在 CI/CD 中加入自动化测试(覆盖验收标准)

避坑速查表

信号 解法
Spec 太模糊 AI 频繁"猜测"实现方式 增加具体的技术细节和示例
Spec 太详细 写 Spec 时间 > 编码时间 只指定"What",不指定"How"
Spec 无人维护 新成员看 Spec 被误导 纳入 DoD,定期清理
Spec 堆积如山 大量 draft 状态 Spec 无人处理 限制 WIP(Work in Progress)
团队抵触 Spec “写文档浪费时间” 从痛点切入,渐进推广
Spec 重复内容多 多个 Spec 中复制相同的技术约束 抽取到全局上下文/指令文件

7. 应用场景与案例

7.1 新项目从零启动

场景描述

团队要从零开发一个"在线课程管理平台",包含课程展示、用户注册、课程购买、视频播放等功能。

Spec 开发流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
第 1 周:Spec 编写阶段
├── Day 1: 需求分析和功能拆解
│ → 产出:功能模块清单、优先级排列

├── Day 2-3: L1 系统级 Spec
│ → SPEC-001: 系统架构 Spec(技术栈、架构模式、部署方案)
│ → SPEC-002: 数据库设计 Spec(ER 图、表结构、索引策略)

├── Day 4-5: L2 模块级 Spec(P0 模块)
│ → SPEC-003: 用户认证模块 Spec
│ → SPEC-004: 课程管理模块 Spec
│ → SPEC-005: 支付模块 Spec

第 2-4 周:实现阶段(边实现 P0,边编写 P1 的 Spec)
├── Week 2: 实现 SPEC-003(用户认证)+ 编写 P1 Spec
├── Week 3: 实现 SPEC-004(课程管理)
├── Week 4: 实现 SPEC-005(支付)

关键技巧

  1. 先写系统架构 Spec:确定技术栈和全局约定后再写模块 Spec
  2. Spec 编写与实现并行推进:不需要等所有 Spec 写完才开始编码
  3. 每个 Sprint 的 Spec 存量控制在 2-3 个:保持 Spec 的时效性

L1 系统架构 Spec 示例片段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
---
title: "在线课程平台系统架构"
spec_id: "SPEC-2026-001"
status: "approved"
---

# 系统架构 Spec

## 技术栈决策

| 层面 | 技术选型 | 选择原因 |
|------|---------|---------|
| 前端 | Next.js 14 (App Router) | SSR 支持、SEO 友好、团队熟悉 |
| 后端 | Node.js + NestJS | TypeScript 全栈统一、装饰器风格 |
| 数据库 | PostgreSQL 15 | 复杂查询支持好、成熟稳定 |
| 缓存 | Redis 7 | 会话管理、热点数据缓存 |
| 存储 | 对象存储(S3 兼容) | 视频和图片的存储 |
| 部署 | Docker + K8s | 团队已有经验 |

## 架构模式

采用分层单体架构(Modular Monolith):

​ ┌─────────────┐
​ │ Next.js │ ← 前端
​ │ Frontend │
​ └──────┬──────┘
​ │ HTTP/REST
​ ┌──────▼──────┐
​ │ NestJS │ ← 后端
​ │ Backend │
​ ├─────────────┤
​ │ Module: Auth│
​ │ Module: Course│
​ │ Module: Payment│
​ │ Module: Video│
​ └──────┬──────┘
​ │
​ ┌───────────┼───────────┐
​ │ │ │
PostgreSQL Redis Object Storage

1
2
3
4
5
6
7
8
9
10

## 全局编码约定
(此部分同时写入 .github/copilot-instructions.md)

- 文件命名:kebab-case
- 类命名:PascalCase
- 函数/方法:camelCase
- 每个模块包含:controller, service, repository, dto, entity
- 错误处理:使用 NestJS 内置 HttpException 体系
- 日志:使用 NestJS Logger

7.2 遗留系统重构

场景描述

有一个运行了 3 年的电商后台管理系统,代码混乱、缺少文档、测试覆盖率很低。需要在不停机的前提下逐步重构。

Spec 开发策略:考古式 Spec(Archaeology Spec)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
阶段一:理解现状(考古)
├── 用 AI 辅助分析现有代码
├── 为现有功能编写"现状 Spec"(As-Is Spec)
│ — 描述系统当前的实际行为(包括已知 bug)
│ — 标记哪些是"有意设计",哪些是"意外行为"

阶段二:规划目标(设计)
├── 为每个要重构的模块编写"目标 Spec"(To-Be Spec)
│ — 基于 As-Is Spec,定义重构后的目标行为
│ — 明确哪些行为保持不变,哪些需要修改

阶段三:渐进实施(迁移)
├── 按 To-Be Spec 逐模块重构
├── 每个模块重构完成后,运行回归测试
└── 更新 Spec 状态

As-Is Spec 示例片段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
---
title: "[As-Is] 订单列表查询"
spec_id: "SPEC-LEGACY-001"
status: "approved"
tags: ["legacy", "as-is", "orders"]
---

# [As-Is] 订单列表查询

## 1. 当前行为描述

### API 端点
GET /admin/orders (注意:未遵循 RESTful 规范,不带 api 版本号)

### 实际行为
1. 支持分页,但分页参数命名为 `p`(page)和 `s`(size)
2. 返回格式不统一,有时嵌套在 `data.list` 中,有时直接在 `data` 中
3. **已知 Bug**:当 status 参数为空字符串时返回全部数据(而非按"全部状态"筛选)
4. **性能问题**:未使用索引分页,大数据量时超过 5 秒

### 数据库查询
- 使用原始 SQL 拼接(存在 SQL 注入风险)
- 无分页优化(使用 OFFSET)

## 2. 依赖方
- 前端管理面板(admin-panel repo)
- 数据导出脚本(scripts/export-orders.py)
- 第三方物流对接服务

To-Be Spec 关键区别

1
2
3
4
5
6
7
8
9
## 与 As-Is 的差异对照

| 方面 | As-Is(现状) | To-Be(目标) | 迁移策略 |
|------|-------------|-------------|---------|
| API 路径 | /admin/orders | /api/v2/admin/orders | 新旧并存,灰度切换 |
| 分页参数 | p, s | page, pageSize | 兼容旧参数 3 个月 |
| 返回格式 | 不一致 | 统一 { data, pagination } | 新 API 统一格式 |
| SQL 注入 | 存在风险 | 使用参数化查询 | 立即修复 |
| 分页性能 | OFFSET | Cursor-based | To-Be 实现 |

7.3 API 开发

场景描述

公司需要为移动端 App 开发一套完整的 RESTful API,包含用户、商品、订单等资源。

API Spec 的特殊关注点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
## API Spec 核心要素清单

### 1. 端点定义
- HTTP 方法 + 路径
- 路径参数和查询参数
- 请求头要求(Authorization, Content-Type 等)

### 2. 请求/响应契约
- 请求体 JSON Schema(字段、类型、必填/可选、验证规则)
- 成功响应格式和状态码
- 所有可能的错误响应

### 3. 认证与授权
- 哪些端点需要认证?
- 需要什么权限/角色?

### 4. 限流策略
- 请求频率限制
- 响应头中的限流信息

### 5. 版本策略
- URL 版本号(/api/v1/)
- 向后兼容规则

实践建议

  1. 一个资源一个 Specuser-api.mdproduct-api.mdorder-api.md
  2. 先定义统一的 API 约定 Spec:错误格式、分页格式、认证方式
  3. 包含完整的请求/响应示例:AI 对照示例生成代码更准确
  4. 标注幂等性:哪些操作是幂等的(PUT, DELETE),哪些不是(POST)

7.4 前端功能开发

场景描述

为一个 SaaS 产品的管理后台新增"数据分析仪表盘"页面。

前端 Spec 的特殊关注点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
## 前端 Spec 核心要素清单

### 1. 页面/组件结构
- 组件树和层次关系
- 可复用组件 vs 页面专用组件

### 2. 状态管理
- 全局状态 vs 局部状态
- 数据流向
- 缓存策略

### 3. 交互行为
- 用户操作 → 系统响应 的完整映射
- 动画/过渡效果
- 键盘快捷键

### 4. 响应式设计
- 断点定义
- 不同屏幕尺寸下的布局差异

### 5. 异步状态处理
- 加载中状态(Loading)
- 空状态(Empty State)
- 错误状态(Error State)
- 乐观更新策略(Optimistic Update)

示例:仪表盘 Spec 片段

1
2
3
4
## 3. 详细设计

### 3.1 页面结构

DashboardPage
├── PageHeader
│ ├── Title: "数据分析"
│ └── DateRangePicker(默认最近 7 天)
├── MetricCards(横排,等宽 4 列)
│ ├── Card: 总用户数
│ ├── Card: 活跃用户数
│ ├── Card: 收入总额
│ └── Card: 转化率
├── ChartSection(2 列布局)
│ ├── LineChart: 用户增长趋势
│ └── BarChart: 收入分布
└── DataTable
└── 最近交易记录(分页,每页 10 条)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

### 3.2 交互行为

| 用户操作 | 系统响应 |
|---------|---------|
| 切换日期范围 | 所有图表和指标卡片重新加载数据 |
| 悬停指标卡片 | 显示与上一周期的对比(↑12% 或 ↓5%) |
| 点击图表数据点 | 显示该日期的详细数据弹窗 |
| 调整浏览器宽度到 <768px | 指标卡片变为 2x2 布局,图表变为单列 |

### 3.3 加载状态

| 状态 | UI 表现 |
|------|--------|
| 初始加载 | 指标卡片显示 Skeleton 动画,图表区域显示加载占位符 |
| 数据为空 | 显示 Empty State 插画 + "暂无数据,请调整日期范围" |
| 加载失败 | 显示错误提示 + "点击重试" 按钮 |
| 部分加载失败 | 失败的组件单独显示错误状态,不影响其他组件 |

7.5 Bug 修复与问题排查

场景描述

生产环境报告"用户在特定条件下无法完成支付",需要排查和修复。

Bug 修复 Spec 模式

Bug 修复同样可以使用 Spec 模式,特别是对于复杂 Bug。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
---
title: "[Bug] 特定条件下支付失败"
spec_id: "SPEC-BUG-2026-042"
status: "approved"
author: "值班开发"
created: "2026-03-24"
tags: ["bug", "payment", "production", "P0"]
---

# [Bug] 特定条件下支付失败

## 1. Bug 描述

### 复现条件
- 用户余额恰好等于商品价格(分文不差)
- 使用优惠券后实际支付金额为 0
- 用户点击"确认支付"

### 预期行为
- 支付成功,订单状态变为 "paid"
- 扣减优惠券使用次数

### 实际行为
- 页面卡在"处理中"状态 30 秒后超时
- 订单状态仍为 "pending"
- 优惠券已被标记为已使用(数据不一致)

### 影响范围
- 影响所有 100% 折扣的优惠券场景
- 过去 7 天有 23 个工单报告此问题

## 2. 根因分析

### 初步排查结果
- 当支付金额为 0 时,支付网关返回错误:"amount must be greater than 0"
- 代码中未处理 0 金额的特殊情况
- 优惠券扣减在支付网关调用之前执行(事务不一致)

### 问题代码位置
- `src/services/payment.ts` 第 87-102 行
- `src/services/coupon.ts` 第 45 行

## 3. 修复方案

### 修复点 1: 0 金额支付逻辑
- 当实际支付金额为 0 时,跳过支付网关调用
- 直接将订单标记为 "paid"
- 记录支付方式为 "coupon_full_discount"

### 修复点 2: 事务一致性
- 将优惠券扣减和订单状态更新包装在数据库事务中
- 如果任何一步失败,整体回滚

### 不应修改
- 支付网关调用逻辑(非 0 金额场景保持不变)
- 前端支付流程

## 4. 验收标准

**AC-1: 0 金额支付成功**
- Given: 用户使用 100% 折扣优惠券,实际支付 0 元
- When: 点击"确认支付"
- Then: 支付成功,订单状态为 "paid",支付方式为 "coupon_full_discount"

**AC-2: 事务一致性**
- Given: 优惠券扣减后发生错误
- When: 事务中的后续步骤失败
- Then: 优惠券使用记录回滚,保持可用状态

**AC-3: 回归验证**
- Given: 正常的非 0 金额支付
- When: 完成支付流程
- Then: 行为不变,支付网关正常调用

**AC-4: 历史数据修复**
- Given: 过去 7 天因此 Bug 导致的不一致数据
- When: 运行数据修复脚本
- Then: 23 个受影响订单的状态和优惠券数据恢复一致

## 5. 测试要求
- 单元测试:覆盖 0 金额分支
- 集成测试:模拟完整支付流程(0 金额 + 正常金额)
- 回归测试:确保现有支付测试全部通过

Bug 修复使用 Spec 的好处

  1. 防止"修了一个 Bug,引入两个新 Bug":通过明确"不应修改"的范围
  2. 确保数据修复:Bug 修复不仅是代码修复,还包括受影响数据的处理
  3. 可追溯:之后可以查看 Bug Spec 了解修复决策的完整上下文
  4. 知识积累:相似的 Bug 可以参考历史 Spec 快速处理

8. 工具生态与高级主题

8.1 与主流 AI 编程工具的集成

GitHub Copilot(Agent Mode)

GitHub Copilot 的 Agent 模式是 Spec 开发模式的天然载体:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
集成方式:

1. 全局指令文件
.github/copilot-instructions.md
→ 放置全局编码约定、Spec 开发流程说明

2. 工作区指令文件
.vscode/copilot-instructions.md
→ 放置项目级别的约定

3. Prompt 文件(.prompt.md)
→ 可创建预设的 Spec 模板 prompt

4. Agent 模式执行流程
→ 在 Chat 中引用 Spec 文件
→ 要求 Copilot 根据 Spec 生成 Plan
→ 审查 Plan 后执行

最佳搭配

  • 使用 @workspace 让 Copilot 感知整个项目结构
  • 将 Spec 文件直接拖入 Chat 作为上下文
  • 使用"分步执行"策略,每步确认后再继续

Cursor

1
2
3
4
5
6
7
8
9
10
11
12
13
集成方式:

1. 项目规则文件
.cursor/rules
→ 类似 copilot-instructions.md,定义全局约定

2. Composer 模式
→ 适合基于 Spec 的多文件生成
→ 可以一次性提交 Spec + 相关上下文

3. Chat 模式
→ 适合 Spec 的审查和优化
→ 可以让 AI 帮助完善 Spec 内容

最佳搭配

  • Composer 模式适合"全自动"策略(简单任务)
  • Chat 模式适合"分步执行"策略(复杂任务)
  • 使用 @file 引用 Spec 文件和相关代码

Claude(API / Console)

1
2
3
4
5
6
7
8
9
10
11
集成方式:

1. System Prompt
→ 放置全局约定和 Spec 开发流程说明

2. Projects 功能
→ 将 Spec 文件上传为 Project Knowledge
→ 所有对话自动包含 Spec 上下文

3. Extended Thinking
→ 适合让 AI 分析复杂 Spec 并生成 Plan

最佳搭配

  • 利用 Extended Thinking 处理复杂的系统级 Spec
  • 使用 Projects 功能管理多个相关 Spec
  • 适合"骨架优先"策略

工具对比

特性 GitHub Copilot Cursor Claude
IDE 集成 VS Code 原生 独立 IDE Web/API
文件操作 ✅ 直接读写 ✅ 直接读写 ❌ 需手动
多文件编辑 ✅ Agent Mode ✅ Composer ❌ 逐文件
上下文容量 很大
Spec 感知 通过指令文件 通过规则文件 通过 System Prompt
最佳场景 日常开发 多文件重构 复杂设计分析

8.2 Spec 与测试驱动开发(TDD)的融合

Spec 开发模式可以与 TDD 完美融合,形成 Spec-Driven TDD 流程:

1
2
传统 TDD:         ❌ Red → ✅ Green → ♻️ Refactor
Spec-Driven TDD: 📋 Spec → ❌ Red → ✅ Green → ♻️ Refactor → ✅ Verify vs Spec

融合流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Step 1: 编写 Spec(包含验收标准)


Step 2: 根据验收标准生成测试用例 ← AI 辅助
│ · AC-1 → test: should create user with valid email
│ · AC-2 → test: should reject duplicate email
│ · AC-3 → test: should reject weak password


Step 3: 运行测试(全部 ❌ Red)


Step 4: 根据 Spec 实现代码 ← AI 辅助


Step 5: 运行测试(全部 ✅ Green)


Step 6: 对照 Spec 验收标准验证(Verify vs Spec)

从验收标准到测试用例的映射

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Spec 验收标准:
AC-1: 正常邮箱注册
- Given: 有效的邮箱和密码
- When: POST /api/v1/auth/register
- Then: 返回 201,包含用户信息
// 自动映射的测试用例
describe('POST /api/v1/auth/register', () => {
// AC-1: 正常邮箱注册
it('should return 201 with user info for valid registration', async () => {
// Given
const payload = {
email: 'new@example.com',
password: 'Abc12345',
name: '测试用户'
};

// When
const res = await request(app)
.post('/api/v1/auth/register')
.send(payload);

// Then
expect(res.status).toBe(201);
expect(res.body).toHaveProperty('id');
expect(res.body.email).toBe('new@example.com');
expect(res.body.name).toBe('测试用户');
expect(res.body.emailVerified).toBe(false);
});
});

Prompt 模板:从 Spec 生成测试

1
2
3
4
5
6
7
8
9
10
11
请根据以下 Spec 的验收标准,生成完整的测试用例。

要求:
1. 每一条验收标准(AC)对应至少一个测试用例
2. 使用 Given-When-Then 注释结构
3. 包含正常路径和异常路径
4. 使用 [Jest/PyTest/...] 测试框架
5. 测试文件路径:[指定路径]

验收标准:
[粘贴 Spec 中的验收标准]

8.3 Spec 开发模式与传统开发模式对比

全面对比表

维度 传统开发 AI 对话式编程 Spec 驱动开发
核心驱动力 需求文档 + 人脑 自然语言 Prompt 结构化 Spec
代码编写者 人类 AI(人类审查) AI(人类监督)
质量控制 Code Review 人工审查 AI 输出 Spec 合规性验证
需求追溯 弱(需额外工具) 无(对话历史会丢失) 强(Spec ↔ Code 映射)
一致性 依赖个人经验 低(每次对话独立) 高(Spec 提供稳定锚点)
可复现性 中(依赖文档质量) 低(prompt 不够系统化) 高(Spec 可重复使用)
学习曲线 中(需学习 Spec 编写)
适合的项目规模 任意 小型/原型 中型及以上
团队协作 通过代码 困难(对话不可共享) 通过 Spec Review
知识沉淀 在代码和文档中 在聊天记录中(易丢失) 在 Spec 文件中(持久化)
变更管理 修改代码 + 更新文档 重新对话 更新 Spec → 重新生成
效率天花板 受限于编码速度 受限于 AI 理解准确度 受限于 Spec 编写质量

什么时候不需要 Spec 开发模式?

场景 原因 替代方案
快速原型/POC 速度优先,不需要长期维护 直接 AI 对话式编程
一行 Bug 修复 问题和修复都很明确 直接修改代码
探索性编程 还不知道要做什么 先探索,再写 Spec
纯 UI 微调 视觉调整不适合文字描述 截图 + 口头描述
个人脚本/工具 只有自己使用,不需要协作 随意选择

8.4 进阶技巧

技巧一:多 Spec 编排

当多个 Spec 之间存在依赖关系时,需要进行编排。

1
2
3
4
5
6
7
8
9
Spec 依赖图示例:

SPEC-001: 用户认证基础设施

SPEC-002: 邮箱注册 ←────────── SPEC-006: 邮件服务

SPEC-003: 登录/登出

SPEC-004: JWT Token 管理 ────→ SPEC-005: Token 刷新

编排规则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
## Spec 执行顺序

### 第一批(无依赖)
- SPEC-001: 用户认证基础设施
- SPEC-006: 邮件服务
→ 这两个可以并行实现

### 第二批(依赖第一批)
- SPEC-002: 邮箱注册(依赖 SPEC-001 + SPEC-006)

### 第三批(依赖第二批)
- SPEC-003: 登录/登出(依赖 SPEC-002)

### 第四批(依赖第三批)
- SPEC-004: JWT Token 管理(依赖 SPEC-003)
- SPEC-005: Token 刷新(依赖 SPEC-004,可与 SPEC-004 串行)

技巧二:Spec 组合模式

对于复杂功能,使用"父 Spec + 子 Spec"的组合模式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
## 父 Spec(总览)

---
title: "支付系统"
spec_id: "SPEC-PAY-000"
type: "parent"
children:
- "SPEC-PAY-001" # 支付网关集成
- "SPEC-PAY-002" # 订单支付流程
- "SPEC-PAY-003" # 退款处理
- "SPEC-PAY-004" # 对账系统
---

# 支付系统 Spec

## 子 Spec 概览

| Spec | 描述 | 优先级 | 依赖 |
|------|------|--------|------|
| PAY-001 | 支付网关集成 | P0 | 无 |
| PAY-002 | 订单支付流程 | P0 | PAY-001 |
| PAY-003 | 退款处理 | P1 | PAY-002 |
| PAY-004 | 对账系统 | P2 | PAY-001, PAY-002 |

## 全局约束
(适用于所有子 Spec 的通用约束)
- 所有金额使用最小货币单位(分)存储
- 支付状态机:pending → processing → success/failed
- 所有支付操作必须有幂等性保障

技巧三:Spec 复盘(Spec Retrospective)

项目交付后进行 Spec 复盘,持续改进:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
## Spec 复盘模板

### 项目/Sprint:[名称]
### 复盘日期:YYYY-MM-DD

### Spec 统计
- 编写的 Spec 数量:10
- 一次通过验证的比例:70%
- 需要修改 Spec 的次数:8 次
- 平均 Spec 编写时间:45 分钟

### 好的做法(Keep)
- AC-1 的 Given-When-Then 格式让测试编写很顺利
- 上下文引用帮助 AI 准确理解了项目约定

### 需要改进(Improve)
- 前端 Spec 缺少响应式设计的描述,导致移动端 Bug
- 部分 Spec 的"非目标"不够明确,AI 实现了不需要的功能

### 新发现(Learn)
- 在 Spec 中包含"错误处理"的具体状态码列表,能显著提高 AI 的实现质量
- 数据模型 Spec 应该包含索引策略,否则 AI 不会主动添加

### 行动项(Action)
- [ ] 更新 Spec 模板,加入"响应式设计"必填章节
- [ ] 建立团队级别的错误码清单
- [ ] 在 Spec Review Checklist 中加入"非目标边界检查"

技巧四:Spec 驱动的 AI 流水线

对于重复性的开发任务,可以构建"Spec → Code"的自动化流水线:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
┌──────────────┐
│ Spec 模板 │
│ + 参数输入 │─────────┐
└──────────────┘ │

┌──────────────────┐
Step 1: 生成 Spec │ ← AI 根据模板和参数生成完整 Spec
└────────┬─────────┘


┌──────────────────┐
Step 2: 人工审查 │ ← 快速确认 Spec 准确性
└────────┬─────────┘


┌──────────────────┐
Step 3: 生成代码 │ ← AI 根据审查后 Spec 生成代码
└────────┬─────────┘


┌──────────────────┐
Step 4: 生成测试 │ ← AI 根据验收标准生成测试
└────────┬─────────┘


┌──────────────────┐
Step 5: 运行测试 │ ← 自动验证
└────────┬─────────┘

通过 / 失败
│ │
▼ ▼
完成 回到 Step 3 修复

适用场景:CRUD API 开发、表单页面开发、数据迁移脚本等高重复性任务。


9. FAQ(常见问题与解答)

Q1: Spec 开发模式会不会降低开发速度?

不会,反而会提高整体效率。

初学者可能觉得"先写 Spec 再写代码"比"直接写代码"慢。但实际上:

阶段 无 Spec 有 Spec
需求理解 靠猜测,后期频繁返工 提前明确,减少返工
AI 代码生成 输出不稳定,需多次重试 一次命中率高
Code Review 需要理解意图 + 检查实现 只需对照 Spec 检查
Bug 修复 不清楚"正确行为"是什么 有明确的验收标准
总耗时 通常更多 通常更少

经验数据:编写 Spec 额外花费的 30-60 分钟,通常能节省后续 2-4 小时的调试和返工时间。

Q2: 简单功能也需要写 Spec 吗?

视情况而定。 参考以下判断标准:

1
2
3
4
5
6
7
8
9
10
11
12
需要 Spec 的情况:
✅ 功能涉及多个文件
✅ 有复杂的业务规则
✅ 需要与团队其他成员协作
✅ 功能会长期维护
✅ 需要 AI 协助实现

不需要 Spec 的情况:
❌ 修改一行配置
❌ 修正一个明确的 typo
❌ 添加一条简单的日志
❌ 纯粹的代码格式化

简易规则:如果你能在 5 分钟内完成且不需要 AI 帮忙,就不需要 Spec。

Q3: Spec 应该写到什么程度才够详细?

"零猜测"测试:把 Spec 交给一个完全不了解项目的开发者(或 AI),如果他不需要问你任何问题就能完成实现,那就够详细了。

常见的"不够详细"信号:

  • AI 生成代码时做了很多你没预期的技术选择
  • 不同的人读同一份 Spec 会有不同的理解
  • 验收标准中使用了"合适的"、"合理的"等模糊词

Q4: 如何说服团队采用 Spec 开发模式?

采用渐进式推广策略

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Level 1(试点):
- 选择一个痛点明显的项目/模块
- 由 1-2 个人先试用
- 收集对比数据(有 Spec vs 无 Spec 的效果)

Level 2(推广):
- 用试点数据展示效果
- 编写团队级 Spec 模板
- 开始在 Sprint Planning 中分配 Spec 编写时间

Level 3(制度化):
- Spec Review 纳入开发流程
- Spec 更新纳入 Definition of Done
- 建立 Spec 质量度量指标

Q5: Spec 和需求文档(PRD)有什么区别?

维度 PRD(产品需求文档) Spec(规格说明)
作者 产品经理 开发者
受众 所有角色 开发者 + AI
侧重 业务价值和用户体验 技术实现和系统行为
精确度 业务级别(较模糊) 技术级别(精确)
格式 自由格式 结构化格式
生命周期 开发前定稿 随开发持续更新

关系:PRD 是 Spec 的输入之一。PRD 告诉你"用户想要什么",Spec 告诉 AI"系统应该怎么做"。

Q6: 多人同时编写 Spec 会冲突吗?

可能会,但可以管理。 与代码冲突类似,Spec 冲突通过以下方式避免:

  1. 模块划分清晰:不同人负责不同模块的 Spec
  2. 使用 Git 分支:每个 Spec 一个分支,通过 PR 合并
  3. 定义全局约定 Spec:技术栈、编码规范等放在共享的上下文文件中,避免各自定义
  4. 每日 Spec Sync:团队快速同步各自 Spec 的进展(类似 Daily Standup)

Q7: AI 生成的代码不符合 Spec 怎么办?

按优先级处理

1
2
3
4
5
6
7
8
9
10
11
12
Step 1: 检查是 Spec 的问题还是 AI 的问题
- 如果 Spec 有歧义 → 修改 Spec,重新生成
- 如果 Spec 清晰但 AI 理解错误 → 进入 Step 2

Step 2: 优化 Prompt 策略
- 将 Spec 拆分为更小的部分逐步执行
- 提供更多上下文(相关代码文件)
- 明确指出 AI 的错误并要求修正

Step 3: 手动修正
- 如果 AI 持续无法正确实现某个部分,手动修正代码
- 在 Spec 中标注"此部分需人工实现"

Q8: 如何衡量 Spec 开发模式的效果?

推荐的度量指标

指标 计算方式 目标值
Spec 首次通过率 一次验收通过的 Spec 数 / 总 Spec 数 > 70%
AI 输出采纳率 无需修改直接使用的 AI 代码行数 / 总生成行数 > 80%
返工次数 Spec 批准后的修改次数 < 2 次/Spec
Bug 密度 Bug 数 / 千行代码 持续下降
Spec 编写时间 平均每个 Spec 的编写时间 30-60 分钟
端到端交付时间 从需求到代码交付的总时间 比无 Spec 时更短

Q9: Spec 文件应该纳入 Git 版本管理吗?

绝对应该。 Spec 文件是项目的一等公民,理由:

  1. 变更追踪:谁在什么时候修改了 Spec 的哪些内容
  2. 协作工具:通过 PR Review 进行 Spec 审查
  3. 版本对应:代码 v1.2 对应 Spec v1.2
  4. 知识沉淀:Spec 的演进历史本身就是宝贵的项目知识
1
2
3
4
5
6
7
# 推荐的 .gitignore 配置
# 不要忽略 specs 目录
!specs/

# 可以忽略 Spec 编写过程中的临时文件
specs/**/*.tmp
specs/**/*.draft.md # 如果使用临时草稿文件

Q10: Spec 开发模式适合个人开发者吗?

非常适合。 个人开发者使用 Spec 模式的好处:

  1. 思维整理:写 Spec 的过程就是理清思路的过程
  2. AI 协作:个人开发者使用 AI 工具的频率更高,Spec 能显著提高 AI 产出质量
  3. 项目延续性:几个月后重新打开项目,Spec 能帮你快速恢复上下文
  4. 简化版本:个人使用可以简化 Spec 格式,跳过 Review 流程

个人开发者的轻量 Spec 格式:

1
2
3
4
5
6
7
8
9
10
11
12
# [功能名]

## 要做什么
- ...

## 怎么做
- 技术栈:...
- 关键实现:...

## 验收条件
- [ ] 条件 1
- [ ] 条件 2

Q11: Spec 开发模式会被 AI 的进步淘汰吗?

不会,反而会更重要。 随着 AI 能力增强:

  • AI 越强大 → 能处理的 Spec 越复杂 → Spec 的价值越大
  • AI 越自主 → 越需要明确的"合约"来约束行为 → Spec 越重要
  • 多 Agent 协作 → 需要统一的"任务描述格式" → Spec 是天然选择

类比:SQL 没有因为数据库引擎的进步而被淘汰,反而更加重要。Spec 之于 AI,就像 SQL 之于数据库——它是人类意图的精确表达语言。

Q12: 如何处理 Spec 中的不确定性?

使用"开放问题"章节明确记录不确定性,而非在 Spec 中留下模糊描述:

1
2
3
4
5
6
7
8
9
## 开放问题

### 已标记的不确定性
- [ ] **OQ-1**: 是否需要支持批量删除?(待产品确认,暂不实现)
- [ ] **OQ-2**: 缓存时间设为多少合适?(暂定 5 分钟,后续根据监控调整)
- [x] **OQ-3**: 使用 UUID v4 还是 v7?(已确定:使用 v7,有序性更好)

### 决策记录
- 2026-03-24: OQ-3 决定使用 UUID v7,原因是 v7 的时间有序性对数据库索引更友好

10. 附录

10.1 参考资源与延伸阅读

方法论相关

  • BDD(行为驱动开发):Spec 中的 Given-When-Then 格式源自 BDD。[Dan North 的 BDD 简介]
  • DDD(领域驱动设计):Spec 中的"通用语言"概念与 DDD 的 Ubiquitous Language 一脉相承
  • Design by Contract:Spec 的"合约"概念源自 Bertrand Meyer 的 Design by Contract 理论
  • Literate Programming:Donald Knuth 提出的"文学化编程"理念,Spec 某种程度上是其现代演绎

工具相关

  • GitHub Copilot 文档:Agent Mode、指令文件配置
  • Cursor 文档:Rules 配置、Composer 模式
  • Claude 文档:System Prompt、Projects 功能

相关实践

  • RFC(Request for Comments):许多科技公司使用的内部技术设计文档,Spec 的灵感之一
  • ADR(Architecture Decision Records):架构决策记录,可以和 Spec 配合使用
  • C4 Model:系统架构可视化模型,适合在 L1 系统级 Spec 中使用

10.2 术语索引

术语 章节 首次出现
AC(Acceptance Criteria) 4.2 验收标准编写原则
Agent Mode 8.1 AI 工具集成
BDD 4.2 Given-When-Then 格式
Context Window 2.4 核心术语表
Design by Contract 2.2 核心原则
Feedback Loop 5.5 迭代与反馈循环
Given-When-Then (GWT) 4.2 行为描述格式
Implementation Agent 2.3 角色模型
Living Documentation 1.2 Spec 核心优势
MoSCoW 3.2 优先级排列方法
Plan 3.4 实施计划
Planning Agent 2.3 角色模型
Progressive Elaboration 2.2 增量式规格定义
SMART 4.2 验收标准原则
Spec 2.1 规格说明
Spec Chain 2.4 Spec 依赖关系
Spec Drift 6.5 反模式
Spec First 2.2 核心原则
SSOT 1.2 单一事实来源
Token Budget 6.2 上下文管理
Verification Agent 2.3 角色模型

10.3 文档变更日志

日期 版本 变更说明 作者
2026-03-24 1.0 初始版本,包含完整的 Spec 开发模式指南

结语

Spec 开发模式不是一套死板的流程规范,而是一种思维方式的转变

从"我来写代码"转变为"我来定义意图,让 AI 实现代码"。

这种转变要求我们发展新的技能——精确描述意图的能力、结构化思考的能力、以及与 AI 有效协作的能力。Spec 文件就是这些能力的载体。

记住三个关键点

  1. Spec First,但不是 Spec Only:先有 Spec,但 Spec 可以在实践中迭代
  2. 质量来自 Spec,而非来自 AI:AI 的输出质量上限取决于 Spec 的质量
  3. Spec 是投资,不是成本:花在 Spec 上的时间,会在后续阶段数倍返还

开始你的第一个 Spec 吧。不需要完美,从一个简单的模块开始,逐步感受 Spec 驱动开发带来的效率提升和质量改善。


本文档遵循 CC BY-SA 4.0 协议。欢迎修改和传播。