Vibe Coding 悖论:感觉编程的质量陷阱
开发者分享一次删除 312 行代码的 PR,虽然大幅删减却保持代码质量。讨论凭直觉编程与实际效果的矛盾。
开发者分享一次删除 312 行代码的 PR,虽然大幅删减却保持代码质量。讨论凭直觉编程与实际效果的矛盾。
我最近为 Nudges 提交的一个 PR,新增 96 行、删除 312 行,改动涉及 38 个文件,其中大约 90% 都是 vibe coding 完成的。而且我对它很有信心。
当我在 Hyrule 世界里畅游时,两个不同的 AI Agent 正悄无声息地重构 Kafka consumer、验证 payload 的结构,并提交代码变更——干净、聚焦,而且达到了 production-ready 的水平。等我回来后,我扫了一遍 diff,看着那些函数名点了点头,又复查了几个关键位置,然后让 Claude Code 提交了 PR。
关键在于:这种感觉很好。因为在这个系统里,AI 不只是在猜——它是在一个由我精心构建的系统中工作。这个系统的架构、消息格式、telemetry,以及可能产生的后果,都由我负责。Nudges 是我的。因此,当代码开始自行编写时,我感觉它就像我个人意志的延伸。
然而,同样的体验——把 AI 当作共同开发者,顺畅而高效——到了我的外包项目里,感受却完全不同。
因为在那里,系统不属于我。我甚至不信任这个系统。我只是一个 contractor,在 30 万行勉强能够运行的代码里摸索前进。那里的架构债务要以年为单位衡量,每一次所谓的“改进”,都有可能引发级联故障。在这种情境下,AI 带来的并不是赋能感。它更像是一面抵御认知过载的盾牌。
代码依然由它来写。但我并不总有余力去关心它是不是最好的代码。
而这——比其他任何事情都更能体现这个新时代的悖论:AI 消除了摩擦。但过去,我们恰恰是在这些摩擦中判断什么才真正重要。
事情始于一张本不该存在的 ticket。
一位客户希望,当表单恰好处于某种特定状态时,UI 能够发出警告。它所包含的规则,又与另外十几条规则彼此重叠。
那简直是一团乱麻。纠缠不清的逻辑,被包裹在前后矛盾的命名规范,以及多年积累的“我们下个版本再处理”式技术债之中。我打开那个 React component。整整 1100 行。绝大部分都是条件判断。没有测试覆盖。没有文档。只有 vibes 和层层嵌套的三元表达式。
我打开 Copilot,按下 Win+H,然后开始说话。
我解释了自己想要实现什么、为什么这件事很重要,以及应该去哪里寻找相关上下文。然后,我向后一靠,揉了揉眼睛。
剩下的部分由一个 AI Agent 写完了。
它创建了一组全新的变量和检查逻辑。每一个都做了 memoization。每一个都有防御性处理。每一个都承载着恰到好处的语义,让我不必重构整个组件,也能继续推进工作。
诱惑就在这里:它写得比我自己动手更加精确。因为我已经累了。因为写了三十年代码之后,当 AI 所做的那些“额外工作”在技术上完全正确时,我并不总有精力坚持用所谓“正确”的方式来完成它。
所以我保留了这些代码。我检查过它。它也确实能够正常运行。代码读起来不错,diff 看上去也很专业。
但我内心深处很清楚——我刚刚又往一个原本就应该只有 300 行的文件里塞进了 30 行代码。
我正在让糟糕的模式延续下去。
我提交了 PR。因为它是正确的。因为这样一来,我就少了一件需要操心的事。
我本可以把这部分逻辑提取出来。我可以把 validation 逻辑拆分到一个独立 module 中,接入一套 test harness,并把整个结构整理到只需使用 “Go to Reference” 就能看懂的程度。说到底,我甚至完全可以自己把它写出来。
但那意味着,我得花两个小时去理解这团乱麻。而我真正需要的,只是用十分钟保持推进的势头。
在一些外包项目中,我每周都要做出几十次这样的取舍:
“正确”的方式:提取、写文档、测试——2 小时。
“足够好”的方式:保持命名清晰,让它能够运行,然后发布——5 分钟。
再把它乘以每周无数次类似的决定。
你就会逐渐看清它的轮廓。
我使用 AI 写代码,并不是因为我自己做不到,也不是因为我懒惰或者漠不关心。
我和 AI 一起写代码,是因为我已经学会了应该把精力用在哪里,才能发挥最大的价值。
而游戏规则正是在这里发生了改变。
因为现在,要做到“足够好”实在太容易了。AI 会提供清晰的命名、聪明的 guard,以及可复用的模式。那条只需五分钟的路径,看上去和需要两小时的路径一模一样——直到你把视角拉远。
你不再意识到自己其实是在做紧急分诊。因为那些绷带看起来就像真正的皮肤。
引用 Richard Campbell 的一句话:“计算机是放大器。”
所以我们要把话说清楚:AI 不会改善你的系统。它只会延续你的系统。
如果现有模式足够干净,它就会把清晰度规模化。如果现有模式已经坏了,它就会把失调规模化——格式优美、语义命名完善的失调。
它会复制一切:
而且整个过程毫无阻力。因为这些代码看上去是正确的。
没有红旗。没有拼写错误。只有一个个细微的不协调之处不断堆叠,直到你被埋进一大堆干净却错误的逻辑之中。
过去你能感受到这种问题——你必须与系统搏斗。现在,系统却像行驶在轨道上一样顺滑地向前推进。如果你没有保持警觉,它就会把你带到一个你从未想过要去的地方。
区别不在于工具,而在于上下文。
在 Nudges 中,系统属于我。我在乎它是如何构建的,因为六个月后,我依然会置身其中。每一个 event、每一个 topic name、每一条 module boundary——都是我亲手构建的。因此,当 AI 添加某些内容时,我立刻就能看出来:它应该放在这里吗?它符合我原本想要构建的系统目标吗?
如果不符合呢?我会停下来。我会修正它。我会轻推一把,让它重新回到正确的轨道上。因为我希望这个系统能够长久维持下去。
在这种情境下,AI 放大的是我的用心。它让我能够在不降低标准的前提下更快推进——因为这些标准从一开始就已经嵌入设计之中。
但在我的外包工作中呢?
系统不属于我。我只是接手它,修补它。而当 AI 提供一个解决方案时,我不会停下来问:“这是 best practice 吗?”我问的是:“它能运行吗?能发布吗?能撑过下一次 merge 吗?”
因为这就是这份工作。因为在这里,用心的成本高于仅仅保证正确的成本,而无论选择哪一种方式,得到的回报都完全相同。
这与能力无关。我并没有老到做不动。我也没有变慢。改变的并不是我能做什么——而是我选择做什么,以及什么时候去做。
我 merge 了那个为 Nudges 提交的 PR。就是我玩电子游戏时,由那些 Agent 写出来的 PR。它很漂亮,也完全正确。但它之所以正确,是因为我花了两年时间构建那些能够确保它正确的约束。
明天,我还会处理客户的另一张 ticket。我会打开一个散发着 2018 年气息和悔恨味道的文件。然后,我可能会让 AI 修补一个本该从根源上解决的漏洞。它会很丑陋。它会“足够好”。而且它会恰如其分地符合这个系统应得的样子。
因为如果代码能够自行编写,我们的双手就会离开键盘。但我们的指纹,却无处不在。
部分评论可能只有登录后的访客才能看到。请登录以查看全部评论。
如需采取进一步行动,你可以考虑屏蔽此人和/或举报滥用行为。