返回笔记首页

第 14 集:为什么需要 Spec Coding(Vibe Coding 的天花板)

主题配置

1. Vibe Coding 的概念与起源

2025 年 2 月,Andrej Karpathy 在推特上发了一条帖子,大意是:他现在写代码基本靠"感觉",告诉 AI 要什么,看一眼输出,感觉不对就再说,感觉对了就继续——他把这叫做 Vibe Coding。

这个词很快就传开了,因为它说出了很多开发者正在做但没想到要命名的事。

Vibe Coding 的典型操作流程

plain
你:帮我写一个用户登录接口,用 NestJS,JWT 认证
AI:[给出一段代码]
你:运行,报错
你:帮我修一下这个错
AI:[修了]
你:好像可以了,继续下一个功能

这没什么不好。对于原型、个人项目、探索性开发,Vibe Coding 极其高效。Karpathy 自己也说了,这套路"对某些项目完全奏效"。

问题在于:当项目变大、团队变多、需要持续维护的时候,Vibe Coding 的天花板就来了。


2. Vibe Coding 的天花板在哪

用一个真实场景来说明。

场景:做一个用户管理模块

Vibe Coding 的方式

plain
创建一个用户管理的 NestJS 接口,支持增删改查

AI 会给你一份代码,能跑,看起来挺完整。然后你继续做下一个功能:

plain
加一个角色权限控制
plain
用户列表加分页和搜索
plain
密码需要加密存储

每次对话,AI 都不知道前几次发生了什么。它不知道你用的是什么数据库驱动,不知道你的错误格式是什么,不知道你的接口是 REST 还是 GraphQL,不知道你的分页是基于 cursor 还是 page number。

于是:

  • 第一次生成用了 class-validator,第三次改成了手写校验
  • 有的接口返回 { data: ... },有的直接返回数组
  • 密码加密有的用 bcrypt,有的用 bcryptjs,版本不一致
  • 错误处理有的抛 HttpException,有的 throw new Error

代码能跑,但质量在悄悄腐烂。这就是 Vibe Coding 的天花板:输出的一致性无法保障,项目越大越难控制。


3. 从 Prompt 到 Production:中间缺了什么

一个 Prompt 和一个上线的功能之间,差的不只是代码。

阶段 Vibe Coding 的状态
需求 模糊的自然语言,凭感觉说
设计 没有,让 AI 自己决定
数据模型 每次对话重新生成,可能不一致
接口契约 没有文档,AI 每次可能给不同结构
错误处理 随机,取决于 AI 当次的"心情"
测试 基本没有,或者是事后补的
一致性 依赖开发者肉眼 review

Spec Coding 要做的事情,就是把"需求"这一层补完整:

在写第一行代码之前,先把"AI 需要知道的所有事情"写成文档

这份文档叫做 spec.md


4. AI 编程范式的跃迁

把 AI 编程的演进简单分三代:

第一代:补全助手(Copilot 时代)

AI 帮你写下一行、下一个函数。你还是主要的思考者,AI 是打字员。

plain
// 你写:
function getUserById(
// AI 补全:
  id: number): Promise<User> {
  return this.userRepository.findOne({ where: { id } });
}

第二代:对话式生成(Vibe Coding 时代)

你描述意图,AI 给出完整实现。上下文依赖人脑管理。

plain
你:给我写一个 NestJS 的用户 CRUD 模块
AI:[完整输出 controller + service + module]

第三代:Spec 驱动开发(Spec Coding 时代)

你写规格文档,AI 按规格执行,上下文由文档承载,不靠对话记忆。

plain
你:按照 @spec/user.md 实现用户模块,
    遵循 .cursorrules 的代码风格,
    参考 @spec/api.md 的接口格式
AI:[严格按规格生成,格式一致、风格统一]

核心区别:Spec Coding 把"上下文"从对话历史转移到了文档。AI 不需要记住你之前说过什么,因为所有约定都在文档里。


5. 开发者的超级能力放大器

有一个比喻很好用:

Vibe Coding 好比你雇了一个手艺不错的工人,但每次干活你都得在旁边盯着,口头告诉他每个细节。

Spec Coding 好比你给了工人一份完整的施工图纸——他按图施工,你去干别的事,回来验收就行。

对于独立开发者,Spec Coding 的意义在于:你可以同时"管理"多个 AI 并行工作

对于带团队的开发者,意义在于:Spec 文档本身就是团队协作的基础,新人对着 spec 就能上手,而不是靠口口相传。


6. 一个完整的对比示例

❌ Vibe Coding 方式

plain
# 第一次对话
"帮我创建一个用户管理的 NestJS 接口,支持创建用户和查询用户列表"

# 第二次对话(新开)
"帮我加一个更新用户的接口,需要校验邮箱格式"

# 第三次对话(又新开)
"用户查询接口加个分页"

结果:三次对话生成的代码,接口返回格式不同、校验风格不统一、分页参数命名也不一样(一个用 page,一个用 pageNum)。


✅ Spec Coding 方式

先写 spec/user.md

markdown
## 用户模块接口规范

### 统一返回格式

所有接口返回 Result 包装:
{
"code": 0,
"message": "ok",
"data": { ... }
}

### 分页参数约定

- page: number(从 1 开始)
- pageSize: number(默认 20,最大 100)

### 字段校验

- email: 必须符合 RFC 5322,使用 class-validator @IsEmail()
- password: 8-32 位,包含大小写字母和数字

### 接口列表

POST /users 创建用户
GET /users 查询列表(支持分页 + 按 name/email 搜索)
GET /users/:id 查询单个
PATCH /users/:id 更新用户
DELETE /users/:id 软删除(is_deleted 标记)

然后每次对话:

plain
"按照 @spec/user.md 实现用户模块,
 使用 Prisma 操作数据库,
 遵循 .cursorrules 的项目规范"

每次生成的代码,结构一致、格式统一、命名规范——因为规范在文档里,不在你的脑子里


7. 小结

Vibe Coding 是 AI 编程的起点,它降低了动手的门槛,让"说人话就能生成代码"成为现实。

但它的天花板很明显:没有规格约束的 AI,就像没有图纸的施工队——每个人都在凭感觉干活,最后拼在一起是一团乱。

Spec Coding 不是让你写更多文档、更多规矩。它的核心只有一件事:

把原本藏在你脑子里的、靠每次对话重新交代的上下文,变成可以被 AI 稳定读取的结构化文档

这一步做到,AI 才真正成为你的工程搭档,而不是每次都要重新带入门的实习生。