找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

4564

积分

0

好友

640

主题
发表于 3 小时前 | 查看: 2| 回复: 0

最近,Thoughtworks、GitHub 以及 Martin Fowler 等技术圈的意见领袖都在频繁讨论一个缩写:SDD,即规范驱动开发(Spec-Driven Development)。

简单来说,SDD 的核心就是 先写规范,再写代码。并且,这里的规范不是为了给人阅读,它的首要目标是让 AI 能够精确理解和执行。这个概念听起来有些抽象?别急,我们一步步拆解。

规范驱动开发SDD流程图展示协作与自动化流程

传统开发模式的困境:需求与代码的断层

我们不妨先回顾一下传统的软件开发流程:

  1. 产品经理产出 PRD(产品需求文档)。
  2. 开发工程师阅读 PRD 后开始编写代码。
  3. 测试工程师同样依据 PRD 来设计测试用例。
  4. 当需求发生变更时,需要同步更新 PRD、代码和测试用例。

这个流程的根本问题在于,PRD 和代码是彻底脱节的两套体系。PRD 的表述往往依赖自然语言,细节模糊,开发过程中大量依赖口头沟通来澄清。几个月后,代码可能已经迭代了十几个版本,而 PRD 文档还停留在最初的模样。新加入团队的成员面对陈旧的文档和复杂的代码,会感到无所适从。

更重要的是,PRD 是为人设计的,机器无法准确解析其意图。在 人工智能 辅助编程日益普及的今天,如果你直接将一份传统的 PRD 丢给 AI,它生成的代码常常南辕北辙,因为 AI 不得不去“猜测”那些模糊需求背后的具体实现。

SDD 的核心思想:规范即代码

SDD 提出了一种新的思路:放弃那种笼统的、描述性的 PRD,转而编写结构清晰、无歧义的规范(Specification)

那么,规范和 PRD 究竟有什么区别?来看一个直观的例子:

传统的 PRD 可能会这样描述:

“用户需要能够登录系统,输入用户名和密码,登录成功后跳转到首页。”

而一份 SDD 规范会这样定义:

## 登录功能

### 输入
*   `username`: string, 必填, 长度 3-20 字符
*   `password`: string, 必填, 长度 8-32 字符

### 处理逻辑
GIVEN 用户提交了登录请求
WHEN 验证用户名存在且密码匹配
THEN 返回登录成功,生成 JWT token
AND 跳转到 `/dashboard`

### 错误处理
*   用户名不存在 → 返回 HTTP 401,提示信息:“用户名或密码错误”
*   密码不匹配 → 返回 HTTP 401,提示信息:“用户名或密码错误”
*   参数缺失 → 返回 HTTP 400,提示具体缺失的字段名

看出差别了吗?

  • PRD 描述的是“要做什么”(What)。
  • 规范 定义的是“具体怎么做”(How),包括精确的输入输出、边界条件、异常流程。

最关键的是,规范是结构化的、机器可读的。将这样一份规范交给 AI,它生成代码的准确率和贴合度会显著提升。

为什么 AI 时代 SDD 变得至关重要?

在过去,编写如此详尽的规范可能费时费力,性价比不高。但AI能力的爆发改变了游戏规则。

好处一:AI 能基于规范生成高质量代码。
给定一份细节完备的规范,AI 可以直接产出符合所有要求的初始代码。开发者从而节省了大量基础编码时间,可以将精力集中在代码审阅、架构设计和关键逻辑的微调上。

好处二:AI 能辅助进行代码维护。
当需求变更时,你只需要修改作为源头的规范,然后指示 AI 根据新规范重新生成或调整代码。只要规范是正确的,代码就不会偏离轨道。

好处三:大幅降低团队沟通成本。
规范成为了项目的“唯一事实来源”(Single Source of Truth)。产品、开发、测试乃至AI都基于同一份精确的文档工作,有效消除了理解偏差。

好处四:自动化测试变得顺理成章。
规范中使用的 Given/When/Then 等结构,可以近乎直接地转换为自动化软件测试用例。代码修改后运行测试套件,能迅速验证原有功能是否被破坏。

SDD 实践的三个成熟度层级

Martin Fowler 对此做了很好的总结,SDD 大致可以分为三个演进层级:

Level 1:规范优先(Spec-First)

先编写规范,然后利用规范来指导 AI 生成代码。此处的规范更像是“一次性”的指导文档,用完后不一定长期维护。
这是最简单的入门方式,非常适合小型功能或一次性任务。

Level 2:规范锚定(Spec-Anchored)

规范被作为核心资产进行长期维护。当需求变化时,首先更新规范,然后让 AI 基于新版规范来修改代码。
这是目前最主流且可行的实践方式。规范与产品代码一同进行版本管理,保持同步迭代。

Level 3:规范即源码(Spec-as-Source)

这是最激进的理想状态:规范是项目中人类维护的唯一“源码”。所有可执行代码均由 AI 从规范生成,并且明确标记为“由规范生成,请勿直接编辑”。
该模式仍在探索阶段,目前仅有 Tessl 等少数工具提供支持。

实战演练:用 SDD 构建一个 Todo 应用

理论说得再多,不如动手一试。我们以一个经典的 Todo 待办事项应用为例,看看 SDD 如何落地。

第一步:编写规范

首先,我们创建一个名为 todo-app.spec.md 的规范文件。

# Todo 应用规范

## 概述
一个简单的待办事项管理应用,支持增删改查和状态切换。

## 数据模型

### Todo 实体
```typescript
interface Todo {
  id: string;           // UUID,唯一标识
  title: string;        // 待办标题,必填,1-100 字符
  completed: boolean;   // 完成状态,默认 false
  createdAt: Date;      // 创建时间
  updatedAt: Date;      // 更新时间
}
```

## API 规范

### 1. 创建待办
**POST /api/todos**

**Request Body:**
```json
{
  "title": "string, 必填, 1-100 字符"
}
```

**Response 201:**
```json
{
  "id": "uuid",
  "title": "string",
  "completed": false,
  "createdAt": "ISO8601",
  "updatedAt": "ISO8601"
}
```

**Error Response 400:**
```json
{
  "error": "标题不能为空" | "标题长度不能超过100字符"
}
```

### 2. 获取待办列表
**GET /api/todos**

**Query Parameters:**
- `filter`: "all" | "active" | "completed"(默认 "all")
- `sort`: "newest" | "oldest"(默认 "newest")

**Response 200:**
```json
{
  "todos": [
    {
      "id": "uuid",
      "title": "string",
      "completed": boolean,
      "createdAt": "ISO8601",
      "updatedAt": "ISO8601"
    }
  ],
  "total": number,
  "activeCount": number,
  "completedCount": number
}
```

### 3. 更新待办状态
**PATCH /api/todos/:id**

**Request Body:**
```json
{
  "title": "string, 可选, 1-100 字符",
  "completed": "boolean, 可选"
}
```

**Response 200:** 更新后的 Todo 对象

**Error Response 404:**
```json
{
  "error": "待办事项不存在"
}
```

### 4. 删除待办
**DELETE /api/todos/:id**

**Response 204:** No Content

**Error Response 404:**
```json
{
  "error": "待办事项不存在"
}
```

## 前端页面规范

### 页面结构
1.  **Header**: 应用标题 + 待办统计(总数/已完成/未完成)
2.  **Input 区域**: 输入框 + “添加” 按钮
3.  **Filter 区域**: 全部/进行中/已完成 切换标签
4.  **Todo 列表**: 每条待办包含:
    -   复选框(切换完成状态)
    -   标题文字(完成的有删除线)
    -   编辑按钮
    -   删除按钮
5.  **Footer**: 清空已完成按钮

### 交互行为
*   输入框回车或点击“添加”创建待办
*   点击复选框切换完成状态
*   双击待办文字进入编辑模式
*   编辑模式下回车保存,ESC 取消
*   点击删除按钮确认后删除
*   切换 filter 标签实时更新列表

## 技术栈
*   后端: [Node.js](https://yunpan.plus/f/58-1) + Express + SQLite
*   前端: React + TypeScript + Tailwind CSS
*   测试: Jest + React Testing Library

第二步:让 AI 生成代码

接下来,将这份完整的规范提交给 Claude、Cursor 或 GitHub Copilot 等 AI 编码助手,并给出指令:

“请根据上面的规范,为我生成完整的 Todo 应用代码,包括后端 API 和前端页面。”

AI 将基于规范生成:

  • 数据库模型与迁移脚本
  • Express 路由和控制器逻辑
  • React 组件树与状态管理代码
  • 基础的 Tailwind CSS 样式

第三步:人工审阅与迭代优化

AI 生成的代码可能并非完美,常见问题包括:

  • 边界条件处理不够周全
  • 某些错误场景的响应被遗漏
  • 缺乏性能优化考虑

这时,你需要回到规范这一源头。补充或修正规范中的细节描述,然后让 AI 根据更新后的规范重新生成代码。

例如,你发现 AI 生成的代码没有对用户输入进行 XSS 防护,那么就在规范中增加安全要求章节:

## 安全要求
- 所有用户输入在存储和渲染前必须进行 XSS 过滤。
- API 响应头必须设置 `Content-Type: application/json; charset=utf-8`。
- 实现基础的接口限流:每个 IP 地址每分钟最多允许 100 次请求。

随后,再次指示 AI 基于包含安全要求的新规范来调整代码。

第四步:从规范生成测试用例

规范中清晰的 Given/When/Then 结构,可以非常方便地转换为自动化测试。AI 也能协助完成这部分工作。

// 基于规范生成的测试示例
describe('Todo API', () => {
  describe('POST /api/todos', () => {
    it('应该创建待办并返回 201', async () => {
      // Given: 用户提交了有效的待办标题
      const title = '学习 SDD';

      // When: 调用创建 API
      const response = await request(app)
        .post('/api/todos')
        .send({ title });

      // Then: 返回 201 和创建的待办对象
      expect(response.status).toBe(201);
      expect(response.body.title).toBe(title);
      expect(response.body.completed).toBe(false);
    });

    it('标题为空时返回 400 错误', async () => {
      // Given: 标题为空
      // When: 调用创建 API
      // Then: 返回 400 错误
    });
  });
});

第五步:应对需求变更

一段时间后,产品经理提出新需求:“需要增加优先级功能,高优先级的待办事项要排在列表前面。”

传统做法:开发者需要手动在数据库模型、API、前端逻辑等多个地方修改代码,容易遗漏,引发 Bug。

SDD 做法

  1. 修改规范:在 Todo 实体中增加 priority: 'high' | 'medium' | 'low' 字段,并同步更新相关的 API 接口规范和前端页面交互逻辑。
  2. 让 AI 重新生成:将更新后的规范交给 AI,让它基于新规范生成或修改所有受影响的代码文件。
  3. 运行测试验证:执行现有的测试套件,确保新增功能没有破坏原有逻辑。

在 SDD 模式下,规范是唯一的真相源。你只需在一处(规范)进行修改,AI 便会帮你将变更同步到所有相关的代码中。

SDD 并非万能银弹

尽管 SDD 前景广阔,但它也有其适用边界和需要注意的问题。

不适用或需谨慎使用的场景:

  • 探索性开发:当需求极其模糊,需要快速原型验证和试错时,先写详细规范可能反而拖慢节奏。
  • 遗留系统改造:对于没有规范文档的历史代码库,从头构建规范的代价可能很高。
  • 极度复杂的业务逻辑:有时,用代码本身来表达复杂逻辑比用规范描述更直接,强行编写规范可能事倍功半。

实践中需要注意的问题:

  • 规范编写的成本:编写高质量、无歧义的规范本身需要时间和技巧,对于极其简单的功能可能得不偿失。
  • 规范质量决定上限:如果规范本身模糊、矛盾或不完整,那么 AI 生成的代码质量也无法保证。
  • 潜在的创新瓶颈:过度依赖 AI 生成模式化代码,可能会抑制开发者在架构和实现上的创新思考。

最佳实践建议:

  • 核心业务逻辑稳定模块采用 SDD,以确保其长期质量和可维护性。
  • 实验性功能,可先用传统模式快速迭代,待其稳定和明确后,再补充规范,将其纳入 SDD 流程。
  • 将规范视为活的文档,建立与代码同步更新的机制,杜绝“写一次就扔”的情况。

总结与展望

SDD 是 AI 辅助编程时代水到渠成的一种范式演进。其本质是,开发者将一部分“编写指令(代码)”的工作,转变为了“编写更精确的元指令(规范)”的工作,而将指令的具体执行交给了 AI。

从模糊的 PRD 到精确的 Spec,从“描述做什么”到“定义怎么做”,从“人编写每一行代码”到“AI 根据规范生成代码”,这代表了软件开发模式的深刻变化。

目前,SDD 仍处于早期发展阶段,相关工具和社区最佳实践都在快速演进中。但“规范即代码”的理念及其在提升开发效率、保证软件质量方面的潜力已经十分清晰。如果你还没有尝试过,不妨从一个像 Todo 应用这样的小项目开始,体验一下“先写规范,后出代码”的全新工作流。你可能会发现,有时候,写好规范比直接写代码更让人省心。关于更多开发模式与架构的讨论,欢迎在云栈社区与更多开发者交流。




上一篇:深入Kbuild:解析Linux内核模块化构建与Makefile底层逻辑
下一篇:飞书2026新品发布解读:AI智能伙伴aily与妙搭Agent如何革新办公协同
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-3-20 15:01 , Processed in 0.481412 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表