一、Vibe Coding 的起源
2025 年 2 月,Andrej Karpathy 在 X(原 Twitter)上发了一条推文,第一次提出了 "Vibe Coding" 这个词。
Karpathy 是谁:
- Tesla AI 前负责人
- OpenAI 联合创始人之一
- 全球顶级 AI 研究者
他的原话核心意思是:你完全沉浸在那种感觉里,忘掉代码本身的存在,只管看、说、运行、复制粘贴,大多数时候它就能跑起来。
一句话定义:Vibe Coding = 用自然语言描述意图,让 AI 完成实现细节
二、Vibe Coding 和传统写代码的本质区别
传统写法的流程
脑子里有想法
↓
查文档(找 API、找语法)
↓
记住语法,想清楚怎么写
↓
一行一行打代码
↓
运行,遇到报错
↓
Debug,改代码
↓
跑通
Vibe Coding 的流程
脑子里有想法
↓
用自然语言把想法描述清楚
↓
AI 生成代码
↓
审查代码,判断对不对
↓
跑通 / 追加要求继续迭代
中间消失的三步
对比两个流程,Vibe Coding 里消失了:
- 查文档 —— AI 知道所有文档
- 记语法 —— AI 知道所有语法
- 一行一行打 —— AI 帮你写
消失的这三步,占了传统开发里大量的时间和精力。
没有消失的部分
- 理解业务需求:你还是要搞清楚要做什么
- 架构判断:你还是要判断用什么技术方案
- 审查代码:AI 给的代码你要能看懂、判断对不对
- 调试能力:遇到问题还是要能定位原因
三、一个具体的对比演示
传统写法:手动实现一个 NestJS 用户 Service
下面这段代码,传统方式需要:
- 知道
@Injectable()装饰器怎么用 - 知道
@InjectRepository()的注入方式 - 知道 TypeORM 的
Repository<T>泛型写法 - 知道
findOne的where参数格式 - 手动打完每一行
import { Injectable } from '@nestjs/common'
import { InjectRepository } from '@nestjs/typeorm'
import { Repository } from 'typeorm'
import { User } from './user.entity'
import { CreateUserDto } from './dto/create-user.dto'
@Injectable()
export class UserService {
constructor(
@InjectRepository(User)
private userRepository: Repository<User>
) {}
async create(createUserDto: CreateUserDto) {
const user = this.userRepository.create(createUserDto)
return await this.userRepository.save(user)
}
async findAll() {
return await this.userRepository.find()
}
async findOne(id: number) {
return await this.userRepository.findOne({ where: { id } })
}
async remove(id: number) {
await this.userRepository.delete(id)
}
}
时间成本:熟练开发者约 5~10 分钟,不熟悉 NestJS 的可能 30 分钟以上。
Vibe Coding 写法:用一段 Prompt 描述需求
打开 Cursor,按 Cmd+L(Windows:Ctrl+L)打开 Chat,输入以下内容:
创建一个用户管理模块,要求:
- 使用 NestJS + Prisma ORM
- 包含 CRUD 完整接口
- 字段:id、username、email、createdAt
- email 字段需要唯一校验
- 删除时软删除(deletedAt 字段,不真正删除数据库记录)
- 接口返回统一的 ResponseDto 格式:{ code, data, message }
- 所有接口加 Swagger 注解
AI 生成的结果会包含:
user.entity.ts或 Prisma Schema 里的 User model 定义create-user.dto.ts、update-user.dto.tsuser.service.ts(完整 CRUD,含软删除逻辑)user.controller.ts(含@ApiTags、@ApiOperation注解)response.dto.ts(统一响应格式)
时间成本:约 30 秒等待生成。
这个 Prompt 为什么能得到好结果
对比两种 Prompt 的质量差异:
差的 Prompt
帮我写一个用户接口
结果:AI 可能用 TypeORM 也可能用 Prisma,可能加 Swagger 也可能不加,返回格式随机,软删除可能没有。
好的 Prompt(上面那个)
- 明确了 ORM:Prisma
- 明确了字段列表:id、username、email、createdAt
- 明确了业务约束:email 唯一、软删除
- 明确了返回格式:ResponseDto
- 明确了接口规范:Swagger 注解
规律:Prompt 里的约束越具体,AI 输出越稳定、越符合预期
四、编程范式的三次跃迁
阶段一:记语法时代(2000s 之前)
- 核心竞争力 = 记住更多 API 和语法
- 好的程序员 = 脑子里装着大量语言规范和库的用法
- 瓶颈 = 人脑记忆容量上限
阶段二:懂架构时代(2000s ~ 2020s)
- 核心竞争力 = 理解框架原理、设计系统架构
- 好的程序员 = 能设计出可扩展、可维护的系统
- 瓶颈 = 工程经验积累速度
阶段三:说意图时代(2025 年往后)
- 核心竞争力 = 把模糊想法转化成精确描述 + 判断 AI 输出质量
- 好的程序员 = 能说清楚要什么、能识别 AI 给的代码对不对
- 瓶颈 = 业务理解深度 + 思维清晰度
三个阶段的关系
不是"新阶段替代旧阶段",而是叠加关系:
- 不懂语法,你看不懂 AI 生成的代码,没办法审查
- 不懂架构,你给 AI 的 Prompt 描述的是错的方案,AI 生成的代码结构有问题
- 在前两个基础上,加上"说清楚意图"的能力,才能真正用好 Vibe Coding
五、AI 是放大器,不是替代品
一个比喻
以前的开发者 = 既是建筑设计师又是施工工人:既要画图纸,又要自己搬砖砌墙。
Vibe Coding 时代的开发者 = 建筑设计师:图纸画清楚,施工的活 AI 来干。
图纸(Prompt)画得越清晰,施工质量越高。如果你连建筑基础知识都不懂,图纸画不出来,AI 也没法帮你。
谁会被替代
会被替代的:只会机械执行、照文档抄代码、不理解业务和架构的开发者。
不会被替代、反而更值钱的:
- 理解业务逻辑,能把需求转化成精确 Prompt 的开发者
- 有架构判断力,能识别 AI 生成代码质量的开发者
- 能设计 Agent 系统、管理 AI 工作流的工程师
放大效应
能力越强,AI 放大得越多:
- 初级开发者用 AI:从每天写 100 行变成写 300 行
- 高级开发者用 AI:从每天完成 1 个功能变成完成 5 个功能
- 架构师用 AI:一个人能驱动整个项目的骨架搭建
六、Vibe Coding 的边界
AI 当前擅长的
- 标准的 CRUD 接口生成
- 根据已有代码生成测试用例
- 重构明确的代码问题(命名、类型、结构)
- 生成样板代码(DTO、Entity、Module 注册)
- 解释不熟悉的代码片段
AI 当前不擅长的
- 复杂的跨系统业务逻辑(需要你理解业务才能描述清楚)
- 性能优化的具体方案(需要你理解瓶颈在哪)
- 架构级别的决策(用哪种消息队列、数据库选型)
- 安全审查(可以辅助,但不能完全依赖)
工作方式的结论
AI 做 80%: 样板代码、标准实现、测试生成、文档编写
你做 20%: 需求拆解、架构决策、质量审查、业务判断
这门课后面每一集,都是在教你怎么用好这 80% + 把 20% 做得更好。
七、本集演示操作步骤
准备工作
- 新建文件夹
vibe-coding-demo - 在文件夹里新建文件
before.ts,写入以下内容(传统写法示例):
import { Injectable } from '@nestjs/common'
import { InjectRepository } from '@nestjs/typeorm'
import { Repository } from 'typeorm'
import { User } from './user.entity'
import { CreateUserDto } from './dto/create-user.dto'
@Injectable()
export class UserService {
constructor(
@InjectRepository(User)
private userRepository: Repository<User>
) {}
async create(createUserDto: CreateUserDto) {
const user = this.userRepository.create(createUserDto)
return await this.userRepository.save(user)
}
async findAll() {
return await this.userRepository.find()
}
async findOne(id: number) {
return await this.userRepository.findOne({ where: { id } })
}
async remove(id: number) {
await this.userRepository.delete(id)
}
}
- 用 Cursor 打开这个文件夹
演示步骤
Step 1:打开 before.ts,展示传统写法
Step 2:按 Cmd+L(Windows:Ctrl+L)打开 Cursor Chat
Step 3:在 Chat 输入框里输入以下 Prompt,按 Enter 发送:
创建一个用户管理模块,要求:
- 使用 NestJS + Prisma ORM
- 包含 CRUD 完整接口
- 字段:id、username、email、createdAt
- email 字段需要唯一校验
- 删除时软删除(deletedAt 字段,不真正删除数据库记录)
- 接口返回统一的 ResponseDto 格式:{ code, data, message }
- 所有接口加 Swagger 注解
Step 4:等待 AI 生成完成,检查以下内容是否都在结果里:
| 检查项 | 期望值 |
|---|---|
| ORM 类型 | Prisma(不是 TypeORM) |
| 软删除字段 | deletedAt: DateTime? |
| 返回格式 | ResponseDto封装 |
| Swagger 注解 | @ApiTags、 @ApiOperation |
| email 校验 | @unique或 @IsEmail() |
Step 5(可选):在 Chat 里继续追加要求,演示迭代能力:
在 findAll 接口里加上分页功能,支持 page 和 pageSize 参数,默认第 1 页每页 10 条
Step 6:对比 before.ts(传统写法)和 AI 生成的代码:
| 对比维度 | 传统写法 | Vibe Coding |
|---|---|---|
| 耗时 | 5~30 分钟 | 30 秒 |
| 是否需要查文档 | 是 | 否 |
| 软删除 | 需要自己想到并实现 | Prompt 里写了就有 |
| Swagger 注解 | 需要自己加 | Prompt 里写了就有 |
| 统一返回格式 | 需要自己封装 | Prompt 里写了就有 |