关于 Vibe Coding 的一些思考 (1)

前传 · 一

2022 年 11 月 30 日,OpenAI 发布了 ChatGPT。8 天之后,我在 Preston 的学生公寓里,收到了一个数据分析师岗位的面试邀请。我打开它,对 GPT-3.5 发出了第一条消息:

2022 年底,我对 GPT-3.5 发出的第一条消息:我该说什么才能通过统计分析的面试?
我对 GPT-3.5 发出的第一条消息

我该用什么词形容当时的心情?喜悦?震惊?还是恐惧?

我就像第一次见到火的原始人——还不懂怎么把它保存下来,除了烤熟食物之外也想不出它还能干嘛,但我心里清楚得很:这就是未来。

12 天之后,我拿到了那份 Offer。

前传 · 二

2023 年 3 月 14 日,我入职刚满三个月,GPT-4 发布了。

它真正让我震惊的地方,不在于比 GPT-3.5 聪明了多少,而在于它是第一个能看懂图像的多模态模型。在那之前,我每天的工作是盯着一张张曲线图,慢慢琢磨某户人家的用电为什么异常,再一个字一个字地写成报告——写完还不算完,得先丢进 Grammarly 把语法捋顺一遍,才敢发给客户。而从那天起,我只需要截一张图,配上一句最简单的 Prompt,它就能还我一份详尽得近乎夸张、且挑不出一个语法错误的分析。

我仿佛眼睁睁看着一朵蘑菇云在面前升起,整个人瘫在工位上,好半天没缓过来。

前传 · 三

2026 年 1 月 5 日,我翻出很多年前发布的一些老视频,发现它们在新设备上已经放不利索了:画面上是隔行扫描拉出的一道道梳齿,有的干脆连声音都解不出来。我想把它们重新转一遍码,找了一圈工具,却发现根本没有好的选择:格式工厂那类全家桶,塞满了各种捆绑软件和广告;FFmpeg 倒是干净,可它没有图形界面,对普通人来说约等于天书,想调参数,或者批量转换,效率也是低得可怜。

于是我心想:要不,自己做一个?

搁一年前,这种念头闪一下也就过去了——我又不会写代码。但这一次,我把想法丢给了 Claude Opus 4.5。结果,它几乎是 one-shot 就把整个软件搭了出来。

如果说 GPT-3.5 是我第一次见到火,GPT-4 是我看着这团火在面前升起成蘑菇云,那这一次,是我第一次意识到:原来我也可以自己生火、自己造工具。我的编程之旅,就这么开始了(成品在这里:NextGen Hyperspeed Video Converter)。

正传 · 我用上了火,但没学会怎么生火

在那之后,我就一头扎进了所谓的 vibe coding:把需求丢给 AI,它把代码铺出来,我大致扫一眼,觉得没什么问题,按下 Approval;页面跑起来了,功能也是对的,一切都顺利得超出我的预期。

大概过了两三个星期,我才意识到一件事:这段时间里,我几乎什么都没记住。昨天 AI 帮我写的那段 function,今天让我自己就写一遍,我一行都写不出来。不是我「忘了细节」——是它压根就没在我脑子里留下过痕迹。代码躺在「我的」项目里,但那段逻辑,从来没有真正进过我的脑子。

火我确实用上了;但生火这件事本身,我好像并没有学会。这让我多少有些不安,于是我去搜了搜:问题到底出在哪里?

一、按下 Approval 是「再认」,不是「生成」

心理学里有一个很老的结论,叫生成效应(Generation Effect):人对自己亲手产出的东西,记忆要远远强于只是读到、认出来的东西。而 vibe coding 的日常,恰好全落在「认出来」这一边:AI 把代码生成出来,我扫一眼,觉得没问题,按下 Approval——从头到尾,没有一步是亲手产出。脑子没出过力,自然什么都留不下。

与之配套的还有一个结论,叫“提取练习”(retrieval practice),也叫测试效应:记忆是在「费力把答案从脑子里取出来」的过程中被巩固的,回忆得越吃力,记得越牢。而 AI 做的事情,恰恰是把答案直接摆到你面前——连「取」这个动作都省了,「巩固」自然也无从谈起。

想通这一点之后,我反而松了口气:不是我变笨了,而是我把形成长期记忆的那道工序,整个跳过去了。

二、「还是老办法练出来的人强」——这句话已经说了七十年

我的第二个念头是:会不会老一辈程序员,就是比我们这一代强?毕竟他们是「古法编程」练出来的。

结果一查才发现,这种想法至少已经重复了七十年——几乎每一代程序员都坚信同一件事:下一层抽象,会把人惯废。FORTRAN 刚出现的时候,就因为「手写汇编更高效」而被不少人看不起,第一门高级语言一度被当成偷懒的工具;1983 年的那篇讽刺文 《Real Programmers Don't Use Pascal》,把汇编原教旨主义者的信条——「不能用汇编干的事,就不值得干」——揶揄了一番,在他们眼里,连结构化编程都属于学院派的自我陶醉;再往后,就轮到 C 程序员看不上 Java 和 Python 了。一圈一圈,循环往复。

有意思的是,每一层新的抽象在问世之初,都会被下面那一层的人骂作「作弊」;可事后看,每一次抽象的上移,最后都把这个行业变得更大、让程序员变得更多,而不是更少(想看完整的脉络,可以看看编程语言简史)。所以「还是古人牛逼」的感慨,大概只是这句说了七十年的老话,轮到我来说一遍而已。

三、古人的牛逼,是被逼出来的

那么,古人的牛逼到底是从哪儿来的?我现在的答案是:不是天赋,而是当年的环境没有给他们别的选择。

以前写前端,这种东西你得背得滚瓜烂熟:

JavaScript
document.querySelector("#btn").addEventListener("click", function () {
  console.log("clicked");
});

写后端,你得心里有数:

JavaScript
app.get("/users", async (req, res) => {
  const users = await db.user.findMany();
  res.json(users);
});

写 SQL,你得能直接从脑子里蹦出来:

SQL
SELECT * FROM users WHERE email = 'test@example.com';

写 React,你得真的理解这一行意味着什么:

JavaScript
const [count, setCount] = useState(0);

这些看起来只是语法,但每一行底下都压着一整套概念:DOM 是什么?event listener 是什么?request 和 response 是什么?async / await 是什么?state 一变,页面凭什么会自己重新渲染?数据库查询和后端接口之间,又是什么关系?AI 可以直接把代码端给你,但它不会顺便把这些概念也放进你的脑子。少了亲手敲、亲手跑、亲手 debug 的那一遍遍折腾,大脑就长不出那套稳定的结构。

四、为什么你会觉得「语法怎么都学不会」

如果你正在学编程,而且满脑子都是「我连语法都学不会」,我想说:问题大概率不在语法本身,而在下面这三道断层里。

断层一:输入太高级,输出太完整

你对 AI 说:「帮我写个登录页,接后端 API,带登录验证。」它立刻交给你一整套:React 组件、表单状态、fetch 请求、token 存储、路由跳转、错误处理、后端接口、中间件、数据库查询。对一个新手来说,这个信息密度是没法消化的——你面前是一个完整的系统,可你还没有沿着:

变量 → 函数 → 对象 → 异步 → HTTP → 组件 → 状态 → 数据库 → 鉴权

这道梯子一级一级爬上来。于是你得出了「我连语法都学不会」的结论。但这其实不是语法的问题,而是抽象层级跳得太快了。

断层二:AI 替你省掉了犯错的过程

老程序员为什么记得牢?因为他们一遍一遍地经历过这个循环:写错 → 报错 → 翻资料 → 改对 → 又报错 → 再翻 → 终于跑通。比如手一抖写出:

JavaScript
const name = "Jack";
name = "Tom";

然后撞上一句:

Output
TypeError: Assignment to constant variable.

有过这么一次,你大概一辈子都不会忘记 const 不能重新赋值。可如果 AI 直接把正确的代码递到你手里,你就只是「看过」,而没有「错过」——看过和会了,是两回事。

断层三:现代前后端,本来就比从前复杂得多

如果你觉得「现在的前后端怎么这么多东西要学」,这个感受并不夸张,是真的。前端早就不是 HTML / CSS / JS 三件套了:框架(React / Vue / Svelte)、Node.js、包管理(npm / pnpm)、构建工具(Vite / Webpack)、REST / GraphQL、状态管理、路由、认证、部署、CI/CD,一层摞着一层;后端也不是写几个接口就完事:语言、框架、数据库、ORM、缓存、队列、鉴权、日志、错误处理、测试、容器、云服务、安全、性能……同样是一长串。所以你并不是学不会,而是一上来就站在了一座膨胀了几十年的技术栈脚下。别忘了,那些「古法程序员」也是一层一层爬上来的——没有谁能在一天之内学完 React、Next.js、PostgreSQL、Docker、Kubernetes、Python 和 Rust。

而且在过去,这座山还不用一个人爬完:做前端的可以一辈子不碰数据库,做后端的可以不关心命令式和声明式 UI 都是什么玩意,吃透一两门语言,就够撑起一整个职业生涯。到了 AI 时代反过来了——既然什么都可以自己做,什么就都得自己面对:前端、后端、数据库、部署,一个人全包。山没有变矮,只是从各爬各的一段,变成了一个人从头爬到顶。

五、拿一段真实的代码来拆一拆

比如你让 AI 写一个登录功能,它可能直接给你这么一段:

JavaScript
const response = await fetch("/api/login", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ email, password }),
});

const data = await response.json();
localStorage.setItem("token", data.token);

如果你没什么基础,这短短几行会同时抛给你一连串问题:const 是什么?await 是什么?fetch 是什么?headers 是什么?JSON.stringify 是什么?response.json() 为什么还要再 await 一次?localStorage 是什么?token 又是什么,为什么非得存起来?你以为自己是「不懂 JavaScript 语法」,其实你是在同一时刻面对了六样东西:变量声明、异步编程、HTTP 协议、JSON 编码、浏览器存储、登录鉴权。觉得难,才是正常的。

更合理的办法,是一层一层来。第一层,只看变量:

JavaScript
const email = "jack@example.com";
const password = "123456";

第二层,对象:

JavaScript
const user = {
  email: "jack@example.com",
  password: "123456",
};

第三层,函数:

JavaScript
function login(user) {
  console.log(user.email);
}

第四层,异步:

JavaScript
async function login() {
  const response = await fetch("/api/login");
}

到第五层,才轮得到完整的登录流程。

六、会写代码,已经不重要了

写到最后,我真正想说的其实是:到了今天,「会写代码」这件事本身,恐怕已经不重要了。语法、API、样板代码——IDE 能补,文档能查,AI 写得比绝大多数人又快又好。所以如果你总觉得自己「连语法都记不住」,别急着下「我不是这块料」的结论:你记不住的那部分,恰恰是最先贬值的那部分。

真正重要的东西,已经跑到代码外面去了:你有没有品味,分得清什么是好东西、什么是凑合能用;你了不了解真实的痛点,知道人们到底被什么卡着;你能不能把一个模糊的想法讲清楚,讲到 AI——或者任何人——一听就知道该干什么;你会不会指挥工具,知道什么时候该换个问法、什么时候该推翻重来;东西做出来之后,你能不能站到用户那一边,判断它到底好不好用。甚至还有最容易被忽略的一样:你能不能意识到「这件事,现在我可以做了」——很多东西迟迟没被做出来,不是因为做不了,而是因为没人反应过来它已经可以做了。

所以,vibe coding 到底把我怎么了?写到这里,答案已经清楚了:它没有让我变笨,它只是把「写代码」这项技能的价格,打到了地板上。我那阵子的慌张,说白了是没反应过来——我在为一项正在贬值的技能焦虑,就像一个刚拿到打火机的人,还在懊恼自己没学会钻木取火。

人类学会生火,用了几十万年;把生火变成不值一提的小事,又用了几千年;而从生火不值一提,到造出足以毁灭所有人类的蘑菇云,只用了一百年。

关于本文

AI 生成内容
否
AI 校对内容
是(模型:Claude Fable 5)
AI 翻译内容
否
分享