ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

从Vibe Coding到规范驱动开发:AI编程如何从碰运气走向可复现

从Vibe Coding到规范驱动开发:AI编程如何从碰运气走向可复现

1. 从“感觉对了”到“有据可依”:为什么我开始警惕 Vibe Coding

前阵子跟几个做独立开发的朋友吃饭,聊到 AI 编程这个话题,桌上几乎所有人都在用 Cursor、Windsurf 或者 VS Code Copilot 这类工具。有个哥们儿说他现在写代码基本就是“跟着感觉走”——打开 AI 编辑器,敲几句自然语言描述,看着补全出来的代码“感觉对了”就回车接受,一个下午能撸出一个功能模块。当时大家都觉得挺爽,毕竟效率确实肉眼可见地提升了。

但问题也恰恰出在这里。这种“跟着感觉走”的编程方式,圈子里现在有个很形象的说法叫Vibe Coding——你凭直觉描述需求,AI 凭概率生成代码,双方都不太较真,只要跑起来没报错、界面看着像那么回事,就算过关。做原型、写脚本、搞个人小工具,这么干完全没问题,甚至可以说是效率神器。可一旦项目要进入“正经”阶段——多人协作、长期维护、需求频繁变更、上线后要扛真实流量——Vibe Coding 的隐患就会像潮水退去后的礁石一样暴露出来。

我自己就踩过这个坑。去年用 AI 辅助快速搭了一个内部管理系统的后端,当时觉得代码写得又快又顺,接口测试也过了。结果两个月后要加一个新功能,我打开当时的代码一看,整个人是懵的:变量命名前后不一致,同一个业务逻辑在三处地方用了三种不同的实现方式,错误处理有的地方用 try-catch 有的地方直接抛,数据库查询有的走 ORM 有的手写 SQL。最要命的是,我完全不记得当时为什么这么写——因为那些决策根本不是“我”做的,是 AI 根据我模糊的描述“猜”出来的。

这就是 Vibe Coding 的核心问题:它优化的是“生成速度”,而不是“可维护性”。AI 编程助手大比拼里,Cursor、Windsurf、Trae 这些工具各有千秋,但它们的共同点是——你给什么提示词,它就生成什么代码,它不会主动问你“这个模块的边界在哪里”“异常情况怎么处理”“未来扩展方向是什么”。而这些恰恰是正经项目必须回答的问题。

于是,规范驱动开发(Specification-Driven Development,简称 SDD)开始被越来越多团队重新重视起来。SDD 不是什么新概念,但在 AI 编程时代,它被赋予了新的意义:用明确的规范来约束 AI 的生成行为,让“感觉对了”变成“有据可依”。这篇文章我就结合自己从 Vibe Coding 转向 SDD 的实践,聊聊怎么把 AI 编程从“碰运气”变成“可复现的工程行为”。

2. 规范驱动开发到底在解决什么问题

2.1 Vibe Coding 的三大隐性成本

很多人觉得 Vibe Coding 的问题只是“代码质量差”,其实远不止如此。我总结下来,它至少带来三类隐性成本,而且这些成本往往在项目中期才会集中爆发。

第一是认知成本。当你用自然语言描述需求让 AI 生成代码时,你和 AI 之间其实存在一个巨大的“理解鸿沟”。你说“做一个用户登录功能”,AI 可能生成一个基于 session 的实现,也可能生成 JWT,还可能生成 OAuth。它选哪个完全取决于训练数据里的概率分布,而不是你的项目实际需求。结果就是,你每次看这段代码都要重新理解一遍“AI 当时是怎么想的”,而这个“想法”可能根本不存在——它只是概率的产物。

第二是协作成本。Vibe Coding 生成的代码往往缺乏一致的命名规范、目录结构和接口约定。一个人用还行,两个人以上协作就是灾难。A 同事让 AI 生成一个getUserInfo接口,B 同事让 AI 生成一个fetchUserDetail接口,功能几乎一样但命名不同、参数不同、返回结构不同。代码 review 的时候,你没法说“这不符合规范”,因为压根就没有规范。

第三是演进成本。正经项目的需求一定会变。今天要加一个字段,明天要改一个流程,后天要接一个新的第三方服务。如果代码是 Vibe Coding 出来的,每次变更都像在沼泽地里盖房子——你永远不知道下一铲子会挖出什么。而 SDD 的核心价值,就是把“变更”变成一件可预期、可控制的事情。

2.2 SDD 的核心思想:先写“合同”,再写代码

规范驱动开发的逻辑其实很朴素:在写任何代码之前,先把“要做什么”和“怎么做”用明确、无歧义的方式写下来。这份规范就是开发者和 AI 之间的“合同”——AI 按照合同生成代码,开发者按照合同验收代码。

这里的“规范”不是指那种几百页的需求文档,而是结构化、可执行、可验证的规格说明。它通常包含几个关键部分:

  • 接口定义:输入是什么、输出是什么、异常情况怎么处理
  • 数据模型:核心实体有哪些字段、类型是什么、约束条件是什么
  • 行为规则:业务逻辑的边界条件、状态流转、权限控制
  • 非功能要求:性能指标、安全要求、日志规范

举个例子,同样是“用户登录”这个功能,Vibe Coding 的提示词可能是“帮我写一个用户登录接口”。而 SDD 的规范可能是这样的:

interface: POST /api/v1/auth/login request: body: username: string, required, 3-20 chars password: string, required, 8-32 chars response: 200: token: string, JWT, expires in 2h user: { id, username, avatar } 401: error: "INVALID_CREDENTIALS" 429: error: "TOO_MANY_ATTEMPTS", retry_after: 60s rules: - password must be hashed with bcrypt cost 12 - failed attempts tracked per username, max 5 in 15min - token must include user_id and role claims

有了这份规范,AI 生成的代码就有了明确的“靶子”。你可以直接检查它有没有实现 429 限流、有没有用 bcrypt cost 12、token 里有没有 role claim。验收标准从“感觉对了”变成了“逐条对照”。

2.3 为什么 AI 编程时代 SDD 反而更重要了

有人可能会说:SDD 不是老生常谈吗?敏捷开发、测试驱动开发不都在强调类似的东西?为什么现在又要专门提?

我的理解是:AI 编程把“写代码”的成本降到了极低,但把“理解代码”和“维护代码”的成本相对抬高了。以前你写代码慢,所以你会花很多时间想清楚再写;现在 AI 几秒钟就能生成几百行,你反而更容易跳过“想清楚”这一步。结果就是代码量爆炸式增长,但可维护性断崖式下跌。

SDD 在这个背景下扮演的角色,是给 AI 的生成能力套上一个“约束框架”。它不反对用 AI 写代码,而是要求你在让 AI 写之前,先把规范定下来。这样 AI 的产出就是“符合规范的实现”,而不是“看起来像那么回事的文本”。MonkeyCode 这类工具之所以开始强调规范驱动,本质上也是看到了这个趋势——AI 编程的下一阶段竞争,不是比谁生成得快,而是比谁生成得“可控”。

3. 把 SDD 落地到 AI 编程工作流:我的实操方案

3.1 工具链选型:不追求最新,追求最顺

先说工具。我试过不少 AI 编程产品,从 Cursor 到 Windsurf,从 VS Code Copilot 到 Trae,还有各种基于 DeepSeek API 自建的助手。最后我的选择是:主力用 Cursor,辅助用 MonkeyCode 做规范管理,复杂逻辑用 DeepSeek API 做补充。

为什么这么选?Cursor 的优势在于它对项目上下文的感知比较强,能读取整个代码库的结构,适合在已有规范的基础上生成代码。MonkeyCode 我主要用来维护规范文档和任务拆解,它的结构化程度比较高,适合把“要做什么”先理清楚。DeepSeek API 则是在遇到特别复杂的算法逻辑时,用来做“第二意见”参考。

这里要强调一点:工具选型没有绝对的最优解,关键是看它能不能融入你的 SDD 流程。如果你用 Cursor 但从来不写规范,那它就是个高级的 Vibe Coding 工具;如果你用最朴素的文本编辑器但坚持先写规范再让 AI 生成,效果可能反而更好。

3.2 规范怎么写:三层结构法

我自己的规范文档采用三层结构,从粗到细,逐层收敛。

第一层是“领域规范”,描述这个项目是做什么的、核心实体有哪些、它们之间的关系是什么。这一层不需要太细,但必须把“边界”画清楚。比如“这是一个面向中小企业的库存管理系统,核心实体包括商品、仓库、入库单、出库单,商品和仓库是多对多关系”。

第二层是“模块规范”,把领域拆成具体的功能模块,每个模块定义清楚输入输出和核心规则。这一层是 AI 生成代码的主要依据。我通常会用一个 Markdown 表格来组织:

模块接口输入输出核心规则
商品管理POST /productsname, sku, priceid, created_atsku 全局唯一,price 大于 0
库存查询GET /inventorywarehouse_id, skuquantity, updated_at只返回当前仓库数据

第三层是“实现规范”,针对具体的技术选型和代码风格做约定。比如“所有数据库操作使用 Prisma ORM”“错误码统一用大写下划线格式”“日志必须包含 trace_id”。这一层看起来琐碎,但恰恰是保证 AI 生成代码一致性的关键。

提示:规范文档不要写得太长。我的经验是,单个模块的规范控制在 200 行以内,超过这个长度就说明拆得不够细。AI 的上下文窗口是有限的,规范太长反而会稀释关键信息。

3.3 提示词工程:把规范“喂”给 AI 的正确姿势

有了规范,下一步就是怎么让 AI 按照规范生成代码。这里有个常见的误区:很多人直接把规范文档粘贴到对话框里,然后说“按照这个规范写代码”。效果往往不好,因为 AI 会“抓大放小”,忽略掉很多细节。

我的做法是分步喂入 + 逐条确认。具体来说:

第一步,先让 AI 阅读领域规范和模块规范,然后让它用自己的话复述一遍核心规则。这一步是为了确认 AI 真的“理解”了规范,而不是假装理解。

第二步,针对具体模块,把实现规范也喂进去,然后要求 AI 先输出一个“实现计划”——它打算怎么写、用哪些技术、怎么处理异常。这一步是为了在生成代码之前就发现偏差。

第三步,确认计划没问题后,再让 AI 生成代码。生成之后,我会逐条对照规范做检查,而不是只看“能不能跑”。

这套流程看起来比 Vibe Coding 麻烦,但实测下来,返工率降低了至少 70%。以前 Vibe Coding 生成的代码,我平均要改 3-5 轮才能用;现在按照 SDD 流程,通常 1-2 轮就能达到可提交状态。

4. 一个完整案例:从规范到代码的全过程

4.1 需求背景与规范定义

假设我们要做一个“优惠券核销”功能。Vibe Coding 的做法可能是直接跟 AI 说“帮我写一个优惠券核销接口”。而 SDD 的做法是先写规范。

领域规范:这是一个电商系统,优惠券有“未使用”“已使用”“已过期”三种状态,核销操作将优惠券从“未使用”变为“已使用”。

模块规范:

interface: POST /api/v1/coupons/{coupon_id}/redeem auth: required, user must own the coupon request: path: coupon_id: string, required body: order_id: string, required response: 200: coupon_id: string status: "USED" redeemed_at: timestamp 400: error: "COUPON_EXPIRED" | "COUPON_ALREADY_USED" 403: error: "NOT_COUPON_OWNER" 404: error: "COUPON_NOT_FOUND" rules: - check coupon exists and belongs to current user - check coupon status is "UNUSED" and not expired - update status to "USED" and record redeemed_at - operation must be idempotent within 5 seconds

实现规范:使用 Prisma ORM,错误码用大写下划线,日志包含 trace_id 和 coupon_id。

4.2 AI 生成与人工校验

把这三层规范喂给 Cursor 之后,我要求它先输出实现计划。它给出的计划是:先查优惠券,再校验归属和状态,然后更新状态,最后返回结果。这个计划基本符合规范,但我注意到它没有提到“幂等性”的处理。

于是我补充提示:“规范里要求 5 秒内幂等,你打算怎么实现?”AI 随后补充了基于 Redis 的分布式锁方案。这一步很关键——如果直接让它生成代码,幂等性很可能被忽略,而这是支付相关功能绝对不能少的。

代码生成后,我逐条对照规范检查:

  • 接口路径和参数:符合
  • 权限校验:有,但错误码用了FORBIDDEN而不是规范里的NOT_COUPON_OWNER,需要改
  • 过期判断:有,但用的是expires_at < now(),规范要求考虑时区,需要补充
  • 幂等性:有 Redis 锁,但锁的 key 没有包含 user_id,存在越权风险,需要改

这些问题如果靠 Vibe Coding 的“感觉”,很可能就漏掉了。但有了规范,每一条都是明确的检查项。

4.3 验收与回归

代码修改完成后,我按照规范里的响应码逐条写了测试用例:正常核销、重复核销、过期核销、非本人核销、不存在的优惠券。五个用例全部通过后,才提交代码。

这里有个小技巧:把规范里的每一条规则都变成一个测试用例。这样规范就不只是“文档”,而是“可执行的验收标准”。后续如果有人修改这段代码,跑一遍测试就知道有没有破坏原有约定。

5. 常见问题与避坑指南

5.1 规范写太细,AI 反而不会写了

这是我最开始遇到的问题。我把规范写得极其详细,连每个字段的长度都规定了,结果 AI 生成代码时反而畏首畏尾,经常卡住或者生成一堆防御性代码。后来我调整了策略:规范只定义“必须遵守的约束”,不定义“实现细节”。比如“密码必须哈希存储”是约束,“用 bcrypt cost 12”是实现细节。约束必须写,实现细节可以留给 AI 发挥,只要不违反约束就行。

5.2 AI 生成的代码“看起来对”但“实际上错”

这是 Vibe Coding 最危险的地方。AI 生成的代码往往语法正确、逻辑通顺,但可能在边界条件上出错。比如一个分页查询,AI 可能生成了offset = page * size,但规范里要求的是offset = (page - 1) * size。这种错误靠“感觉”很难发现,必须靠规范逐条对照。

我的应对方法是:在规范里明确写出边界条件的测试用例。比如“page=1 时返回第 1-10 条,page=2 时返回第 11-20 条”。这样 AI 生成代码后,我可以直接用这些用例验证。

5.3 团队协作时规范怎么同步

如果是多人协作,规范文档必须放在版本控制里,和代码一起管理。我通常会在项目根目录建一个specs/文件夹,里面按模块存放规范文件。每次修改规范都要走 PR 流程,确保所有人都知道规范变了。

另外,我会在 CI 流程里加一步:检查代码是否符合规范里的关键约束。比如用 ESLint 检查命名规范,用自定义脚本检查错误码格式。这样规范就不只是“纸面约定”,而是“自动化检查”。

5.4 什么时候可以不用 SDD

说了这么多 SDD 的好处,但我也得承认:不是所有场景都适合 SDD。如果你只是写一个一次性脚本、做一个周末原型、或者探索一个完全陌生的技术方向,Vibe Coding 的效率优势是实实在在的。SDD 的价值在于“长期维护”和“多人协作”,如果你的项目不需要这两点,那就不用给自己加戏。

我的判断标准很简单:如果这个代码三个月后你还会看,那就值得写规范;如果三天后就不看了,那就怎么快怎么来。

6. 我个人的一些体会

从 Vibe Coding 转向 SDD 的过程,对我来说最大的改变不是工具或流程,而是心态。以前用 AI 编程,我追求的是“快”——快速生成、快速试错、快速迭代。现在我用 AI 编程,追求的是“稳”——规范先行、逐条验收、可追溯可复现。

这个转变一开始让我很不适应,因为写规范确实要花时间。但用了几个月之后,我发现写规范的时间远远小于返工的时间。以前 Vibe Coding 一个模块,生成只要 5 分钟,但调试和修改可能要 2 小时;现在写规范要 20 分钟,生成和验收加起来 40 分钟,总时间反而更短。

还有一个意外收获:写规范的过程本身就是在梳理需求。很多时候我以为自己想清楚了,一动笔写规范才发现到处都是模糊地带。这些模糊地带如果留给 AI 去“猜”,结果就是一堆需要返工的代码;如果自己在规范阶段就解决掉,后面就顺风顺水。

最后分享一个小技巧:把规范当成和 AI 的“对话记录”。每次 AI 生成代码出现偏差,我就把偏差原因补充到规范里。比如“AI 容易忽略幂等性,需要在规范里显式强调”。这样规范会越来越完善,AI 的生成质量也会越来越高。本质上,你是在用规范“训练”你的 AI 助手,让它越来越懂你的项目。

返回列表