从氛围编程到规格驱动开发

我在之前的文章《从代码到洞察:数据分析师的软件工程最佳实践》中已经提到过,工程技能和最佳实践对分析师和其他数据专业人员来说极其有用。

在AI时代,这一点更加真实,因为我们有更多机会构建自己的分析工具:从显示图表或展示不同场景的精美数据查看器,到可以根据输入参数预测结果的模拟器。就我个人而言,我在日常工作中一直在使用Web应用程序。

围绕氛围编程已经有很多炒作,但似乎专业工程师已经在超越它,更多地倾向于规格驱动开发。甚至创造了"氛围编程"这个词的Andrej Karpathy也在一年后承认这个时代正在结束,我们正在进入智能体工程的时代——在详细规格下编排智能体,并有人类监督。

今天(一年后),通过LLM智能体编程正日益成为专业人士的默认工作流程,只不过有了更多的监督和审查。目标是在不妥协软件质量的情况下获得使用智能体的杠杆。很多人试图想出一个更好的名字来将其与氛围编程区分开来,我个人目前最喜欢的"智能体工程":

  • "智能体",因为新的默认情况是你99%的时间不是直接写代码,而是在编排执行工作的智能体并充当监督者。
  • "工程"强调这其中有艺术、科学和专业知识。这是你可以学习并变得更好的东西,有着自己不同层面的深度。

在本文中,我想在一个全新项目上实践规格驱动开发,遵循JetBrains在DeepLearning.AI上的课程《Spec-Driven Development with Coding Agents》中的最佳实践。

这个项目更个人化一些,但仍然与数据相关。由于我正在为9月的半程马拉松做准备,我试图平衡跑步和力量训练。有太多工具了,每个都专注于旅程的不同部分,找到一个真正适合我的解决方案出奇地困难。所以,我决定一石二鸟:构建自己的Web应用,同时希望能学到一些新东西。

准备好了吗?我也是。但在我们跳入实现之前,让我们先花几分钟了解一下规格驱动开发背后的理论。

1、氛围编程 vs 规格驱动开发

我们很多人已经体验过氛围编程:你写一个简短的提示词(例如,"请在我的Web应用中添加一个DAU图表"),等待智能体生成变更,在本地运行,并检查结果是否符合你的期望。

通常,它不符合。所以你回到同一个对话,要求智能体调整图表,并持续迭代直到结果足够好。

这种方法对于简单项目相当有效,但不容易扩展,尤其是当多个开发者在同一个代码库上工作时。

主要的缺点是缺乏最佳实践和共享的约定。例如,如果没有结构化的方法,团队很容易在同一个DBT管道中以五种不同的方式运行ML模型训练。

另一个常见问题是,我们通常不会持久化与AI智能体对话的结果或推理。因此,很容易丢失为什么要做出某些决策的线索。例如,一个智能体可能忘记你为什么以特定方式清理数据,下一次更新可能会悄悄引入不同的结果。

上下文衰减也是一个特别常见的问题。AI智能体是无状态的,在处理更大的项目时,我们经常不得不因为上下文窗口限制而开始新的对话,实际上是从头开始我们的沟通。

规格驱动开发(SDD)更接近传统的工程实践。不是直接跳入实现,我们先自己做一些艰苦的思考:做出架构决策,定义需求,并将它们文档化在一个存储在仓库中的结构化markdown规格中,随项目一起更新。这产生了一个重要的转变:我们将规格(我们正在构建什么以及为什么)与实现(实际代码)解耦了。

SDD通过在会话之间(甚至在不同AI智能体之间)保留上下文,同时围绕项目的主要不可妥协的方面对齐人类和智能体,解决了氛围编程的许多核心问题。

2、SDD工作流

一个典型的规格驱动开发工作流通常包括以下阶段。

第一步是定义宪章——对项目关键决策的共识。它通常包括几个核心文档:

  • 使命解释了"为什么":我们为什么构建这个项目,它的关键目标和功能是什么?
  • 技术栈记录技术决策,以及部署和更新流程。
  • 路线图概述项目阶段、计划功能,并随着项目发展持续更新。

规格可以为新项目和现有项目创建,这使得这种方法相当通用。

一旦项目级文档到位,我们就可以进入功能开发阶段,通常包括:

  1. 理解我们想要构建什么并编写详细的规格。
  2. 实现变更。
  3. 验证实实现是否符合预期。

在成功实现你的第一个功能后,你可能会立即感到继续下一个功能的冲动。但这实际上是暂停和重新思考的正确时刻。

这就是重新规划的地方。这是一个专门的阶段,用于重新审视宪章并审查之前的功能决策和计划,以确保它们仍然与项目目标一致。

现在我们已经涵盖了理论,让我们把它付诸实践。

3、开始构建

够了理论,是时候构建了。为了更好地理解规格驱动开发在实践中如何工作,我决定将其应用到一个真实的全新项目。

我首先为这个项目创建了一个新仓库(当然,花了半个小时选择名称和logo):仓库。我还在README.md文件中记录了我的初始产品愿景。

SDD方法的一个好处是它在很大程度上与LLM、智能体或IDE的选择无关,所以你可以使用任何你喜欢的设置。对于这个项目,我将使用Visual Studio Code和Claude Code插件,因为它允许我使用Claude作为智能体,同时直接在编辑器中审查所有代码变更。

3.1 创建宪章

如我们讨论的,第一步是编写宪章。当然,我们不需要手动完成,我们可以使用LLM基于初始产品愿景以及通过后续问题收集的额外上下文来将其组合在一起。

We are building Trainlytics, a personal fitness tracking web app built
for people who want more control, flexibility, and insights than standard
fitness apps provide. Find the full requirements in README.md.

Let's create a "constitution" in a specs directory that consists of 
the following parts:
- mission.md - what and why we are building; the main mission of the product
- tech-stack.md - core technical decisions
- roadmap.md - project phases broken down in implementation order

IMPORTANT: You must use your AskUserQuestion tool to get my feedback.

然后智能体会提出一系列澄清问题,帮助定义项目宪章并创建初始实施计划。

最终,智能体创建了我们要求的三个文件。

在这一点上,你可能会想立即让智能体开始构建项目,但这可能太早了。

在继续前进之前,我们首先需要验证和改进宪章。现在花时间对齐计划是值得的,因为这个规格以后会转化为成千上万行代码。尽早解决模糊性和错误要好得多。

我通常通过自己阅读文档并与智能体迭代来完成这一点,提出澄清问题并逐步完善计划。一个好的做法是通过智能体进行所有更改,而不是自己修补文档,以保持项目的一致性。例如,我告诉智能体应用程序中需要认证,因为我的使用场景是从桌面和移动设备登录锻炼记录。这导致了技术栈文档和路线图的更新。

审查完成后,你还可以要求第二个智能体——带有全新的上下文——来批评计划。有大量证据表明反思能提高输出质量。

当所有检查完成后,是时候将宪章提交到仓库了。

3.2 第一个功能阶段

现在,是时候进入第一个功能阶段了。根据我们的路线图,我们将从MVP:核心活动记录开始。在这个阶段结束时,用户应该能够在桌面和移动设备上登录,记录一次跑步和一次健身房训练,并在历史记录中查看两者的完整详情。

如讨论的,每个功能阶段遵循一个简单的循环:规划 → 实现 → 验证。所以让我们从定义规格和构建计划开始。

Find the next phase in specs/roadmap.md and create a new branch, 
ask me about any steps in the specs that are not fully clear.

Then create a new directory in the format YYYY-MM-DD-feature-name under specs/ 
for this feature, with the following files:
- plan.md - a structured list of numbered task groups
- requirements.md - scope, key decisions, and context
- validation.md - how we define success and confirm the implementation can 
be merged

Use specs/mission.md and specs/tech-stack.md as guidance.
提示:值得在LLM智能体中开始一个带有清晰上下文的新会话。

智能体很快就把规格组合好了。

此时,又到了审查规格并确保一切与原始愿景对齐的时候了。如你所见,在智能体工程中,开发者的角色转向了引导、审查和做出架构决策,而不是直接编写规格或代码。

一旦你对计划满意,就可以进入实现了。我更喜欢分别实现每组任务,而不是一次性完成整个功能阶段,但这取决于功能的大小。对于这个项目,我使用了以下提示词。

Take the next task group from 2026-05-04-phase-1-mvp/plan.md and implement it.
Use requirements.md and validation.md for guidance.
Once done, update the status in both the plan and validation documents.

当代码准备好后,就该审查了。这是最重要的步骤之一,所以值得在这里投入一些时间。

在数据相关的应用中,我通常将审查集中在核心业务逻辑上,检查数字是否符合我的预期。

我必须承认,我对前端技术几乎零了解,所以我很少详细审查前端代码。相反,我只是在本地测试界面并检查一切是否按预期工作。对于这个案例,我决定运行应用看看它如何工作。

在与智能体几次迭代后,我们成功在本地运行了应用,它运行良好。我们已经可以添加不同的练习和活动类型,并记录有氧和力量训练。

手动审查后,使用反思并让新智能体验证实现是否与计划一致,以及过一遍validation.md中定义的点也是有用的。

理论上,规格驱动开发建议功能阶段以验证结束。在实践中,很少能如此干净利落地运作。你可能会发现实现的某些部分不符合预期。此时,你有两个选择:

  • plan.md中再添加几个迭代并继续完善功能(这适用于较小的变更),或者
  • 如果问题更重大,将它们作为下一个功能阶段的一部分,在重新规划期间处理。

需要注意的一个重要事项:可能会有诱惑简单地向LLM智能体解释问题并要求修复,而不是更新规格并重新实现。试着抵制这种捷径。保持规格作为真相来源是使这种方法稳健的关键。

所有检查完成后,我们可以创建并合并拉取请求

此时,我们已经有一个可以工作的应用程序,结果确实令人满意。更令人惊讶的是,整个流程端到端只花了两个多小时(包括在智能体工作时起草这篇文章)。

3.3 重新规划

有了这么好的进展,你可能想继续构建。我理解,但在当前的AI时代,人类的主要价值在于思考和架构。所以这实际上是退后一步反思的正确时刻:我们是否仍想继续同一个方向,我们的产品和流程应该改变什么?

当我开始自己使用这个应用时,我意识到它还没有准备好完全支持我的使用场景。这意味着我们需要重新确定优先级,以便我能尽快在日常生活中的使用它。所以,我用以下提示词来做了这件事。

Let's revise our plan in roadmap.md.
I would prioritise the next phases as follows:
1. Strength session templates
I can live without planning, but I need templates, because I often struggle 
to remember all the exercises in a session.

The idea is:
- If a template already exists in the log, show all stats (exercises, sets, 
reps, weight, etc.). Allow editing these values and committing changes
- If anything is changed, ask whether the user wants to update the template

2. UI improvements
The current design is not yet sleek enough, so I'd prioritise a round of UI 
improvements:
- Add the logo and product motto to the website
- Add a settings tab to manage activity types and exercises
- Create a single screen to log both cardio and strength sessions
- Improve the history screen with richer activity details
- Allow adding titles to activities (strength/cardio sessions) and segments
- Support specifying time, not only date
- Add more color to the interface (I like shades of blue)
- For cardio exercises, adjust units to: minutes, kilometers, and min/km pace

3. Basic analytics
Add simple analytics to the history screen showing weekly stats at
the top of the page (e.g. total minutes and calories split between cardio
and strength).

重新规划也是重新审视我们流程本身的好时机。例如,我注意到我们没有持续更新roadmap.md,规格开始漂移了。引入一个变更日志也会很有用,这样我们就有了产品随时间如何演变的清晰历史。

让我们让智能体来做这件事。

Please review plan.md, update roadmap.md to reflect completed work, 
and create a CHANGELOG.md file with a concise summary of the changes.

现在我们已经在方向上达成一致并有了正确的设置,让我们继续构建。

3.4 下一阶段

现在我们可以遵循相同的过程并迭代各个阶段。由于这是一个可重复的循环,现在是讨论可能自动化的好时机。

到目前为止,我们一直在手动编写所有提示词,但这些工作流也可以作为Claude Code或其他LLM编码智能体中的"技能"来自动化。

此外,已经有一些现成可用的规格驱动开发实现。最受欢迎的是GitHub的Spec Kit

你可以这样安装它。

uv tool install specify-cli --from git+https://github.com/github/spec-kit.git
specify version # to check that it works

接下来,你需要在Claude中初始化技能。这会设置.specify/文件夹并将斜杠命令安装到.claude/commands/中。

specify init . --integration claude 
# there are 30 integrations with agents so specify the one you're using

当你在Claude Code中看到speckit命令时,你就知道它工作了。

安装后,你可以遵循类似的工作流:从定义宪章开始,然后迭代功能循环。

一个区别是,在Spec Kit中,宪章更关注高级别的关注点,如代码质量、测试标准、UX一致性和性能要求。

说实话,我稍微更偏好JetBrains提出的方法,因为它在宪章本身中保留了更多上下文。但一如既往,没有银弹,Spec Kit可能根据你的用例工作得更好。已经为你实现了SDD工作流也很方便。

使用Spec Kit,我运行了上面描述的两个阶段,效果很好。在第一个功能阶段之后,开发自然变成了一个持续改进的循环,而不是线性过程。因此,我认为是时候结束这个故事了。

4、结束语

总共,我花了大约4.5小时构建了一个可用的端到端产品来跟踪和分析我的数据。还有很大的改进空间,我会继续迭代。我已经可以看到几个潜在的UI增强,我也想最终集成AI使应用更智能。

坦白说,按照这种结构化的开发流程工作是一次有趣的体验。在我的日常工作中,我经常依赖一次性的LLM对话来进行变更,而没有在仓库中维护完整的决策和规格记录。

然而,这里没有一刀切的方法。

  • 如果你只是想做一个小改进或在又一个Jupyter notebook中运行一些临时分析,预先编写完整的规格可能有点过头。
  • 但当你在一个更大的项目上工作时(尤其是与其他人一起),规格驱动开发肯定会成为我的默认方法。

观察工程师角色的转变也很有趣:从直接编写代码到更专注于架构决策、审查和系统设计。

虽然今天听起来可能有点极端,但我确实认为我们正在逐步走向一个英语成为主要"编程语言"界面的世界。我们已经看到了这方面的早期尝试,比如CodeSpeak,它探索了更自然的语言驱动的编程范式。我将在下一篇文章中尝试CodeSpeak,敬请期待。


原文链接: From Vibe Coding to Spec-Driven Development

汇智网翻译整理,转载请标明出处