☰
Vibe Coding 正在批量制造屎山?AI 编程的四个结构性缺陷与避坑指南
2026/10/20 14:37:33 网站建设 项目流程

1. 当“感觉对了”成为编程新范式

“Vibe Coding”这个词最近在开发者圈子里出现的频率越来越高。它的核心主张听起来很诱人:你不需要逐行写代码,不需要深入理解底层逻辑,只需要用自然语言描述你想要什么,让AI生成代码,然后凭“感觉”判断能不能跑、对不对。跑通了就继续,报错了就把错误信息丢回去让AI修,循环往复,直到“感觉差不多了”就交付。

我第一次接触这种工作方式是在一个内部工具的开发场景里。当时需要快速搭一个数据处理脚本,需求不算复杂但涉及好几个库的调用。按照传统方式,我得查文档、调参数、处理边界情况,大概需要半天。有人建议我试试“Vibe Coding”——直接告诉AI我要什么,让它生成,我只看结果对不对。说实话,前二十分钟体验非常好,代码刷刷地出来,运行也通过了。但当我试图在这个基础上加一个新功能时,问题出现了:我发现自己根本看不懂之前生成的代码,变量命名毫无规律,函数职责混乱,同一个逻辑在三处不同的地方用三种不同的方式实现。那一刻我意识到,我可能正在亲手制造一座“屎山”。

这篇文章想聊的,不是“AI能不能写代码”这种已经被讨论烂了的话题,而是一个更根本的问题:当“Vibe Coding”把编程从“理解驱动的构建”变成“感觉驱动的拼凑”,我们到底在做什么?它解决了什么问题,又制造了什么问题?哪些场景适合用,哪些场景用了就是给自己挖坑?如果你是一个正在使用或准备使用AI辅助编程的开发者,无论你是刚入行的新手还是有一定经验的老手,这篇文章里的观察和思考应该都能帮你少踩几个坑。

2. Vibe Coding到底在做什么:从“理解驱动”到“感觉驱动”的范式转移

2.1 传统编程的认知模型:心智模型先行

要理解Vibe Coding的问题,得先搞清楚传统编程是怎么工作的。写代码这件事,表面上是敲键盘,实际上是一个持续构建心智模型的过程。你在写一个函数之前,脑子里已经大致有了数据怎么流动、状态怎么变化、边界在哪里。你选择用数组还是链表,不是随便选的,是因为你理解了两者在插入和查找上的性能差异。你决定把逻辑拆成三个函数而不是一个,是因为你预判了未来的扩展方向。

这种“理解先行”的模式有一个关键优势:当代码出问题时,你有能力定位。因为你知道每一行代码为什么在那里,所以当行为不符合预期时,你可以沿着自己的理解路径去排查。这就像你亲手搭了一个书架,哪块板子松了你一摸就知道。而Vibe Coding模式下,你面对的是一个别人(AI)搭的书架,你只知道它看起来像个书架,但哪块板子承重、哪颗螺丝吃劲,你完全不清楚。

2.2 Vibe Coding的工作循环:生成-运行-反馈-再生成

Vibe Coding的典型工作流是这样的:你用自然语言描述需求,AI生成一段代码,你运行,如果报错就把错误信息贴回去让AI修,如果没报错但结果不对就描述现象让AI调,循环直到“看起来能用”。整个过程的核心反馈信号是“能不能跑”和“结果对不对”,而不是“代码为什么这样写”。

这个循环有一个隐蔽的陷阱:每一次“修复”都是一次局部补丁,而不是对整体结构的调整。AI在修复错误时,倾向于在现有代码上打补丁,而不是重构。这就导致代码库随着迭代次数的增加,逐渐变成一个“补丁摞补丁”的结构。更麻烦的是,这些补丁之间的逻辑关系你并不清楚,因为每一轮修复你只关注了当前报错的那个点。

我见过一个典型的例子:一个用Vibe Coding方式生成的API接口,最初版本只有二十行,功能正常。后来陆续加了参数校验、错误处理、日志记录、缓存逻辑,每次都是“出问题了就让AI加一段”。最终这个接口变成了两百多行,里面有四层嵌套的try-catch,三个不同风格的错误返回格式,以及两处互相矛盾的缓存失效逻辑。没有人敢动它,因为没人知道动了之后会影响到什么。

2.3 “感觉对了”的认知偏差:流畅性错觉与达克效应

Vibe Coding之所以让人上瘾,是因为它制造了一种强烈的“流畅性错觉”。心理学上有个概念叫“加工流畅性”,当信息处理变得容易时,我们会倾向于认为它更真实、更正确。AI生成的代码通常语法正确、格式整齐、注释齐全,读起来很“顺”,这种顺畅感会让我们误以为代码质量很高。

但代码质量和可读性、格式规整度之间的关系很弱。一段代码可以格式完美但逻辑混乱,可以注释详尽但实现错误。Vibe Coding模式下,你缺乏深入阅读和理解的动机,因为“它能跑”。这种状态持续久了,会形成一种能力退化:你越来越依赖AI来理解和修改代码,自己独立排查问题的能力在下降。这就是达克效应的典型表现——你不知道自己不知道什么,因为AI帮你把“不知道”的部分掩盖了。

3. 屎山是如何被批量制造的:Vibe Coding的四个结构性缺陷

3.1 缺乏全局架构视角:局部最优的累积

AI生成代码时,它的上下文窗口是有限的。它看到的是你当前描述的需求和它自己之前生成的那部分代码,而不是整个项目的全貌。这意味着它做出的每一个决策都是局部最优的,但这些局部最优叠加起来,很可能指向一个全局最差的结果。

举个例子:你在项目A模块让AI生成一个日期格式化函数,它用了方案X。后来在B模块你又让AI生成类似功能,由于上下文不同,它用了方案Y。再后来C模块用了方案Z。三个模块各自都能跑,但整个项目里存在三套日期处理逻辑,维护成本翻了三倍。传统编程中,一个有经验的开发者会在第二次遇到同样需求时想到复用,但Vibe Coding的交互模式天然抑制了这种全局思考——你每次只关注当前这个功能能不能跑通。

3.2 错误处理的表面化:try-catch掩盖的逻辑漏洞

AI在处理错误时有一个非常明显的倾向:用try-catch把可能出错的地方包起来,然后打印日志或者返回一个默认值。这种做法在语法层面是正确的,但在逻辑层面往往是灾难性的。因为它把“错误”变成了“静默失败”,问题被掩盖了而不是被解决了。

我审查过一个Vibe Coding生成的数据同步脚本,里面有一个关键步骤是从源读取数据写入目标。AI生成的代码在写入失败时catch了异常,然后log了一句“写入失败”,接着继续处理下一条。表面上看这很健壮——一条失败不影响其他。但实际上,这个脚本的调用方完全不知道有数据没写进去,后续的报表和分析全部基于不完整的数据。这种“看起来能跑”的代码,比直接崩溃的代码危险得多,因为崩溃至少会让你知道出了问题。

3.3 命名与抽象的随机性:语义漂移的累积效应

变量命名和函数抽象是代码可读性的基石。好的命名能准确传达意图,好的抽象能隐藏复杂度。但AI生成代码时,命名和抽象的质量极不稳定。同一个概念,它可能在这个函数里叫data,在那个函数里叫payload,在第三个地方叫input。你让AI“优化一下命名”,它可能会把data改成rawData,但不会去统一整个项目的命名风格。

更严重的是抽象层级的混乱。AI有时会把本该拆分的逻辑塞进一个巨型函数,有时又会把简单的操作过度抽象成多层调用。这种不一致性随着代码量的增长会形成“语义漂移”——你看到processData这个函数名,以为它做的是数据清洗,点进去发现它其实在做格式转换,再往下看发现它还顺带发了通知。每次阅读这样的代码,你都需要重新建立理解,认知负担极重。

3.4 测试的缺失与“手动验证”的陷阱

Vibe Coding的工作流里,测试通常是被忽略的。因为整个循环是“生成-运行-看结果”,这个“看结果”就是最原始的手动测试。你运行一下,输入几个样例,输出对了,就认为没问题了。但手动测试的覆盖率和边界情况处理,和自动化测试完全不是一个量级。

AI可以帮你生成测试代码,但前提是你得知道要测什么。而Vibe Coding模式下,你对代码的理解本身就不深,很难设计出有效的测试用例。这就形成了一个恶性循环:不理解代码导致测试不充分,测试不充分导致问题被遗漏,问题被遗漏导致你更不敢改代码,更不敢改导致你更依赖AI来修改,依赖AI导致你更不理解代码。

4. 什么场景能用,什么场景用了就是挖坑

4.1 适合Vibe Coding的场景:一次性脚本与原型验证

说了这么多问题,并不是要全盘否定Vibe Coding。它在某些场景下确实能大幅提升效率。关键判断标准是:这段代码的生命周期有多长,以及出错的代价有多大。

一次性脚本是最适合的场景。比如你有一个CSV文件需要做格式转换,用完就扔,不会有人维护,出错了重新跑一遍就行。这种场景下,Vibe Coding的效率优势非常明显,你不需要理解pandas的每一个参数,只需要结果正确。

原型验证也是合适的场景。当你需要快速验证一个想法是否可行时,用Vibe Coding快速搭一个能跑的demo,看看效果,然后决定要不要投入资源正式开发。这个阶段的目标是“验证”而不是“交付”,代码质量可以暂时让步。

4.2 需要警惕的场景:长期维护的业务代码

一旦代码需要长期维护、多人协作、或者涉及关键业务逻辑,Vibe Coding的风险就会急剧上升。长期维护意味着代码会被反复修改,而每次修改都需要理解现有逻辑。如果原始代码就是“感觉驱动”生成的,后续维护者(包括未来的你自己)将面临巨大的理解成本。

多人协作场景下,问题更严重。你的同事需要读懂你的代码,需要在你代码的基础上扩展。如果代码的命名、结构、错误处理都没有一致的逻辑,协作效率会大幅下降。代码审查也会变得困难,因为审查者很难判断一段“能跑但看不懂”的代码是否真的正确。

4.3 绝对不要用的场景:安全敏感与数据一致性要求高的模块

涉及安全认证、权限控制、支付逻辑、数据一致性保证的代码,绝对不应该用Vibe Coding的方式生成。这些领域的共同特点是:错误不是“能不能跑”的问题,而是“跑错了会怎样”的问题。一个权限校验的漏洞、一个事务边界的错误、一个加密参数的误用,后果可能是灾难性的。

AI在这些领域生成代码时,表面上看起来往往很“专业”——用了正确的库、调用了正确的API、参数看起来也对。但安全逻辑的微妙之处在于边界条件和异常路径,而这些恰恰是AI最容易出错的地方。比如一个JWT校验,AI可能正确实现了签名验证,但忘记检查过期时间,或者把算法混淆攻击的防护漏掉了。这些漏洞在手动测试中很难发现,但一旦被利用,后果严重。

5. 从“感觉驱动”回到“理解驱动”:一套可操作的实践框架

5.1 建立“理解门槛”:不理解的代码不合并

最核心的一条原则:任何进入主分支的代码,你必须能解释清楚它的执行路径。这不是说你要逐行注释,而是说如果有人问你“这段代码在输入X的情况下会怎么走”,你能回答上来。如果回答不了,说明你还没有真正理解它,不应该把它合并到需要长期维护的代码库里。

这个门槛听起来很高,但它是防止屎山积累的最有效手段。具体操作上,你可以采用“三问法”:这段代码的输入是什么?输出是什么?中间的关键决策点在哪里?如果你能清晰回答这三个问题,说明你对代码有了基本的理解。如果回答得含糊,那就需要继续深入。

5.2 用AI做“解释器”而不是“生成器”

AI在编程中的一个被低估的用法是:让它解释代码,而不是生成代码。当你拿到一段不理解的代码时,可以让AI逐段解释它在做什么。这个过程中,你是在主动构建理解,而不是被动接受结果。解释完之后,你可以追问“如果输入是空数组会怎样”“如果网络超时了会走哪条路径”,通过这些问题来验证你的理解是否完整。

这种用法把AI从“代笔者”变成了“助教”,你仍然是理解的主体,AI只是帮你加速理解过程。长期来看,这种模式对你的能力增长是有益的,而不是像纯生成模式那样导致能力退化。

5.3 强制重构节点:每N次迭代做一次结构整理

Vibe Coding的迭代模式天然倾向于“只加不改”。为了对抗这种倾向,你需要人为设置重构节点。一个可操作的方法是:每完成一个小功能,花十分钟回顾一下这次改动涉及的代码,看看有没有重复的逻辑可以抽取、有没有命名不一致的地方可以统一、有没有错误处理可以简化。

这个习惯的关键是“强制”——不要等到代码烂得没法看了再重构,而是把它变成开发流程的一部分。就像吃饭后要洗碗,不是等碗堆成山了再洗。十分钟的投入,换来的是后续维护成本的指数级下降。

5.4 测试先行:用测试用例锁定行为边界

在让AI生成代码之前,先想清楚这段代码应该满足哪些行为。把这些行为写成测试用例,然后再让AI去实现。这样做的好处是:测试用例是你写的,你理解每一个用例的意图;AI生成的代码必须通过这些用例,相当于有了一个客观的验收标准。

测试用例还有一个额外的好处:它们是代码行为的文档。当后续有人(包括你自己)需要修改这段代码时,跑一遍测试就知道有没有破坏原有功能。这比读代码去理解行为要可靠得多。

6. 常见问题与排查技巧实录

6.1 AI生成的代码“能跑但看不懂”怎么办

这是Vibe Coding最典型的问题。我的建议是:不要急着在上面加功能,先花时间理解它。具体做法是,让AI逐段解释代码,然后你自己画一张流程图或者写一段伪代码来总结它的逻辑。如果你能用自己的话把这段代码讲清楚,说明你理解了;如果讲不清楚,继续追问AI,直到能讲清楚为止。

如果代码实在太乱,理解成本高于重写成本,那就果断重写。重写的时候,你可以参考AI生成的版本,但要用自己的结构来组织。这样你既利用了AI的效率,又保证了自己对代码的理解。

6.2 错误处理越加越多但问题依然存在

这通常是因为错误处理加在了错误的层级。AI倾向于在出错的地方就地catch,但正确的做法往往是在更上层统一处理。比如一个数据写入操作,在写入函数里catch异常并返回false,调用方检查返回值决定是否重试——这比在写入函数里catch后打印日志继续执行要合理得多。

排查这类问题时,你可以问自己:这个错误发生了,谁最应该知道?谁最有能力处理?把错误处理放在那个层级,而不是放在错误发生的地方。

6.3 代码越改越慢,每次改动都提心吊胆

这是屎山形成的典型信号。代码的修改成本已经超过了它的价值。这时候需要做一个决策:是继续打补丁,还是停下来重构。判断标准是:如果下一个需求的实现需要改动超过三个地方,或者改动一处会影响到你不确定的范围,那就应该重构。

重构不一定要大动干戈。可以从最痛的那个点开始,把相关的逻辑抽出来,理清依赖关系,加上测试,然后再继续。关键是不要继续在烂代码上叠加新功能,那只会让问题更严重。

6.4 如何判断一段AI生成的代码是否可以信任

一个实用的检查清单:第一,看它有没有处理边界情况(空输入、超长输入、特殊字符);第二,看它的错误处理是“静默失败”还是“明确报错”;第三,看它的命名是否一致,同一个概念是否用了同一个名字;第四,看它有没有硬编码的值(比如写死的路径、密钥、超时时间);第五,看它有没有明显的性能问题(比如循环里查数据库)。

如果这五点都通过了,代码基本可以信任。如果有任何一点存疑,就需要进一步审查或者让AI修改。

7. 一些个人体会

我用Vibe Coding的方式做过不少事情,从数据处理脚本到内部工具的原型,也踩过不少坑。最大的体会是:AI生成的代码质量,很大程度上取决于你给它的约束。如果你只说“帮我写一个函数处理用户数据”,它会给你一个能跑但随意的实现。如果你说“帮我写一个函数,输入是用户对象数组,输出是按注册时间排序的用户名列表,要求处理空数组和null元素,命名用驼峰式,错误处理返回空数组而不是抛异常”,它会给你一个质量高得多的结果。

所以问题不在于AI能不能写好代码,而在于你有没有能力把需求描述清楚。而把需求描述清楚的前提,是你自己先想清楚了。这又回到了那个核心观点:理解驱动,而不是感觉驱动。AI是一个放大器,你理解得越深,它帮你放大的效果越好;你理解得越浅,它帮你放大的混乱也越多。

另一个体会是关于“什么时候停”。Vibe Coding很容易让人陷入“再调一下就好了”的循环,尤其是当AI每次都能给你一个“看起来有希望”的修改时。但有时候,停下来重新思考比继续调更有价值。我的经验是:如果同一个问题调了三次还没解决,就应该停下来,回到需求本身,看看是不是方向错了。继续在错误的方向上让AI帮你微调,只会离目标越来越远。

最后说一个具体的技巧:让AI生成代码时,要求它同时生成一段“设计说明”,用自然语言解释这段代码的结构和关键决策。这个说明不需要很长,几句话就行。它的价值在于,当你几天后回来看这段代码时,这份说明能帮你快速恢复上下文。而且写说明的过程本身也会迫使AI更认真地组织代码结构,减少随意性。这个习惯我坚持了一段时间,效果很好,推荐你也试试。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询