Specification-Driven Development (SDD) - 规范驱动开发

这篇文章翻译自Github的开源项目spec-kit 下的规范驱动开发- Specification-Driven Development (SDD)。它的核心哲学是一场权力的反转:将软件开发的“单一事实来源”从易变的代码彻底转移到人类意图的直接表达——即规范本身。它主张,通过利用AI将结构化、精确且可执行的规范直接生成为代码,可以从根本上消除意图与实现之间的鸿沟。这种方法将开发者的角色从繁琐的“代码翻译者”提升为高阶的“意图定义者”和“系统思想家”,使其专注于创造力、架构和批判性思维,而将机械的实现过程自动化。最终,软件的演进不再是修补代码,而是持续迭代和完善作为系统灵魂的规范,从而实现前所未有的开发速度、适应性和质量保证。

以下翻译基于2025-09-09的commit

权力的反转

几十年来,代码一直是王道。规范服务于代码–它们是我们搭建的脚手架,在真正的编码工作开始后就被丢弃了。我们编写产品需求文档来指导开发,创建设计文档来辅助实现,绘制图表来可视化架构。但这些始终从属于代码本身。代码即真理。其他的一切充其量只是良好的意图。代码是真理的源泉,随着代码的不断推进,规范很少能跟上步伐。由于资产(代码)和实现是一体的,所以很难有并行的实现而不试图从代码构建。

基于规范的开发(SDD)颠覆了这种权力结构。规范不再服务于代码,而是代码服务于规范。产品需求文档(PRD)不再是实施的指南,而是生成实施的源头。技术方案不再是指导编码的文件,而是生成代码的精确定义。这并非是对我们构建软件方式的渐进式改进,而是对驱动开发的根本性重新思考。

自软件开发诞生以来,规格说明与实现之间的差距一直困扰着软件开发。我们曾试图通过更好的文档、更详细的需求以及更严格的流程来弥合这一差距。但这些方法都失败了,因为它们默认这一差距不可避免,只是试图缩小它,却从未消除它。SDD 则通过使规格说明及其从规格说明中生成的具体实现计划具有可执行性来消除这一差距。当规格说明到实现计划生成代码时,就不存在差距了—只有转换。

这种转变如今成为可能,是因为人工智能能够理解并执行复杂的规范,并制定详细的实施计划。但未经结构化的原始人工智能生成会导致混乱。SDD 通过规范以及后续精确、完整且清晰无误的实施计划来提供这种结构,这些计划足以生成可运行的系统。规范成为主要的成果。代码则成为其在特定语言和框架中的表达(作为实施计划的实现)。

在这个新世界里,维护软件意味着不断演进规格说明。开发团队的意图通过自然语言(“意图驱动开发”)、设计资产、核心原则和其他指导方针来表达。开发的通用语言(lingua franca)上升到了更高层次,而代码则是最后的实现手段。

调试意味着修正产生错误代码的规范及其实施计划。重构意味着为了清晰而重新组织。整个开发工作流程围绕规范作为核心事实来源而重新组织,实施计划和代码则是持续再生的输出。由于我们富有创造力,所以要为应用程序添加新功能或创建新的并行实现,就需要重新审视规范并制定新的实施计划。因此,这个过程是 0 到 1,(1’,…),2,3,N。

开发团队专注于发挥创造力、进行试验以及运用批判性思维。

SDD 工作流在实践中的应用

工作流程始于一个想法–通常模糊且不完整。通过与人工智能的反复对话,这个想法逐渐演变成一份全面的产品需求文档(PRD)。人工智能会提出澄清问题,识别边缘情况,并帮助定义精确的验收标准。在传统开发中可能需要数天会议和文档编写的工作,在这里只需几个小时的专注规格编写即可完成。这改变了传统的软件开发生命周期(SDLC)–需求和设计成为持续的活动,而非独立的阶段。这有利于团队流程,团队评审的规范被表述和版本化、在分支中创建并最终合并。

当产品经理更新验收标准时,实施计划会自动标记受影响的技术决策。当架构师发现更好的模式时,产品需求文档(PRD)会更新以反映新的可能性。

在整个规范流程中,研究代理(research agents)会收集关键背景信息(critical context)。他们会调查库的兼容性、性能基准以及安全影响。组织约束会自动被发现并应用–贵公司的数据库标准、认证要求和部署政策会无缝融入到每一个规范中。

从产品需求文档(PRD)出发,人工智能生成实施计划,将需求与技术决策相匹配。每一项技术选择都有详细的依据说明。每一个架构决策都能追溯到具体的需求。在整个过程中,一致性验证持续提升质量。AI对规范进行分析,查找其中的模糊性、矛盾之处和空白之处,这并非是一次性的把关,而是持续不断的完善。

一旦规格说明及其实施计划足够稳定,代码生成就会开始,但它们不必是“完整的”。早期生成的代码可能是探索性的–测试规格说明在实际中是否合理。领域概念变成数据模型。用户故事变成API 端点。验收场景变成测试。这通过规范测试场景将开发和测试融合在一起,因为这些场景不是在代码编写之后才写的,而是生成实现和测试的规范的一部分。

反馈循环不仅限于初始开发阶段。生产指标和事故不仅会触发紧急修复,还会更新下一代的规格说明。性能瓶颈会成为新的非功能性需求。安全漏洞会成为影响所有未来版本的限制条件。在规格说明、实现和运营现实之间这种反复的互动中,真正的理解才会浮现,传统的软件开发生命周期也会转变为持续的演进。

为何SDD在当下至关重要

有三大趋势使得SDD中心不仅成为可能,而且成为必要:

首先,AI的能力已达到一个阈值,可以从自然语言规范可靠地生成可工作的代码。这并非是要取代开发者,而是通过自动化从规范到实现的机械性转译工作,来增强他们的效率。它能够放大探索和创造力,能够轻松支持“推倒重来”,支持增删和批判性思考。

其次,软件的复杂性呈指数级增长。现代系统集成了数十种服务、框架和依赖项。通过人工流程使所有这些部分与最初意图保持一致变得越来越困难。SDD通过规范驱动生成提供系统性的一致性。框架可能会演进为优先支持AI而非人类,或者围绕可复用组件进行架构设计。

第三,变化的步伐在加快。如今需求的变化速度比以往任何时候都要快得多。转型(Pivoting)不再是个例–而是常态。现代产品开发需要基于用户反馈、市场状况和竞争压力进行快速迭代。传统开发将这些变化视为干扰。每次转型都需要手动将变更在文档、设计和代码中进行传播。结果要么是缓慢、谨慎的更新,限制了速度,要么是快速、鲁莽的变更,累积了技术债务。

SDD 能够支持"假设/模拟"(what-if/simulation)实验,“如果我们需要重新实现或更改应用程序以满足业务需求,比如销售更多的 T 恤,那我们该如何实施和进行实验呢?”

SDD 将需求变更从障碍转变为常规工作流程。当规范驱动实现时,转型会成为系统性的再生,而非手动重写。在产品需求文档(PRD)中更改核心需求,受影响的实施计划会自动更新。修改用户故事,相应的API端点会重新生成。这不仅关乎初始开发,更关乎在不可避免的变化中保持工程进度。

核心原则

规范作为通用语: 规范成为主要的产物(artifact)。代码成为其在特定语言和框架下的表达。维护软件意味着不断改进规范。

可执行规范: 规范必须足够精确、完整且无歧义,以便能够生成可运行的系统。这消除了意图与实现之间的差距。

持续改进: 一致性验证是持续进行的,而非一次性通过的关卡。AI会持续分析规范中的模糊性、矛盾性和缺失之处。

研究驱动性上下文: 研究代理(Research agents)在整个规范制定过程中收集关键的上下文信息,调查技术选项、性能影响和组织约束。

双向反馈: 现实生产影响规范演进。指标、事件和运营经验成为规范改进的输入。

通过分支进行探索: 从同一份规范生成多种实现方法,以探索不同的优化目标–性能、可维护性、用户体验、成本。

实现方法

如今,实践SDD需要整合现有工具并在整个过程中保持纪律性。该方法可通过以下方式实施:

  • 使用AI助手进行迭代式规范开发
  • 借助研究代理收集技术背景信息
  • 通过代码生成工具将规范转化为实现
  • 调整版本控制系统以适应规范优先的工作流
  • 通过 AI 分析规范文档进行一致性检查

关键在于将规范视为事实的来源,而代码则是服务于规范的生成输出,而非相反。

通过命令简化 SDD

SDD方法论通过三个强大的命令得到了显著增强,这三个命令能够自动执行“规范 → 规划 → 任务分配”的工作流程:

/specify 命令

此命令将一个简单的功能描述(用户提示)转换为一个完整的、结构化的规范,并进行自动化的仓库管理:

  1. 自动功能编号: 扫描现有规范以确定下一个功能编号(例如,001, 002, 003)。
  2. 创建分支: 根据您的描述生成语义化的分支名称并自动创建该分支。
  3. 基于模板的生成: 根据您的需求复制并定制功能规格模板。
  4. 目录结构: 为所有相关文档创建正确的 specs/[branch-name]/ 结构。

/plan 命令

一旦有了功能规格说明,此命令就会创建一个全面的实施计划:

  1. 规范分析: 读取并理解功能需求、用户故事和验收标准。
  2. 符合章程: 确保与项目章程和架构原则保持一致。
  3. 技术转译: 将业务需求转换为技术架构和实现细节。
  4. 详细文档: 为数据模型、API合约和测试场景生成支持文档。
  5. 快速启动验证: 生成一份涵盖关键验证场景的快速启动(Quickstart)指南。

/tasks 命令

计划创建后,此命令会分析该计划及相关的设计文档,以生成一个可执行的任务列表:

  1. 输入: 读取 plan.md(必需),以及(如果存在)data-model.mdcontracts/research.md
  2. 任务推导: 将合约、实体和场景转换为具体任务。
  3. 并行化: 标记独立任务 [P] 并勾勒出可以安全并行的任务组。
  4. 输出: 在功能目录中写入 tasks.md,准备好由任务代理(Task agent)执行。

示例:构建聊天功能

以下是这些命令如何改变传统开发工作流的:

传统方法:

1
2
3
4
5
6
1. 在文档中编写 PRD (2-3 小时)
2. 创建设计文档 (2-3 小时)
3. 手动设置项目结构 (30 分钟)
4. 编写技术规范 (3-4 小时)
5. 创建测试计划 (2 小时)
总计: 约 12 小时的文档工作

使用命令的 SDD 方法:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# 步骤 1: 创建功能规范 (5 分钟)
/specify Real-time chat system with message history and user presence

# 这会自动创建:
# - 创建分支 "003-chat-system"
# - 生成 specs/003-chat-system/spec.md
# - 用结构化的需求填充它

# 步骤 2: 生成实施计划 (5 分钟)
/plan WebSocket for real-time messaging, PostgreSQL for history, Redis for presence

# 步骤 3: 生成可执行任务 (5 分钟)
/tasks

# 这会自动创建:
# - specs/003-chat-system/plan.md
# - specs/003-chat-system/research.md (WebSocket 库对比)
# - specs/003-chat-system/data-model.md (Message 和 User 模式)
# - specs/003-chat-system/contracts/ (WebSocket 事件, REST 端点)
# - specs/003-chat-system/quickstart.md (关键验证场景)
# - specs/003-chat-system/tasks.md (从计划推导的任务列表)

在 15 分钟内,您就拥有了:

  • 一份包含用户故事和验收标准的完整功能规范
  • 一份包含技术选择和理由的详细实施计划
  • 准备好用于代码生成的API合约和数据模型
  • 涵盖自动化测试和手动测试的全面测试场景
  • 所有文档都在一个功能分支中得到了妥善的版本控制

结构化自动化的力量

这些命令不仅节省时间,还能确保一致性和完整性:

  1. 无遗漏细节: 模板确保方方面面都得到考虑,从非功能性需求到错误处理。
  2. 可追溯的决策: 每个技术选择都与具体需求相关联。
  3. 活文档: 规范与代码保持同步,因为是规范生成了代码。
  4. 快速迭代: 在几分钟内更改需求并重新生成计划,而非数天。

这些命令通过将规范视为可执行的产物而非静态文档,体现了 SDD 的原则。它们将规范制定过程从一必要但令人讨厌的事情转变为开发的驱动力。

模板驱动的质量:结构如何约束大语言模型以获得更好的结果

这些命令的真正威力不仅在于自动化,还在于模板如何引导大语言模型(LLM)的行为,以产出更高质量的规范。这些模板充当了复杂的提示,以富有成效的方式约束了 LLM 的输出:

1. 防止过早陷入实现细节

功能规范模板明确指示:

1
2
- ✅ 关注用户需要什么(WHAT)以及为什么(WHY)
- ❌ 避免如何实现(HOW)(不涉及技术栈、API、代码结构)

这种约束迫使 LLM 保持恰当的抽象层次。当LLM可能自然地跳到“使用 React 和 Redux 实现”时,模板会使其专注于“用户需要其实时数据更新”。这种分离确保了即使实现技术发生变化,规范也能保持稳定。

2. 强制使用明确的不确定性标记

两个模板都强制要求使用 [NEEDS CLARIFICATION](需要澄清)标记:

1
2
3
当从用户提示创建此规范时:
1. **标记所有模糊之处**: 使用 [NEEDS CLARIFICATION: 具体问题]
2. **不要猜测**: 如果提示没有指明某事,就标记它

这防止了LLM 做出看似合理但可能不正确的假设的常见行为。LLM 不会猜测“登录系统”使用电子邮件/密码认证,而是必须将其标记为 [NEEDS CLARIFICATION: 未指定认证方法 - 电子邮件/密码、SSO、OAuth?]

3. 通过清单进行结构化思考

模板包含全面的清单,可作为规范的“单元测试”:

1
2
3
4
### Requirement Completeness - 需求完整性
- [ ] 不再有 [NEEDS CLARIFICATION] 标记
- [ ] 需求是可测试且无歧义的
- [ ] 成功标准是可衡量的

这些清单迫使 LLM 系统地自我审查其输出,从而发现那些可能被遗漏的漏洞。这就像是给了 LLM 一个质量保证框架。

4. 通过关卡实现章程合规性

实施计划模板(plan template)通过阶段性关卡(phase gates)来强制执行架构原则:

1
2
3
4
5
6
7
### Phase -1: Pre-Implementation Gates - 阶段 -1:实施前关卡
#### Simplicity Gate (Article VII) - 简约关卡(第七条)
- [ ] 使用的项目 ≤3 个?
- [ ] 没有面向未来的过度设计?
#### Anti-Abstraction Gate (Article VIII) - 反抽象关卡(第八条)
- [ ] 直接使用框架?
- [ ] 单一模型表示?

这些关卡通过让 LLM 明确地为任何复杂性辩护来防止过度设计。如果一个关卡未通过,LLM 必须在“复杂性跟踪”部分记录原因,从而为架构决策创建问责制。

5. 分层细节管理

模板强制实施适当的信息架构:

1
2
3
**重要**: 此实施计划应保持高层次和可读性。
任何代码示例、详细算法或冗长的技术规范
必须放在相应的 `implementation-details/` 文件中

这能避免常见的问题,即规格说明变成难以阅读的代码堆砌。LLM 学会保持适当的细节层次,将复杂内容提取到单独的文件中,同时使主文档易于浏览。

6. 测试先行思维

该实现模板强制执行先测试后开发的流程:

1
2
3
4
### 文件创建顺序
1. 在 `contracts/` 目录下创建 API 规范
2. 按顺序创建测试文件:合约 → 集成 → e2e → 单元
3. 创建源文件以使测试通过

这种顺序约束确保了 LLM 在实现之前就考虑可测试性和合约,从而形成更稳健且可验证的规范。

7. 防止臆测性功能

模板明确不鼓励臆测:

1
2
- [ ] 没有臆测性或“可能需要”的功能
- [ ] 所有阶段都有明确的前置条件和交付物

这能阻止 LLM 添加那些虽好但会使实现过程复杂化的“锦上添花”功能。每个功能都必须能追溯到一个具体的用户故事,并且有明确的验收标准。

复合效应

这些约束条件共同作用,从而产生出的规范具有以下特点:

  • 完整: 清单确保不会遗漏任何事项
  • 无歧义: 强制澄清标记突出不确定性
  • 可测试: 测试先行思维融入流程
  • 可维护: 适当的抽象层次和信息层级
  • 可实施: 明确的阶段和具体的交付成果

模板将LLM从一个创意作家转变为一个有纪律的规范工程师,将其能力引导到持续生产高质量、可执行的、真正驱动开发的规范上。

章程基础:强制执行架构纪律

SDD 的核心是一部章程–一套指导规范如何转化为代码的不可更改的原则。该章程(memory/constitution.md)充当着系统的架构DNA,确保每个生成的实现都保持一致性、简约性和高质量。

开发九条

章程规定了九条原则,涵盖了开发进程的各个方面:

第一条:库优先原则

每个功能都必须以一个独立的库开始–没有例外。这从一开始就强制采用模块化设计:

1
2
产品需求(Specify)中的每个功能都必须以一个独立的库开始其生命周期。
任何功能都不得在未首先抽象为可复用库组件的情况下直接在应用程序代码中实现。

该原则确保规范生成的是模块化、可复用的代码,而非单一的整体式应用程序。当LLM生成实施计划时,它必须将功能构建为具有清晰边界和最少依赖关系的库。

第二条:命令行界面规定

每个库都必须通过命令行接口(CLI)暴露其功能:

1
2
3
4
所有 CLI 接口必须:
- 接受文本作为输入(通过 stdin、参数或文件)
- 产生文本作为输出(通过 stdout)
- 支持 JSON 格式进行结构化数据交换

这强化了可观测性和可测试性。LLM无法将功能隐藏在不透明的类中–一切都必须可通过基于文本的接口进行访问和验证。

第三条:测试先行原则

这是最具变革性的一条–测试未行,代码不动:

1
2
3
4
5
这是**不可协商的**:所有实现必须遵循严格的测试驱动开发(TDD)。
在以下条件满足之前,不得编写任何实现代码:
1. 单元测试已编写
2. 测试已由用户验证和批准
3. 测试已确认为失败状态(红色阶段)

这完全颠覆了传统的AI代码生成。与生成代码并期望其能正常运行不同,LLM必须首先生成全面的测试来定义行为,获得批准后,才生成实现代码。

第七条与第八条:简洁与反抽象

这两条配对的条款防止了过度设计:

1
2
3
4
5
6
第 7.3 节:最小化项目结构
- 初始实现最多3个项目
- 增加项目需要有文档化的理由

第 8.1 节:信任框架
- 直接使用框架特性,而不是对其进行包装

当 LLM 可能自然地创建复杂的抽象时,这些条款迫使它为每一层复杂性做出解释。实施计划模板的“阶段-1 关卡”直接强制执行这些原则。

第九条:集成测试优先

优先考虑真实世界的测试,而不是孤立的单元测试:

1
2
3
4
测试必须使用真实环境:
- 优先使用真实数据库而非模拟(mocks)
- 使用实际服务实例而非存根(stubs)
- 在实现之前必须编写集成测试

这确保了生成的代码在实践中有效,而不仅仅是在理论上。

通过模板执行章程

该实施计划模板通过具体的检查点将这些条款付诸实践:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
### 阶段-1:实施前的关卡
#### 简约关卡(第七条)
- [ ] 使用的项目 ≤3 个?
- [ ] 没有面向未来的过度设计?

#### 反抽象关卡(第八条)
- [ ] 直接使用框架?
- [ ] 单一模型表示?

#### 集成优先关卡(第九条)
- [ ] 合约已定义?
- [ ] 集成测试已编写?

这些关卡充当了架构原则的编译时检查。LLM必须通过这些关卡,或者在“复杂性跟踪”部分记录合理的例外情况,才能继续进行。

不可变原则的力量

章程的力量在于其不可变性。尽管实现细节可以演变,但核心原则始终不变。这提供了:

  1. 时间上的连贯性: 今天生成的代码与明年生成的代码遵循相同的原则。
  2. 跨LLM的一致性: 不同的AI模型产出架构兼容的代码。
  3. 架构完整性: 每个功能都强化而非削弱系统设计。
  4. 质量保证: 测试先行、库优先以及简洁原则确保代码易于维护。

章程的演进

虽然原则是不可变的,但其应用方式却可以发展变化:

1
2
3
4
5
第 4.2 节:修订流程
对此章程的修改需要:
- 对变更理由的明确文档记录
- 项目维护者的审查和批准
- 向后兼容性评估

这使得方法论在保持稳定性的同时能够学习和改进。章程本身通过带有日期的修订记录展示了其演变过程,表明了原则如何能够基于真实世界的经验进行完善。

超越规则:一种开发哲学

章程不仅仅是一本规则手册,它还是一种塑造 LLM 如何思考代码生成的哲学:

  • 可观察性优于不透明性: 一切必须都能通过命令行界面进行检查。
  • 简约优于巧妙: 从简单做起,只有在证明有必要时才增加复杂性。
  • 集成优于隔离: 在真实环境中测试,而非人工环境。
  • 模块化优于单体: 每个功能都是一个具有清晰边界的库。

通过将这些原则嵌入到规范和规划过程中,SDD确保了生成的代码不仅功能正常,而且是可维护、可测试且架构合理的。章程将 AI 从一个代码生成器转变为一个尊重和增强系统设计原则的架构合作伙伴。

变革

这并非要取代开发者或自动化创造力,而是通过自动化机械式的转译工作来增强人类的能力。它是要创建一个紧密的反馈循环,让规范、研究和代码共同演进,每一次迭代都能带来更深的理解以及意图与实现之间更好的一致性。

软件开发需要更好的工具来保持意图与实现之间的一致性。SDD提供了一种通过可执行规范来实现这种一致性的方法,这些规范生成代码,而不仅仅是指导代码。