从 vibe coding 到 spec-driven development

TL;DR · AI 摘要
本文探讨了从 vibe coding 转向 spec-driven development 的必要性和实践方法,强调了后者在团队协作和项目管理中的优势。
核心要点
- Vibe coding 适用于简单项目,但在大型项目中缺乏最佳实践和共享规范。
- Spec-driven development 强调先进行架构决策和需求定义,再进行实现,有助于团队协作和项目管理。
- Andrej Karpathy 提出 agentic engineering 概念,强调通过详细规范和人工监督来协调代理进行开发。
结构提纲
按章节快速跳转。
- §引言
介绍从 vibe coding 到 spec-driven development 的背景和动机。
比较两种开发模式的优缺点。
讨论 vibe coding 在大型项目中的问题。
介绍 spec-driven development 如何解决这些问题。
- §实践案例
作者通过一个个人项目展示如何应用 spec-driven development。
思维导图
用一张图看清主题之间的关系。
查看大纲文本(无障碍 / 无 JS 友好)
- From Vibe Coding to Spec-Driven Development
- 引言
- Vibe coding vs Spec-driven development
- Vibe coding 的局限性
- Spec-driven development 的优势
- 实践案例
金句 / Highlights
值得收藏与分享的关键句。
主要的问题是缺乏最佳实践和共享规范。例如,没有结构化的方法,团队很容易在同一个 DBT 管道中出现五种不同的 ML 模型训练方式。
Spec-driven development (SDD) 更接近传统的工程实践。我们不是直接跳入实现,而是先自己进行深入思考:做出架构决策,定义需求,并将这些内容记录在存储库中的结构化 Markdown 规范中,与项目一起更新。
即使是提出“vibe coding”概念的 Andrej Karpathy 也在一年后承认,这个时代即将结束,我们将进入 agentic engineering 时代——通过详细规范和人工监督来协调代理进行开发。
从氛围编码到规范驱动开发
我在之前的文章《从代码到洞察:数据分析师的软件工程最佳实践》中提到,工程技能和最佳实践对分析师和其他数据专业人士来说非常有用。
在人工智能时代,这一点更加明显,我们有更多机会构建自己的分析工具:从展示图表或不同场景的高级数据查看器,到可以根据输入参数预测结果的模拟器。我个人在日常工作中经常使用网络应用程序。
关于氛围编码有很多炒作,但似乎专业工程师已经开始超越它,更倾向于规范驱动开发。甚至“氛围编码”这一术语的创造者 Andrej Karpathy 也在 2025 年 2 月 承认,仅仅一年后,这个时代即将结束,我们正在进入代理工程的时代——在人类监督下根据详细规范协调代理。
_今天(一年后),通过 LLM 代理编程正逐渐成为专业人士的默认工作流程,只是增加了更多的监督和审查。目标是在利用代理的同时,不牺牲软件的质量。许多人试图为此找到一个更好的名称以区别于氛围编码,我个人目前最喜欢的是“代理工程”:
– “代理”是因为新的默认做法是你 99% 的时间不会直接编写代码,而是协调代理并进行监督。
– “工程”强调这是一门艺术与科学,需要专业知识。你可以学习并变得更好,它有自己的深度。_
在这篇文章中,我想在一个绿地项目中实践规范驱动开发,遵循 JetBrains 在 DeepLearning.AI 课程《规范驱动开发与编码代理》中的最佳实践。
这个项目有点个人化,但仍与数据相关。随着我准备九月份的半程马拉松,我正在努力平衡跑步和力量训练。市面上有那么多工具,每个工具都专注于旅程的不同部分,找到真正适合我的解决方案出乎意料地困难。因此,我决定一石二鸟:一边构建自己的网络应用,一边希望在这个过程中学到新东西。
准备好行动了吗?我也准备好了。但在我们开始实施之前,先花几分钟了解一下规范驱动开发背后的理论。
氛围编码 vs 规范驱动开发
我们很多人都已经体验过氛围编码:你写一个简短的提示(例如,“请在我的网络应用中添加一个 DAU 图表”),等待代理生成更改,本地运行并检查结果是否符合预期。
通常,结果并不符合预期。于是你回到同一个聊天窗口,要求代理调整图表,并不断迭代直到结果足够好。
这种方法对于简单的项目来说效果还算不错,但在多个开发者共同处理同一代码库时,扩展性较差。
主要的问题在于缺乏最佳实践和共享规范。例如,没有结构化的方法,团队很容易在同一个 DBT 管道中出现五种不同的机器学习模型训练方式。
另一个常见问题是,我们通常不会持久化与 AI 代理对话的结果或推理。因此,很容易忘记某些决策的原因。例如,代理可能会忘记你为什么以特定方式清理数据,下次更新时可能会悄悄引入不同的结果。
上下文衰减也是一个特别常见的问题。AI 代理是无状态的,当处理较大的项目时,我们经常因为上下文窗口限制而不得不开始新的聊天,实际上是从头开始沟通。
规范驱动开发(SDD)更接近传统的工程实践。我们不是直接跳入实现,而是先自己进行深入思考:做出架构决策,定义需求,并将这些内容记录在存储于仓库中的结构化 Markdown 规范中,并随项目一起更新。这带来了一个重要的转变:我们将规范(我们要构建什么以及为什么)与实现(实际代码)解耦。
SDD 通过在会话间(甚至在不同的 AI 代理间)保留上下文,同时使人类和代理围绕项目的非谈判核心达成一致,解决了氛围编码的核心问题。
SDD 工作流
典型的规范驱动开发工作流通常包括以下几个阶段。
第一步是定义宪法——即项目的关键决策协议。它通常包括几个核心文档:
- 使命解释了“为什么”:我们为什么要构建这个项目,它的关键目标和功能是什么?
- 技术栈记录技术决策,以及部署和更新过程。
- 路线图概述了项目阶段、计划的功能,并随着项目的进展不断更新。
规范可以为新项目和现有项目创建,这使得这种方法非常灵活。
一旦项目级别的文档就绪,我们可以进入功能开发阶段,该阶段通常包括:
- 理解我们要构建的内容并编写详细规范。
- 实现更改。
- 验证实现是否符合预期。
成功实现第一个功能后,你可能会立即想要继续下一个功能。但其实这是暂停和重新思考的最佳时机。
这就是重新规划的阶段。这是一个专门的阶段,用于回顾项目章程,审查之前的功能决策和计划,确保它们仍然与项目目标一致。
现在我们已经了解了理论,让我们将其付诸实践。
构建
够了理论,是时候开始构建了。为了更好地理解规范驱动开发在实际中的工作方式,我决定将其应用于一个真正的绿地项目。
我首先为此项目创建了一个新的仓库(当然,花了一半的时间选择名称和标志):仓库。我还在我项目的 README.md 文件中记录了初始产品愿景。
规范驱动开发方法的一个优点是它对 LLM、代理或 IDE 的选择具有很大的灵活性,因此你可以使用你喜欢的任何设置。对于这个项目,我将使用带有 Claude Code 插件的 Visual Studio Code,因为它允许我在编辑器中直接使用 Claude 作为代理并审查所有代码更改。
创建章程
正如我们所讨论的,第一步是编写章程。当然,我们不需要手动完成,可以使用 LLM 基于初始产品愿景以及通过后续问题收集的附加上下文来生成章程。
我们正在构建 Trainlytics,一个个人健身追踪网络应用,
专为希望比标准健身应用提供更多控制、灵活性和洞察力的人群设计。
完整的功能需求请参见 README.md。
让我们在 specs 目录中创建一个“章程”,包括以下部分:
- mission.md - 我们在构建什么以及为什么;产品的主要使命
- tech-stack.md - 核心技术决策
- roadmap.md - 按实施顺序划分的项目阶段
重要提示:你必须使用你的 AskUserQuestion 工具获取我的反馈。然后,代理会提出一系列澄清问题,帮助定义项目章程并创建初步的实施计划。

图片由作者提供
最终,代理创建了我们要求的三个文件。

图片由作者提供
此时,你可能会有立即要求代理开始构建项目的冲动,但这可能为时过早。
在继续之前,我们需要验证和细化章程。现在花时间对计划达成一致是值得的,因为这个规范后来将转化为数千行代码。及早解决模糊性和错误会更好。
我通常通过自己阅读文档并与代理迭代来完成这一步,提出澄清问题并逐步完善计划。一个好的做法是通过代理进行所有更改,而不是自己修补文档,以保持项目的一致性。例如,我告诉代理我们需要在应用中加入身份验证,因为我的用例是从桌面和移动设备记录锻炼。这导致了技术栈文档和路线图的更新。

图片由作者提供
一旦你对审查满意,还可以要求另一个具有新鲜上下文的代理来批评计划。有大量证据表明反思可以提高输出质量。
当所有检查都完成后,是时候将章程提交到仓库中了。
第一个功能阶段
现在,是时候进入第一个功能阶段了。
根据我们的路线图,我们将从 MVP:核心活动记录 开始。在这个阶段结束时,用户应该能够在桌面和移动设备上登录,记录跑步和健身房训练,并在他们的历史记录中查看这些活动的全部细节。
正如我们所讨论的,每个功能阶段都遵循一个简单的周期:计划 → 实现 → 验证。所以让我们先定义规范并制定计划。
在 specs/roadmap.md 中找到下一阶段,并创建一个新的分支,
询问我关于规范中任何不清楚的步骤。
然后在 specs/ 下创建一个格式为 YYYY-MM-DD-feature-name 的新目录,
用于此功能,包含以下文件:
- plan.md - 编号任务组的结构化列表
- requirements.md - 范围、关键决策和上下文
- validation.md - 如何定义成功并确认实现可以合并
使用 specs/mission.md 和 specs/tech-stack.md 作为指导。_提示:在 LLM 代理中启动一个具有清晰上下文的新会话是有价值的。_
代理很快就整理好了规范。

图片由作者提供
此时,再次审查规范并确保一切与原始愿景一致是很重要的。如你所见,在代理工程中,开发者的角色转向了指导、审查和做出架构决策,而不是直接编写规范或代码。
一旦你对计划满意,就可以开始实施了。我更喜欢分别实现每个任务组,而不是一次性完成整个功能阶段,但这取决于功能的大小。对于这个项目,我使用了以下提示。
从 2026-05-04-phase-1-mvp/plan.md 中的下一个任务组开始实施。 使用 requirements.md 和 validation.md 作为指导。 完成后,在计划和验证文档中更新状态。
当代码准备就绪后,就到了审查阶段。这是最重要的步骤之一,因此值得在这里投入一些时间。
在与数据相关的应用程序中,我通常会重点关注核心业务逻辑,并检查数字是否符合我的预期。
我必须承认,我对前端技术几乎一无所知,因此很少详细审查前端代码。相反,我只是在本地测试界面,检查一切是否按预期工作。在这种情况下,我决定运行应用程序并看看它的表现如何。
经过几次与代理的迭代,我们成功地在本地运行了应用程序,并且它能够正常工作。我们已经可以添加不同的练习和活动类型,并记录有氧和力量训练。

图片由作者提供
手动审查之后,使用反思并让新的代理验证实现是否与计划一致,以及检查 validation.md 中定义的要点也是很有用的。
理论上,基于规范的开发建议功能阶段以验证结束。但在实践中,这很少能如此顺利。你可能会发现某些部分的实现不符合预期。在这种情况下,你有两个选择:
- 在
plan.md中再增加几个迭代,继续完善功能(这适用于较小的更改),或者 - 如果问题较为严重,将其视为下一功能阶段的一部分,并在重新规划时处理它们。
需要注意的一点是:直接向 LLM 代理解释问题并要求修复,而不是更新规范和重新实现,这种捷径可能会很诱人。尽量避免这种捷径。保持规范作为事实来源是使这种方法稳健的关键。
所有检查完成后,我们可以创建并合并 拉取请求。
此时,我们已经有一个可以工作的应用程序,结果确实令人满意。更令人惊讶的是,整个过程仅用了两个多小时(包括在代理工作时起草这篇文章的时间)。
重新规划
取得如此好的进展后,你可能会有继续构建的冲动。我理解这一点,但在当前的人工智能时代,人类的主要价值在于思考和架构。因此,现在实际上是退一步反思的好时机:我们是否仍然希望继续沿着同一个方向前进,我们应该在产品和流程中做出哪些改变?
当我开始自己使用这个应用程序时,我意识到它还不能完全支持我的用例。这意味着我们需要重新优先排序,以便我尽快能够在日常生活中使用它。因此,我使用了以下提示进行了重新规划。
让我们在 roadmap.md 中修订我们的计划。
我会按照以下顺序优先考虑接下来的阶段:
1. 力量训练模板
我可以没有计划功能,但需要模板,因为我经常记不住一个训练中的所有练习。
想法是:
- 如果日志中已存在模板,显示所有统计数据(练习、组数、次数、重量等)。允许编辑这些值并提交更改
- 如果有任何更改,询问用户是否要更新模板
2. 用户界面改进
当前的设计还不够精美,因此我会优先进行一轮用户界面改进:
- 在网站上添加标志和产品口号
- 添加设置标签以管理活动类型和练习
- 创建一个单一屏幕来记录有氧和力量训练
- 改进历史屏幕,提供更多活动详情
- 允许为活动(力量/有氧训练)和段落添加标题
- 支持指定时间,而不仅仅是日期
- 为界面添加更多颜色(我喜欢蓝色调)
- 对于有氧运动,调整单位为:分钟、公里和每公里配速
3. 基本分析
在历史屏幕上添加简单的分析,显示页面顶部的每周统计数据(例如,有氧和力量训练的总分钟数和卡路里消耗)重新规划也是回顾我们自身流程的好时机。例如,我注意到我们没有一致地更新 roadmap.md,规范开始偏离。引入变更日志也很有用,这样我们就可以清楚地了解产品随时间的演变。
让我们请代理为我们完成这些任务。
请审查 plan.md,更新 roadmap.md 以反映已完成的工作,
并创建一个 CHANGELOG.md 文件,简要总结变更内容。现在我们已经在方向上达成一致,并且有了正确的设置,让我们继续构建。
下一阶段
现在我们可以遵循相同的过程,通过各个阶段进行迭代。由于这是一个可重复的循环,讨论可能的自动化是一个好时机。
到目前为止,我们一直在手动编写所有提示,但这些工作流也可以作为“技能”在 Claude Code 或其他 LLM 编码代理中自动化。
此外,已经有一些现成的基于规范的开发实现。最流行的一个是由 GitHub 开发的 Spec Kit。
你可以像这样安装它。
uv tool install specify-cli --from git+https://github.com/github/spec-kit.git
specify version # 检查是否安装成功接下来,你需要在 Claude 中初始化这些技能。这将设置 .specify/ 文件夹并在 .claude/commands/ 中安装斜杠命令。
specify init . --integration claude
# 有 30 种与代理的集成方式,请指定你正在使用的集成方式当你在 Claude Code 中看到 speckit 命令时,就知道安装成功了。

图片由作者提供
安装完成后,您可以遵循类似的工作流程:首先定义宪法,然后通过功能循环进行迭代。
Spec Kit 的一个不同之处在于,宪法更侧重于高层次的问题,如代码质量、测试标准、用户体验一致性以及性能要求。
坦率地说,我稍微更喜欢 JetBrains 提出的方法,因为它在宪法本身中保留了更多的上下文。但正如通常所说,没有万能的解决方案,根据您的使用情况,Spec Kit 可能会更合适。另外,已经为您实现了 SDD 工作流程,这也很方便。
使用 Spec Kit,我完成了上述两个阶段,效果很好。在第一个功能阶段之后,开发自然地成为了一个持续改进的循环,而不是线性过程。至此,我认为是时候结束这个故事了。
总结
总的来说,我花了大约 4.5 小时构建了一个可用于跟踪和分析数据的端到端产品。还有很多改进的空间,我会继续迭代。我已经看到了几个潜在的 UI 增强点,并且希望最终能够集成 AI 使应用程序更加智能。
坦率地说,按照如此结构化的开发流程工作是一次有趣的体验。在我的日常工作中,我经常依赖一次性 LLM 聊天来做出更改,而不会在仓库中维护完整的决策和规范记录。
然而,这里并没有一成不变的方法。
- 如果您只是想进行一个小的改进或在另一个 Jupyter 笔记本中运行一些临时分析,事先编写完整的规范可能有些过度。
- 但是当您正在处理一个较大的项目(尤其是与其他人合作时),规格驱动的开发肯定是我默认的方法。
观察工程师角色的变化也很有趣:从直接编写代码转向更多地关注架构决策、审查和系统设计。
虽然今天听起来可能有点极端,但我确实认为我们正逐渐迈向一个以英语为主要“编程语言”接口的世界。我们已经在这一方向上看到了早期尝试,例如 CodeSpeak,它探索了更自然语言驱动的编程范式。我将在下一篇文章中尝试 CodeSpeak,敬请期待。
参考
本文灵感来源于 DeepLearning.AI 的_“使用编码代理进行规格驱动开发”_短期课程。