在AI编程工具日益普及的今天,一个重要的概念正在改变我们与AI协作编写代码的方式——SDD(Specification-Driven Development,规范驱动开发)。本文将深入解析SDD的核心理念,以及为什么主流AI编程工具都选择支持SDD模式。

什么是SDD

SDD的定义

Specification-Driven Development(规范驱动开发) 是一种软件开发方法论,它强调在编写代码之前先编写清晰、精确的规范说明,然后严格按照规范来实现代码。

核心原则

  • 规范先行:代码实现之前必须先编写Spec
  • 精确描述:用形式化或半形式化的语言描述需求
  • 双向追踪:规范与代码保持一致,可相互验证
  • 迭代完善:从简单规范开始,逐步细化完善

SDD vs 传统开发模式

维度 传统开发 SDD
起点 需求文档或口头描述 精确编写的Spec文件
灵活性 需求边改边写 规范确认后再实现
验证方式 手动测试为主 规范可作为测试用例
AI协作 AI自由发挥空间大 AI按规范执行
变更处理 需求变更成本高 规范变更驱动代码修改

为什么AI编程需要SDD

AI编程的挑战

1. 上下文理解偏差

AI模型虽然强大,但并非能完全理解人类的模糊描述。传统开发中的需求往往是:

"实现一个用户登录功能,要有基本的验证"

这种模糊描述会导致AI生成代码与预期不符。

2. 生成代码质量不稳定

没有规范约束时,AI可能:

  • 遗漏边界情况处理
  • 忽略安全考量
  • API设计风格不统一
  • 实现与项目已有代码风格不一致

3. 迭代维护困难

AI生成的代码在没有规范的情况下:

  • 难以判断是否满足需求
  • 修改时不知道影响范围
  • 新人接手难以理解设计意图

SDD如何解决这些问题

规范提供精确意图

# 传统需求描述
"实现一个用户登录功能"

# SDD规范描述
## 功能需求
1. 支持用户名/邮箱 + 密码登录
2. 登录成功后生成JWT token,有效期24小时
3. 密码错误3次后锁定账户15分钟
4. 登录接口需要防暴力破解(限流:同一IP 5分钟内最多10次)

## 接口规范
- POST /api/v1/auth/login
- Request: { "username": string, "password": string }
- Response: { "token": string, "expiresIn": 86400 }

## 错误处理
- 400: 参数校验失败
- 401: 用户名或密码错误
- 423: 账户已被锁定

## 安全要求
- 密码存储使用bcrypt
- 返回的token不包含敏感信息

规范即测试用例

SDD规范可以直接或通过工具转换为:

  • API的Mock测试
  • 单元测试用例
  • 集成测试场景
  • 验收标准

SDD在AI编程中的价值

1. 减少幻觉(Hallucination)

AI在有明确规范约束时,更容易生成符合预期的代码,而不是"创造"一些不存在的功能。

2. 提高代码一致性

规范定义了统一的:

  • API设计风格
  • 代码组织结构
  • 命名规范
  • 错误处理模式

3. 便于审查和协作

规范的清晰性使得:

  • 代码审查有据可依
  • team member可以并行工作
  • 新成员快速理解项目

4. 支持渐进式开发

SDD支持从简单规范开始,逐步扩展:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# v1.0 最小可用版本
## AuthService
- login(username, password): Promise<User>

# v1.1 增加token支持
## AuthService
- login(username, password): Promise<LoginResult>
- logout(token): Promise<void>
- refreshToken(token): Promise<LoginResult>

# v1.2 增加第三方登录
## AuthService
- login(username, password): Promise<LoginResult>
- loginWithOAuth(provider, code): Promise<LoginResult>
- logout(token): Promise<void>
- refreshToken(token): Promise<LoginResult>

SDD的核心组件

1. Spec文件结构

project/
├── SPEC.md              # 主规范文件
├── api/
│   └── openapi.yaml     # API规范
├── models/
│   └── schema.md        # 数据模型规范
└── specs/
    ├── auth.md          # 认证模块规范
    ├── user.md          # 用户模块规范
    └── ...

2. 规范编写原则

FIRRN原则

  • Factual(事实性):描述系统实际行为,不是愿望清单
  • Independent(独立性):每个规范模块独立描述一个功能
  • Readable(可读性):规范要易于理解和维护
  • Realistic(可行性):规范要可实现、可测试
  • Necessary(必要性):每个需求都是必要的

3. 规范与代码的对应

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

### 描述
根据用户ID获取用户信息

### 输入
- userId: string (必填,用户ID)

### 输出
- User对象或null

### 行为
1. 验证userId格式
2. 从数据库查询用户
3. 返回用户信息(密码字段排除)

### 错误
- InvalidUserIdError: userId格式无效

对应代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
async getUserById(userId: string): Promise<User | null> {
  // 1. 验证userId格式
  if (!isValidUserId(userId)) {
    throw new InvalidUserIdError(userId);
  }

  // 2. 从数据库查询用户
  const user = await this.db.users.findOne({
    where: { id: userId },
    attributes: { exclude: ['password'] }
  });

  // 3. 返回用户信息
  return user;
}

SDD工作流程

完整开发流程

┌─────────────────────────────────────────────────────────┐
│  1. 需求分析                                             │
│     - 收集业务需求                                        │
│     - 识别关键用例                                        │
│     - 确定约束条件                                        │
└───────────────────────┬─────────────────────────────────┘
                        ▼
┌─────────────────────────────────────────────────────────┐
│  2. 编写Spec(规范)                                      │
│     - 编写SPEC.md                                        │
│     - 定义API接口                                         │
│     - 描述数据模型                                         │
│     - 明确边界条件和错误处理                                │
└───────────────────────┬─────────────────────────────────┘
                        ▼
┌─────────────────────────────────────────────────────────┐
│  3. 评审与确认                                            │
│     - 技术评审                                            │
│     - 业务确认                                            │
│     - 达成共识后锁定规范                                    │
└───────────────────────┬─────────────────────────────────┘
                        ▼
┌─────────────────────────────────────────────────────────┐
│  4. AI生成代码                                            │
│     - 基于Spec生成代码                                     │
│     - 生成单元测试                                         │
│     - 生成API文档                                          │
└───────────────────────┬─────────────────────────────────┘
                        ▼
┌─────────────────────────────────────────────────────────┐
│  5. 验证与迭代                                            │
│     - 代码是否符合Spec                                     │
│     - 测试覆盖是否完整                                      │
│     - 发现问题时更新Spec或修复代码                            │
└─────────────────────────────────────────────────────────┘

Spec评审检查清单

  • 功能描述清晰,无歧义
  • 输入输出明确定义
  • 边界条件已覆盖
  • 错误处理完整
  • API设计一致
  • 数据模型合理
  • 安全考虑周全
  • 性能要求明确

SDD工具生态

主流SDD工具

工具 特点 适用场景
Spec-Kit 专为AI编程设计,CLI工具 Claude Code集成
OpenSpec 开放标准,社区驱动 跨工具通用
Stopify 简单Markdown格式 轻量级项目
Docusaurus 文档驱动 文档完善项目

Claude Code与SDD

Claude Code天然支持SDD工作流:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 1. 创建项目并编写规范
mkdir my-project && cd my-project
claude "初始化一个Node.js REST API项目,创建SPEC.md规范文件"

# 2. 基于规范实现
claude "根据SPEC.md实现用户认证模块"

# 3. 验证实现是否符合规范
claude "检查当前实现是否完全符合SPEC.md中的定义"

# 4. 规范更新时同步修改
# 编辑SPEC.md添加新功能
claude "根据更新后的SPEC.md重构相关代码"

SDD最佳实践

规范编写技巧

1. 使用结构化格式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
## 功能名称

### 描述
简短描述功能做什么

### 输入
- param1: type (描述)
- param2: type (描述)

### 输出
- type: 描述

### 行为
1. 步骤1
2. 步骤2

### 错误
- ErrorType: 描述

2. 使用具体例子

### 登录成功示例
输入: { "username": "[email protected]", "password": "correct_password" }
输出: { "token": "eyJhbGciOiJIUzI1NiIs...", "expiresIn": 86400 }

### 密码错误示例
输入: { "username": "[email protected]", "password": "wrong_password" }
输出: 401 { "error": "INVALID_CREDENTIALS", "message": "用户名或密码错误" }

3. 定义清晰的验收标准

## 验收标准
- [ ] 用户名格式验证正确
- [ ] 密码强度验证正确
- [ ] 登录成功返回有效token
- [ ] 错误次数统计正确
- [ ] 账户锁定功能正常
- [ ] Token过期处理正确

常见陷阱

1. 规范过于详细

1
2
3
4
5
6
7
# 不好的做法:规定代码实现细节
### 实现
使用for循环遍历数组,在第5行调用helper函数

# 好的做法:只描述行为
### 实现
按指定顺序处理数据项

2. 规范与实现脱节

  • 每次代码更新都同步更新Spec
  • Spec变更必须经过评审
  • 禁止"代码实现了但Spec没更新"

3. 过度抽象

规范要具体可执行,不是泛泛而谈的架构设计。

总结

SDD的核心价值

  1. 明确性:消除模糊需求,减少沟通成本
  2. 可验证性:规范可直接转化为测试用例
  3. 可维护性:代码和文档始终保持一致
  4. AI友好:为AI提供清晰执行目标

SDD适用场景

场景 SDD适合度 原因
AI辅助编程 非常适合 AI需要明确指令
复杂业务系统 适合 减少需求理解偏差
快速原型 一般 规范可能成为负担
个人小项目 可选 过度设计可能浪费
多人协作项目 非常适合 统一理解和标准

学习建议

  1. 从小项目开始:选择一个简单项目练习SDD工作流
  2. 使用好用的工具:推荐从Spec-Kit或简单Markdown开始
  3. 保持规范更新:规范不是一次性的,需要持续维护
  4. 与AI协作:让AI帮你生成规范初稿,你来审核和完善

SDD不是银弹,但它为AI编程提供了一个可靠的框架。随着AI编程工具的不断进化,SDD将成为高效人机协作的重要基础。