大厂集体押注 SDD!阿里、腾讯、亚马逊都在用的规范驱动开发,优势在哪?坑怎么避?

亚马逊 Kiro 因内置 Spec 工作流而出圈,阿里 Qoder 的 Quest Mode 是采用 Spec 驱动的 AI 自主编程,腾讯云 CloudBase AI Toolkit 同样集成了 Spec 工作流......随着越来越多头部厂商的采用,规范驱动开发(Spec-Driven Development,SDD)正成为 AI 编程中的新兴范式。本文深入探讨 SDD 的核心概念,将其划分为规范优先、规范锚定和规范即源码三个层次,分析该方法在实践中的优势与挑战,并审视其是否正在重演“模型驱动开发”(Model-Driven Development,MDD)的历史困境。
欢迎订阅合集 AI 博客精选:精心编译海外技术厂商发布的高质量 AI 领域博客文章。
目录
什么是规范驱动开发?
规范 (spec) 到底是什么?
评估 SDD 工具的挑战
工具剖析:Kiro
工具剖析:spec-kit
工具剖析:Tessl 框架
观察和疑问
个人思考
什么是规范驱动开发?
在 AI 编程领域,规范驱动开发 (Spec-Driven Development, SDD) 是一个定义尚在变化中的新术语。根据目前的观察,SDD 的核心理念似乎是指在利用 AI 编写代码之前,首先编写一份规范(spec),即文档先行。这份规范将成为人类开发者与 AI 共同的事实来源。
不同的工具和平台对它有各自的理解。例如,GitHub 认为,在 AI 编程这个新世界里,维护软件意味着演进规范,软件的通用语言被提升到了一个更高的层次,而代码则成了“最后一英里”的实现方法。Tessl 则将其定义为一种开发方法,规范(而非代码)是主要的产物,规范使用结构化、可测试的语言来描述开发意图,然后由 AI 编码 Agent 生成与之匹配的代码。在研究了这些术语的用法和相关工具后,我认为 SDD 在实践中存在三个层次:
1. 规范优先 (Spec-first):这是最基础的层面,开发者首先编写一份深思熟虑的规范,然后在当前任务的 AI 辅助开发工作流中使用这份规范。
2. 规范锚定 (Spec-anchored):在任务完成后,规范并不会被丢弃,而是被保留下来,以便在后续对该功能进行演进和维护时继续使用。
3. 规范即源码 (Spec-as-source):这是最激进的层面,规范在时间推移中成为项目的主要源文件,人类开发者只编辑规范,永远不会直接修改代码。
并非所有工具都追求达到“规范锚定”或“规范即源码”的程度,目前所见的所有 SDD 方法和定义都属于“规范优先”,这些工具对于规范在长期维护中的策略,往往表述得含糊不清,或者完全开放。这三者是层层递进的关系:“规范锚定”建立在“规范优先”的基础上,而“规范即源码”又建立在“规范锚定”的基础上。
规范 (spec) 到底是什么?
在 SDD 的讨论中,关键问题自然是:规范 (spec) 究竟是什么?目前似乎还没有一个公认的定义。我所见到的最接近一致的定义,是将规范比作一份产品需求文档 (Product Requirements Document)。
规范这个词目前被严重滥用了。根据我的尝试将其定义为:规范是一种结构化的、面向行为的产物(或一组相关产物),它使用自然语言编写,用以表达软件功能,并作为 AI 编码 Agent 的指导。 每种 SDD 的变体都会定义各自的规范结构、详细程度以及这些产物在项目中的组织方式。
我认为,在规范与代码库的通用上下文文档之间做出区分是很有用的。通用上下文指的是诸如规则文件、产品的高阶描述或代码库架构说明等内容。有些工具将这种上下文称为记忆库(memory bank),因此这里也沿用这个叫法。这些记忆库文件与代码库中所有的 AI 编码会话都相关;而规范则不同,它只与那些创建或更改特定功能的特定任务相关。例如,记忆库可能包含 AGENTS.md 或 architecture.md 这样的文件,而规范可能是针对某个具体故事(如 Story-324.md)或某个特定功能(如 feature-x 文件夹下包含 data-model.md 和 plan.md)的文档。
评估 SDD 工具的挑战
事实证明,要以接近真实使用的方式来评估 SDD 工具及其方法,是相当耗时的。你必须在不同规模的问题上尝试它们,包括全新的项目( Greenfield Project)和已有的遗留项目(Brownfield Project),你还需要真正花时间去审查和修订那些中间产物,而不能只是粗略地扫一眼。正如 GitHub 关于 spec-kit 的博文所说:至关重要的是,你的角色不仅仅是引导,更是要验证。在每个阶段,你都需要反思和提炼。
对于我尝试的三种工具中的两种来说,将它们引入现有的代码库似乎需要做更多的工作,这使得评估它们在遗留项目代码库中的用处变得更加困难,,我对这种模式在真实项目中如何运作仍然抱有许多疑问。
例如,评估者需要投入大量时间来学习工具的特定工作流,理解其规范的组织方式,并适应 AI 生成的中间产物。在遗留项目中,工具需要理解大量现有代码的上下文,这本身就是一个巨大的挑战。如果工具生成的规范或代码与现有逻辑不匹配,开发者需要花费更多时间去调试和修正,这个成本可能远高于传统开发方式。因此,缺乏来自真实、长期项目的反馈,使得我们很难判断 SDD 究竟是提高了效率,还是仅仅增加了不必要的复杂性。
工具剖析:Kiro
三种工具中,Kiro 是最简单(或最轻量级)的一个。它似乎主要停留在“规范优先”的层面。所有例子都只是用它来处理一个任务或一个用户故事,没有提到如何在多个任务中随时间推移,以“规范锚定”的方式来使用需求文档。
Kiro 的 spec 流程被设计为三个步骤:需求 (Requirements) → 设计 (Design) → 任务 (Tasks)。每个工作流步骤都由一个 Markdown 文档表示,Kiro 会在引导你完成这三个步骤。
首先是需求文档。它被构建为一个需求列表,每个需求代表一个“用户故事” (User Story),采用“作为...(As a...)”的格式。同时,每个需求都配有验收标准,采用“假如... (GIVEN...) 当... (WHEN...) 则... (THEN...)”的格式。
接下来是设计文档。设计文档包含了组件架构图,以及诸如数据流、数据模型、错误处理、测试策略、实现方法和迁移策略等部分。(不确定这是一个固定的结构,还是会根据任务的不同而变化。)
最后是任务文档。这是一个任务列表,这些任务可以追溯到需求文档中的编号。Kiro 为这些任务提供了一些额外的界面元素,允许你逐个运行任务,并审查每个任务带来的变更。每个任务本身是待办事项的列表,并以相关的需求编号(如 1.1, 1.2, 1.3)结尾。
Kiro 也有记忆库的概念,称之为 steering 功能。其内容是灵活的,并且其的工作流程似乎并不依赖于任何特定文件的存在。当你要求 Kiro 生成引导文档时,它创建的默认拓扑是 product.md(产品说明)、structure.md(结构说明)和 tech.md(技术栈说明)。
工具剖析:spec-kit
spec-kit 是 GitHub 版本的 SDD 实现。它以命令行界面 (CLI) 的形式分发,可以为多种常见的编码助手创建工作区设置。一旦结构设置完毕,你就可以在编码助手中通过斜杠命令 (slash commands) 与 spec-kit 互动。由于它的所有产物都直接放入你的工作区,这使得它在三者中成为最可定制的一个。
spec-kit 的工作流程是:宪章 (Constitution) → 循环执行 [ 规范 (Specify) → 计划 (Plan) → 任务 (Tasks) ]。
spec-kit 的记忆库概念是其规范驱动方法的先决条件,他们称之为宪章 (Constitution)。宪章应该包含那些不可变的且应始终应用于每次变更的高级原则。它基本上是一个非常强大的规则文件,在工作流程中被大量使用。
在工作流程的每一步(规范、计划、任务),spec-kit 都会借助一个 bash 脚本和一些模板来实例化一组文件和提示。然后,工作流会大量使用文件内部的清单,来跟踪用户需要澄清的事项、违反宪章的情况、研究任务等。它们就像是每个工作流步骤的“完成态定义”,不过是由 AI 来解释的,所以并不能 100% 保证它们会被遵守。
spec-kit 的一个特点是,一份规范是由许多文件组成的。例如,一个规范文件夹可能包含数据模型 (data-model)、计划 (plan)、任务 (tasks)、规范 (spec)、研究 (research)、API 和组件 (component) 等多个 Markdown 文件。
乍一看,GitHub 似乎渴望实现一种“规范锚定”的方法。他们声称在重新思考规范,使其不是静态文档,而是随项目演进的、可执行的、有生命的产物,成为共享的事实来源。但 spec-kit 会为创建的每个规范创建一个新的代码分支 ,这似乎表明他们将规范视为一个变更请求生命周期内的产物,而不是一个功能特性的完整生命周期的产物。这让我认为,spec-kit 仍然只停留在“规范优先”的层面,而不是真正的“规范锚定”。
工具剖析:Tessl 框架
Tessl 框架 目前仍处于私有测试阶段,与 spec-kit 类似,它也是一个 CLI 工具,可以为各种编码助手创建所有工作区和配置结构。
Tessl 是这三款工具中唯一一个明确追求“规范锚定”方法,甚至在探索“规范即源码”层面的工具。Tessl 的规范可以作为被维护和编辑的主要产物,其生成的代码文件顶部甚至会标记注释,如 // GENERATED FROM SPEC - DO NOT EDIT (由规范生成 - 请勿编辑)。
规范和代码文件之间目前是 1:1 映射,即一个规范文件会转换成代码库中的一个文件。但 Tessl 仍处于测试阶段,他们正在试验不同的版本,后续也可能发展到一个规范映射到具有多个文件的代码组件的级别。
我使用 Tessl CLI 从一个现有代码库的 JavaScript 文件中逆向出了一份规范,这份规范文件包含了诸如 @generate 或 @test 之类的标签,似乎是用来告诉 Tessl 要生成什么内容。其 API 部分展示了一种思路,即至少在规范中定义暴露给代码库其他部分的接口,这大概是为了确保生成组件中这些更关键的部分完全处于维护者的控制之下。运行 tessl build 命令,就可以为这份规范生成相应的 JavaScript 代码文件。
将“规范即源码”的规范置于一个相当低的抽象层次(每个代码文件对应一个规范),可能会减少 LLM 需要执行的步骤和解释,从而降低出错的几率。不过即使在这种低抽象层次上,在从同一份规范多次生成代码时,也存在不确定性。为了提高代码生成的可重复性,我不断迭代和完善规范,使其越来越具体。
观察和疑问
这三种工具都自称为规范驱动开发的实现,但它们彼此之间差异很大。因此,在谈论 SDD 时,首先要记住的是,它指的并不是某一个事物,我在试用后,产生了一些关键的观察和疑问。
一个工作流能适应所有规模吗?
Kiro 和 spec-kit 都提供了各自固定的工作流,但我很确定它们都不适用于现实生活中绝大多数的编码问题。特别是,我不清楚它们如何能满足不同问题规模的需求,以至于能被普遍适用。 当我让 Kiro 修复一个我过去用来测试 Codex 的小 bug 时,我很快发现这个工作流就像杀鸡用牛刀。需求文档把这个小 bug 变成了 4 个用户故事,总共 16 条验收标准。当我使用 spec-kit 时也遇到了类似的挑战,我不确定该用它来解决多大规模的问题。它的步骤太多,创建的 Markdown 文件也太多,对于一个中等大小的功能(比如一个 3-5 个故事点的功能)来说,这感觉像是小题大做。
审查 Markdown 还是审查代码?
spec-kit 创造了大量的 Markdown 文件让我审查,这些文件内容重复,而且与已有的代码也重复。它们非常冗长,审查起来很乏味。Kiro 的情况稍好,因为它只有 3 个文件,理解“需求 > 设计 > 任务”的心智模型也更直观。但对于我要求修复的小 bug 来说,Kiro 也显得过于冗长了。老实说,我宁愿审查代码也不愿审查这些 Markdown 文件。
虚假的控制感?
即使有了所有这些文件、模板、提示、工作流和清单,我仍然经常看到 AI 编码 Agent 最终没有遵循所有的指令。虽然现在 LLM 的上下文窗口更大了,但这并不意味着 LLM 会正确地理解其中的所有内容。例如,spec-kit 在规划阶段有一个研究步骤,它对现有代码做了大量研究,这很,但最终编码 Agent 没有意识到这是已有代码的描述,只是把它们当作新的规范,重新生成了一遍,造成了重复。此外,我也看到了 编码 Agent 因为过于急切地遵循指令(例如宪章中的某条)而做得过火的情况。过去的经验表明,保持控制的最佳方式是小步、迭代。因此,我对这种需要大量前期规范设计的做法持怀疑态度。
如何有效分离功能规范与技术规范?
在 SDD 中,一个普遍的想法是刻意分离功能规范和技术实现。这种渴望的背后,大概是希望我们最终能让 AI 填充所有的解决方案和细节,并能用同一份规范切换到不同的技术栈。但在现实中,当我尝试 spec-kit 时,我经常搞不清楚什么时候该停留在功能层面,什么时候该添加技术细节。
目标用户是谁?
许多 SDD 工具的演示和教程都包含了定义产品和功能目标的内容,甚至引入了“用户故事”这样的术语。这可能是想利用 AI 作为跨技能的推动者,让开发者更深入地参与需求分析吗?还是让开发者与产品经理结对工作?但这些都没有明说。这又回到了问题规模的疑问上:SDD 到底适用于什么场景?
规范锚定与规范即源码:我们从历史中吸取教训了吗?
虽然许多人将 SDD 与 TDD (测试驱动开发) 或 BDD (行为驱动开发) 相提并论,但我认为还有一个重要的平行对比值得关注,那就是 MDD (Model-Driven Development,模型驱动开发),尤其是对于“规范即源码”而言。我职业生涯早期曾在几个严重依赖 MDD 的项目上工作过,当我尝试 Tessl 框架时,我不禁回想起了那段经历。MDD 中的模型基本上就是规范,尽管不是用自然语言,而是用定制的 UML 或文本 DSL (领域特定语言) 来表达。我们构建自定义的代码生成器来将这些规范转换成代码。最终,MDD 并未在商业应用中流行起来,它处于一个尴尬的抽象层次,制造了过多的开销和约束。LLM 消除了 MDD 的一些开销和约束,因此人们又燃起了新的希望,希望我们现在终于可以专注于编写规范,然后直接生成代码了。有了 LLM,我们不再受限于预定义的、可解析的规范语言,也不必构建复杂的代码生成器。当然,为此付出的代价是 LLM 的不确定性。而且,可解析的结构也有其优势,比如我们可以为规范作者提供大量的工具支持,以编写有效、完整和一致的规范。
我在想,“规范即源码”,甚至“规范锚定”,是否会最终同时继承 MDD 和 LLM 的缺点:既僵化不灵活,又具有不确定性。我们应该回顾过去从规范生成代码的尝试,以便在今天探索 SDD 时吸取教训。
个人思考
在我个人使用 AI 辅助编程的过程中,我也经常会花时间先精心制作某种形式的规范,然后交给编码 Agent。因此,在许多情况下,“规范优先”的总体原则绝对是有价值的。目前,从业者最常问的问题就是:“我该如何构建我的记忆库?”以及“我该如何为 AI 编写一份好的规范和设计文档?”。
关于尝试过的这些工具,我对它们在现实世界中的实用性提出了许多疑问。我在想,它们中的一些是否正试图把我们现有的工作流过于字面地“喂”给 AI 编码 Agent,最终放大了现有的挑战,如审查过载和 AI 幻觉。尤其是那些依赖大量细碎文件的方法,我不禁想到德语中的一个复合词——“Verschlimmbesserung”:我们是否在试图改进某个流程时,却适得其反,使其变得更糟?
版权声明: 本文为 InfoQ 作者【莫尔索】的原创文章。
原文链接:【http://xie.infoq.cn/article/40a7c8806fb98d3aade3caff7】。文章转载请联系作者。







评论