如今,应用程序的构建方式正在发生彻底的改变。
过去,编写和审查代码是最困难的部分。 但现在,关键在于如何有效地向 LLM 传达你想要构建的东西。
我的朋友们,这就是所谓的 规范驱动开发 (Spec-Driven Development)。
规范驱动开发已成为AI工程师或希望使用AI构建应用程序的人需要学习的最重要技能之一。
但它与你可能熟知的另一种常见技术——Vibe编码 (Vibe Coding) 有何不同? 让我们来一探究竟。
什么是Vibe编码?
人们在想到AI辅助编码或编码代理时,通常会想到Vibe编码。
让我给你一个Vibe编码的典型例子,然后我们再比较它与规范驱动开发的不同之处。
作为开发者或构建者,你通常会从你的AI编码代理开始,无论它是在浏览器中还是在你的本地机器上。
你从最初的提示开始。
你向LLM编写一个初始提示,说:“嘿,我想要一个具有某种功能、用特定语言(如Java或Python)编写的应用程序。”
graph TD
A[用户] --> B{编写初始提示};
B --> C[LLM];
C --> D{生成代码};
D --> E{用户};
E --> F{编辑提示};
F --> C;
C --> G{生成新代码};
G --> H((理想的实现));
这个提示被发送到模型。
模型会根据它认为你想要的东西以及它的训练数据开始生成代码。
此时,我们得到了一些样板代码。 这对于测试来说非常棒,这也是我喜欢Vibe编码的原因。
但问题是,我们可能没有得到我们想要的确切实现。
所以,我们会去编辑那个提示。 我们会说:“我想要一些不同的东西”,或者“使用一个不同的库”。
我们会在编辑提示和AI继续编码之间来回切换。
经过几次尝试,直到我们达到理想的实现状态。
这就是我们在进行Vibe编码时通常看到的情况。
但问题是,AI模型是如何根据我们给出的提示做出具体决策的? 我们可以对想要创建的应用进行一百次不同的尝试,每次都可能得到不同的结果。
这让很多人感到沮丧。
事实是,Vibe编码跳过了我们软件工程中习惯的传统 软件开发生命周期 (SDLC)。
传统的软件开发生命周期 (SDLC)
软件开发生命周期采用了一种稍微不同的方法。
graph TD
A[规划与设计] --> B[实现];
B --> C[测试];
C --> D[部署];
D --> E[维护];
我们通过使用特定的项目需求(通常称为 PRD)来规划和设计我们的项目。
然后,我们获取项目所需的内容,并开始实现这些功能。
一旦有了这些功能,我们就测试它们是否有效。 我们进行一些质量保证,然后进入部署阶段——从开发到预发布再到生产,最后是项目的维护。
深入了解:规范驱动开发
虽然Vibe编码非常棒,感觉就像魔法一样,但规范驱动开发采用了一种不同的方法。
它将一些软件开发生命周期的组件添加到了AI生成的软件开发中。
让我们看一个规范驱动开发的假设场景。
规范驱动开发同样会利用LLM作为AI代理来编写代码或运行测试。
但一切都始于提示。
关键是,我们不是在提示一个具体的实现。 我们是在提示我们希望系统做什么——即 行为 和我们想要的 约束。
这个特定的 规范 (Specification) 就像一份合同,被用来创建一份需求文档。
这份需求文档将成为项目工作方式的主要层级结构。
graph TD
A[用户] --> B{提示 (行为/约束)};
B --> C[LLM];
C --> D{生成规范};
D --> E{用户审查};
E -- 批准 --> F{生成设计文档};
E -- 编辑 --> D;
F --> G{用户审查};
G -- 批准 --> H[AI 实现];
G -- 编辑 --> F;
模型和代理如何编写代码、进行测试、编写文档、进行验证等等,都将围绕这份需求文档展开。
如果我们对这些需求满意,我们可以批准并说:“是的,我希望将这份需求规范转化为一个设计文档,其中包含每个具体实现的待办事项。”
或者,我们可以说:“嘿,我想编辑我希望这个项目如何实现的方式。”
因为在这一点上,还没有任何东西被实现。 而AI模型的核心在于正确的指令。
拥有这样的规范,远比让LLM猜测哪个解决方案可能最适合用户的请求要好得多。
我们从设计出发,如果我们对设计以及希望它如何被实现为代码感到满意,那么我们就可以让模型去实现它。
这就是规范驱动开发的工作原理。
[!TIP] 规范驱动开发将传统的开发模型颠覆过来,使规范成为驱动所有下游工作(如实现和测试)的主要产物。
开发范式的演变
让我们快速回顾一下开发周期的演变,以更好地理解规范驱动开发的定位。
- 传统开发
- 我们首先编写 代码。
- 然后,我们才编写 文档。
- 我们从直觉出发,然后继续前进。
- 测试驱动开发 (TDD)
- 我们从 测试 开始,定义我们希望应用程序具有的功能行为。
- 然后,我们才去编写 代码。
- 这也是一种非常流行的开发方法。
- 规范驱动开发 (Spec-Driven Development)
- 它将整个模式颠覆了过来。
- 我们从 规范 (Specs) 开始。
- 然后进入 设计文档 和需求。
- 最后才是 代码 的实现。
它就像是测试驱动开发和行为驱动开发的“超级版”,这真的非常酷。
实践中的差异:一个例子
让我们通过一个例子来具体感受一下。
Vibe编码的方式
使用Vibe编码,我们只是与模型对话,进行快速的即时编辑。
我们可能会说:
“嘿,我们需要一个
/login页面,让我们的用户进行身份验证。”
这是一个很好的请求。 但我们怎么知道模型会做什么呢? 它可能有30种不同的实现方式,我们可能需要与模型来回沟通。 这有时比我们自己编写代码还要耗时。
规范驱动开发的方式
规范驱动开发的方法则有所不同,当然,它仍然使用LLM来创建我们对这个功能的需求。
在这种情况下,我们将定义一个新功能。
feature: user_authentication
description: "Handles user login and authentication."
endpoint: /login
method: POST
parameters:
- name: user
type: string
description: "The username for authentication."
- name: pass
type: string
description: "The password for the user."
failure_cases:
- condition: "Missing username"
response: "400 Bad Request - Username is required."
test_cases:
- scenario: "Valid credentials"
expected_response: "200 OK"
- scenario: "Invalid credentials"
expected_response: "401 Unauthorized"
这个新功能是 用户身份验证。 我们还没有开始实现,这只是规划阶段。
- 我们定义它将是一个位于
/login的端点,用于处理POST请求。 - 然后,我们明确指出将接受两个变量:
user和pass,用于用户名和密码。 - 这样,当实现开始时,我们就清楚地知道为什么会得出这个结论。
- 我们还定义了失败回退,比如,如果缺少用户名,会发生什么。
- 我们甚至可以从这里生成测试用例,比如“有效凭据”应返回
200状态码。
这真的非常酷,因为当我们在进行AI辅助编码时,我们为编码代理减少了模糊性。
我们可以使用规范驱动开发来颠覆传统的开发模型。 规范成为了驱动所有下游工作(如实现和测试等)的主要产物。