如果你最近正在用AI辅助写代码(也就是很多人说的 Vibe Coding),那我大概已经知道你的真实状态了:第一版代码一口气跑通的时候,你觉得AI就是神;但等需求一改、一报错,你把问题丢回去,它改了A却弄坏了B,你再让它修B,它扭头又把A改崩了。来回几个回合之后,你已经分不清是AI在修Bug,还是它在给你制造Bug。
这篇我就想讲清楚一件事:为什么你和AI之间会陷入"越修越崩"的拉扯,以及用什么方法能把这个循环拦腰截断。我会给你一套我自己一直在用的四步法,每一步都会配上具体的对话写法、判断标准和踩坑记录,保证你看完能直接用。
1. 先看清你为什么会陷入"修一个Bug,长两个Bug"的循环
1.1 所谓Vibe Coding,本质是两种极端状态间的自由落体
Vibe Coding的字面意思是"跟着感觉写代码",听着很潇洒:你描述需求,AI生成代码,你验收效果。最上头的时刻是初版代码跑起来的那一刻,但很多人忽略了一件事——这个"感觉"在初期是顺畅的,一旦进入修Bug阶段,就会瞬间变成互相折磨。
我举一个很常见的例子。你让AI写一个搜索框,它给你一个过滤函数,你跑了一下,发现搜中文没结果。你把这句话发过去:"搜索中文不生效,帮我修一下。"AI回你一句"抱歉,可能是编码问题,已经修复"。你再试,中文好了,但原本工作正常的英文也挂了。你再报英文问题,它改完发现排序又乱了。此时你的心态已经从"AI真方便"跌到"这东西到底行不行",而对话记录已经从1条变成15条,每一条都在同一个文件里来回改。
这个循环的本质是什么?不是AI变笨了,也不是你指令不够详细——是上下文被污染了。AI不像人一样拥有持久记忆,它每次回答都基于当前对话历史来预测最可能的回复。当对话里堆满了修修补补的错误描述、半截代码片段和它的道歉,它自己都理不清现在这个文件到底处于什么状态。你让它修,它只能继续编,编出来的东西自然又引入新问题。
1.2 崩溃循环的三个显性特征,以及为什么传统调试经验失灵
陷入这种循环之后,一般会出现三个非常典型的特征:
第一个特征是修A坏B。AI并不真正理解整个项目的架构,它只是看到一个局部的代码片段,然后基于上下文猜测怎么改。如果你的项目里有多处地方调用同一个函数,它改了函数的内部逻辑,却没意识到其他调用方也会受影响。
第二个特征是"道歉式修复"。你仔细回想一下,AI在多次修改失败后,往往会先来一句"对不起,我之前的思路有问题,这次我重写了"。这句话听起来态度很好,但下次报错时,你会发现它改的方向和上次说的完全相反。道歉不是修复,它只是概率预测中的一个过渡态。
第三个特征是"越描越黑"。你会发现,当你试图补充更多信息时,问题反而更混乱:比如你把整个文件500行都粘过去,AI回复了一段完全偏离主题的方案——因为它被无效信息淹没了,分不清哪些是要害、哪些是噪音。
传统调试里有日志、断点、二分定位这些手段,为什么到AI辅助编程这里就失灵了?因为你面对的不是一个确定的程序,而是一个概率模型队友。你不能给它讲"我觉得是这里问题"就撒手,它会把你的猜测当成事实去展开。你得提供它真正需要的东西:一个具体到不能再具体的输入、输出和报错。这既是接下来四步法的出发点,也是你和AI协作时最需要转变的思维方式。
2. 告别来回拉扯的Vibe Coding四步法总览
2.1 四步法到底指哪四步
我自己总结的四步法,不是复杂的工程流程,而是四个逼着你把信息组织清楚的步骤。每次遇到Bug,按顺序走一遍,绝大多数情况下能在两轮对话内解决问题。
| 步骤 | 名称 | 核心理念 | 解决的核心问题 |
|---|---|---|---|
| 第一步 | 锁定问题边界 | 把"它不工作"翻译成一个可验证的断言 | 解决AI猜来猜去的问题 |
| 第二步 | 喂对上下文 | 报错原文、最小代码片段、预期vs实际 | 解决AI看错重点的问题 |
| 第三步 | 重写优先 | 让AI重写局部逻辑,而不是在烂代码上打补丁 | 解决补丁越叠越乱的问题 |
| 第四步 | 闭环验证 | 自己动手验证,不把"AI说修好了"当结论 | 解决反复回归的问题 |
这四个步骤其实对应的是一个合理外包工程师协同时的最低协作标准。你想象一下,如果你手里有一位外包程序员,你给他提需求时会怎么说?你不会只说"这个东西坏了",你会告诉他具体场景、具体报错、你期望什么。AI也是这样,只不过它还多了两个特性:它非常擅长在"重写"中纠正自己的错误;同时它也很容易在"修补"中叠加混乱。四步法正好利用了前者、规避了后者。
2.2 四步法背后的核心逻辑:把AI当外包工程师,不把AI当读心机器人
很多人用AI写代码,潜意识里是把它当成一个全知全能的人来用的。你觉得它在整个项目里什么都知道,所以你可以用模糊的话术跟它交流。但现实是,AI只能看到你放进对话窗口里的东西,它看不全你的项目,更不知道你脑子里那个"显而易见"的业务规则。你省掉的每一句描述,它都会用自己的"猜测"来补。
四步法的第一步锁定问题,本质上是逼着你自己先搞明白Bug到底是什么。很多时候你不需要AI,你自己在复现步骤里就能发现问题。而就算你不用自己找原因,你给AI一个精确的复现路径,它比你给一个含糊描述要容易处理得多。
第二步喂对上下文,是把模型的盲猜范围压缩到一个极小的空间。就像警犬找物证,你得先给它闻一下沾有气味的布料,它才能追对方向。你给的报错原文、出错的输入和最小代码块,就是那块"布料"。
第三步重写优先,是为了避免"拆东墙补西墙"。AI在原有烂代码上修修补补,很容易越修越乱,你不如让它推翻那一小块逻辑,从干净状态重新实现,这比你一遍遍打补丁要快得多。
第四步闭环验证,则帮你守住最后的防线。AI输出"已修复"的那一刻,并不代表任务真的结束了。你得亲自运行、验证边界、回归旧功能,确认改动没有炸掉别的地方。这套四步法最妙的地方,是它把最费时间的"反复拉扯"消灭在了前两步里,把最考验耐心的事情压缩到了最后一步——只验证一次,而不是验证十次。
3. 第一步 锁定问题:把"它不工作"翻译成一个可验证的断言
3.1 为什么"不工作"会让AI原地划水
"不工作"这句话在任何协作场景里都是灾难,跟AI协作尤其如此。因为"不工作"不是一个信息,而是一团情绪。AI收到这团情绪后,只能从概率上猜你的意思:是报错了?行为不对?还是结果不符合预期?它猜得越多,跑偏的概率就越高。
举个例子,一个典型的错误描述是:"我点了搜索按钮之后没反应,求帮看。"这句话没有任何参考点,"没反应"可能是点击事件没绑定,可能是搜索结果为空时界面没提示,可能是接口报错被吞掉了。AI大概会怎么做?它会试图覆盖所有可能性,写出一段兼顾各种情况的代码,导致的問題是:它根本不知道你这边的实际场景,写出来的"全能代码"在你的项目里根本无法直接用。
正确的做法是把Bug描述压缩成一句可验证的断言。什么叫断言?就是一句话里能说清"我做了X,输入是Y,期望结果是Z,实际结果是W"。断言有一个特征:你可以用它来明确判断代码是否通过。比如"当我输入中文关键字'苹果'时,期望返回包含苹果的两条数据,但现在返回了空数组",这就是一个合格的断言。
3.2 手把手示范:从模糊描述到单点Bug描述
我拿一个做搜索过滤的来说,你就明白这两者差距有多大了。
模糊版本,也是最常见的失败版本:
搜索功能有问题,搜中文不好使,帮我看看。
AI看不到你的代码上下文,也不知道"不好使"具体指什么,它大概率会给你贴一段关于编码或者正则的判断,表面看是在解决问题,实际是在答非所问。你照着它的话改,很可能越跑越偏。
用四步法第一步整理过的版本是这样的:
有一个函数 filterItems(items, keyword),它根据 keyword 过滤数组。现在传入了数组 [{ name: '苹果' }, { name: '香蕉' }] 和关键字 '苹果',期望返回包含"苹果"的那条数据,实际返回为空数组。请帮我定位问题。
这两段话之间的差别,就是"让AI猜需求"和"让AI做判断"的差别。第二段话里AI不需要猜测任何东西,它能基于这个场景写出确定的修复方案。而且这里还有一个额外的收益:当你在写"期望"和"实际"时,你很可能自己就发现了问题——比如,是不是keyword传参时被转义了?是不是filter的判断条件写反了?
3.3 最小复现:锁定问题的实用技巧
在实际操作里,我强烈建议你做一个"最小复现":不要再拿线上完整业务去让AI修代码,而是单独提炼出出问题的输入、输出和这段逻辑。这么做有几点好处:
第一,最小复现能让你把问题从复杂业务噪音里剥离开。你面对的是一个白盒测试一样的小环境,而不是一个牵一发动全身的大系统。
第二,给AI提供的可操作信息急剧增加。它对小函数的判断准确率远高于对大型模块的整体改写——这不是玄学,而是上下文越短,模型预测越准。
第三,能避免"连带伤害"。当AI只能在小范围内修改时,它很难误伤到别的逻辑。
我个人的操作方法是:一旦发现有Bug,先花三分钟在本地写一个调用该函数的测试用例,把输入输出打印出来。如果这个测试能稳定复现,我就把这个测试连同相关函数代码一起丢给AI;如果连测试都写不出来,那说明我自己对这段代码的理解还不够,这时候盲目让AI修只会加重混乱。
4. 第二步 喂对上下文:一次把三样东西递到AI嘴边
4.1 必给项一:报错原文,越原始越暴力
报错信息是你在和AI协作时最值钱的上下文。很多人懒得复制报错,喜欢用自己的话转述,比如"它说有个变量不对",这种转述会损失掉大量有用信息。报错原文里的错误类型、堆栈信息、行号、变量名,每一个字段都可能指向真正的根因。
我的习惯是原封不动地把报错粘贴过去,包括堆栈。有一次我在一个项目里碰到了一个奇怪的报错,报错信息里提示的是某个模块内部出了问题,跟我的代码完全无关。如果我只说"代码报错了",AI一定一头雾水;但我把完整堆栈一贴,AI立刻指出这是依赖版本不匹配导致的问题,并且告诉我改哪一行依赖声明。
再有就是,报错原文可以防止AI"编造修复"。如果你不给它报错原文,它为了显得自己在帮你,会编造一些它想象中的修复方案。你把报错给它,相当于给它一个锚点,它的回答会被限制在解决这个具体报错的范围内,而不是自由发挥。你要是能顺手把报错发生前后的代码路径也贴出来,那就更好了。
4.2 必给项二:带行号的最小代码块,而非整个文件
给代码的时候,很多人会陷入一个极端:要么只给一行,要么给整个文件。只给一行,AI缺乏上下文推不出逻辑;给整个文件,信息太杂,AI还被无关代码干扰。
最理想的是给一个带行号的、几十行之内的最小代码块,并且明确告诉AI这段代码在哪个文件里,大概是什么功能。为什么带行号?因为当对话进行到后半段,AI可能会在回复里提到"把X函数的xx行改掉",如果你引用的代码没有行号,你们俩会渐渐对不上"到底是哪一行",来回拉扯又开始了。
我常用的话术是这样的:
这是 utils.ts 里的 filterItems 函数,第 12-28 行。入参是 items: Array<{ name: string }>,keyword: string。即当前报错发生在第 17 行的 includes 判断处。
这样AI一眼就知道代码边界在哪里,问题发生的范围在哪里,它可以直奔主题。
4.3 必给项三:预期行为vs实际行为
报错有了,代码有了,还差最后一块拼图:你到底期望它干什么。为什么这一步重要?因为AI的所谓"修复"经常是修好了报错,但没实现你的意图。比如你要的是一个严格的精确匹配,AI却改成了宽松匹配,报错是没了,但功能变了。
"预期行为vs实际行为"这个写法,可以让AI的每一次修改都在你的目标范围内做微调,而不是跑偏到奇怪的方向。我跟AI协作时,最常用的句式就是:
期望:只返回完全匹配 keyword 的条目。实际:返回了所有包含 keyword 子串的条目,包括"苹果汁"和"苹果酱"。
这句话一说出来,AI就能立刻理解你的需求是精确匹配,而不是子串匹配。如果没有这句话,它可能改了半天都还在找Bug,因为它根本不知道你所谓的"期望结果"到底是什么。在做这一步时我还会顺带补充约束条件,比如大小写是否敏感、空字符串该怎么处理。这些细节看似不重要,但往往就是"修A坏B"的导火索。
4.4 常见翻车:一次性粘500行,AI开始胡说
我最想吐槽的操作,就是有人一股脑把几百行文件丢过去,然后说"帮我检查哪里有问题"。这么做的问题有两个:第一,模型处理超长上下文时会丢失早期信息,你去读它的回复,经常会发现它分析的重点跟你实际报错的地方完全对不上;第二,它很难在这么多代码里找到真正的Bug,因为有太多潜在的"可疑点"。
所以在实际操作中,请务必克制住"多给一点信息AI就更聪明"的错觉。AI不是人,它不会被"额外信息"感动,它只会被"相关信息"赋能。你给它300行模块的上下文,它的出错率远比给它60行核心代码要高。如果你实在不知道问题出在哪里,你可以先不贴代码,而是描述你的调用链,让AI帮你缩小范围,然后你再决定把哪部分的代码贴给它。
另外我还要提醒一句:当你给AI贴代码时,不要贴完之后加一句"应该都在这了"。你以为这句话是帮助,实际上它会加重AI的一个毛病——过度自信。AI接收完代码后,通常会直接给出结论,哪怕它没有完全读明白。你多问一句"你确定这段代码里没有别的问题吗"并不能缓解这个毛病,因为模型永远倾向于给出看起来合理的答案。真正的解法是:你提供的代码上下文足够小,小到让它连自信犯错的空间都没有。
5. 第三步 重写优先:止损比打补丁更值
5.1 为什么在错误代码上继续打补丁,越打越绝望
我先问一句:你见过Bug下面是另一层Bug吗?AI写在最外层的修复看上去是对的,但它的逻辑建立在底层某个错误的假设上。你让AI"改一下这个函数",它在错误的底层假设之上继续叠加判断,结果就是代码变得越来越绕,逻辑分支越来越多,最后谁都不知道中间发生了什么。
这就像一面墙已经歪了,你不在下面垫地基,反而在墙顶上往左糊一层、往右糊一层。从远处看,墙每糊一次貌似直了一点,但根基没动,甚至因为多了重量,歪得更快了。AI的"补丁式修复"也有同样的特点:每一次修,它都只把当前报错堵住,但代码的内部一致性在持续恶化。
这时候你需要的不是继续指挥它打补丁,而是让它把那块逻辑推倒重来。大多数人不敢这么做,是因为担心AI重写后丢功能。但我的经验是:在输出一个"你满意但不完美"的重写版本之后,你再往里面加回功能细节,这个迭代过程比在烂代码上打补丁要快得多。
5.2 三套"重写式"提示词模板,覆盖90%的Bug场景
我分享三套我反复用的重写式提示词模板,每一套对应不同的场景。
场景一:函数级重写。适合单个函数内部逻辑混乱,难以继续修补的情况。
请重新实现 filterItems 这个函数。保留入参和返回结构,不修改调用方。内部实现请彻底重写,不要沿用当前实现。附加要求:精确匹配、大小写不敏感。
关键词是"彻底重写"和"不修改调用方"。前者告诉AI不要保留旧结构,后者明确边界,防止它顺手改了其他依赖代码。
场景二:模块拆分。适合一个函数职责过多,哪个逻辑都沾一点,导致改了这边坏了那边的情况。
当前 validateAndFilter 函数既做校验又做过滤,职责混在一起。请将它拆成两个独立函数:validateInput 和 filterItems,并在调用处做相应调整。不要改变对外行为。
这个模板的关键是"不要改变对外行为",它是在给重构划定安全边界。AI一旦知道自己不能改对外行为,它就会在结构优化上花力气,而不是在语义改动上发挥。
场景三:实现方案替换。适合知道问题根源在哪,但不想和AI争论细节的情况。
这个函数的匹配逻辑基于正则表达式,导致中文搜索出错。请改用 includes + toLowerCase 的方式重新实现,并保证输出与预期一致。
这个模板直接把根因和方案都给AI,它就不需要再犯愁了。你可能觉得这种操作有点像自己写代码,但它依然能省你很多打字和调试的时间。
5.3 什么时候可以保留补丁,什么时候必须重写
我也不是每次都让AI重写,那样太奢侈了。我的判断标准很简单:如果这个补丁只涉及一个条件判断里的某个局部逻辑,改动范围在5行以内,那打补丁没问题;但如果这个函数已经经过两次以上的修复,或者AI连续两次在相近的地方改出不同的结果,那就别犹豫,直接重写。
还有一个信号也值得注意:当AI每次修复时都要求新增一个参数来"控制某个边缘情况",你就该警惕了。新增参数意味着接口变化,而接口变化会连锁影响所有调用方。这通常是它在给错误的选择打补丁,而不是在修正根本问题。
另外我还想推荐一个做法:在让AI重写之前,先用版本控制把你的当前版本保存好。这一点看起来是废话,但在实际操作里,很多人都忘了给Git提交一个检查点。AI重写完之后如果效果更差,你要能一键回到旧版本。不然你就只能眼睁睁看着AI把唯一能跑的版本改坏,又没法撤销,那种绝望感我太熟悉了。
6. 第四步 闭环验证:别让"AI说修好了"成为你的验收单
6.1 三个必跑的最低验证清单
AI说"我已经修复了这个问题,请验证"的时候,绝大多数人会犯一个错误:试一下发现没报错,就默认修复成功。这个习惯极其危险,因为你只验证了"有Bug的那条路径",完全没有验证"没Bug的路径是否被改坏"。
我给自己定了一个最低验证清单,每次修复完都必须过一遍:
- 原Bug路径验证:重新跑一次当初复现问题的操作,确认它确实被修好了。
- 相邻功能验证:这个函数周边的功能点自己手动过一遍,比如入参为空、传特殊字符、传超长字符串等。
- 旧功能回归验证:想想这个函数之前被依赖方用到的地方,挨个测试一遍。
你可能觉得这三步很烦,但请相信我,这三步加起来的时间,远小于你在AI那里反复报Bug、被它来回复改所消耗的时间。前三步法帮你减少的是"来回拉扯"的轮次,第四步法帮你减少的是"拉扯完了才发现还没修好"的绝望。
6.2 让AI主动交代副作用与影响范围
在让AI改代码之前,我建议你加上一句话:"请说明这次修改会影响哪些调用方,有没有可能产生副作用。"这句话是我偶然试出来的,效果出奇地好。你会发现,一旦你要求AI交代影响范围,它的回答方式会发生明显变化:从直接给代码,变成先分析依赖,再谨慎地说明改动边界。
这背后的原因很简单:当你要求它列出影响范围时,它会更多地考虑调用关系,而不仅仅是眼前这一小段代码。你可以根据它列出的范围来做回归测试,不用自己瞎猜。
如果AI回答"这个改动不影响其他模块,只有这个函数自己",那说明改动确实很局部。如果它列出了一大堆调用方,你就得额外小心,验证范围要扩大到这些调用方场景。更进一步,你也可以追问一句"有没有更安全的改法,尽量避免改动对外行为",让AI在选择方案时多往兼容方向想。
6.3 用版本控制给每次修复留退路
第四步里最容易被忽视的一个环节,就是用版本控制记录每一次AI修复前后的状态。我见过太多开发者从头到尾只用一个分支,让AI改完代码后直接覆盖,等想回到上一版时发现已经回不去了。最后只能对着AI说"你能不能把我之前那个版本弄回来",这又是新一轮拉扯。
正确的做法特别简单:在开始修复之前,先把当前能跑的版本提交一次,写好commit信息,比如"fix: 搜索功能中文匹配问题 - 修改前备份"。然后把AI的修改应用上去,如果最终验证不通过,你一句git revert就完事了。这个过程在命令行里只需要五秒钟,但它能让你在心态上彻底解放——你再也不怕AI把代码改坏了,因为你知道自己永远有退路。
尤其当你面对一种"越修越乱"的状态时,最有效的止损方式不是你继续逼问AI,而是回到上一个能跑的版本,重新用四步法走一遍。很多人不敢这样止损,总觉得"都改了这么多轮了,继续修也许就好了",结果越陷越深。请记住:时间不是沉没成本,及时回滚重新开始,往往是最省时间的路径。
6.4 追加"最后一遍"回归询问
最后一招,是我自己每次修复结束后都会问的一句话:
请再检查一遍你的修改,有没有可能在某个边界条件下产生新异常?如果有,请一并补充处理。
这句话的作用不是为了得到一个完美的回答,而是给AI一个机会,让它意识到自己可能需要补充防御性代码。实测下来,这一问有几次真的帮我发现了AI自己埋下的新隐患,比如对空数组没有判空处理、对特殊字符没有转义。你要知道,AI写完的代码默认只考虑"正常路径",边界路径它往往会忽略。你主动追问,等于帮它补齐了这部分思考。
7. 实测复盘:一个搜索过滤Bug从"越修越崩"到"一次过"的完整对话
7.1 原始场景与最初的黑历史对话
为了让你更直观地看到四步法的威力,我拿一个模拟项目X里的真实场景来复盘。当时我有一个搜索过滤功能,用于在前端页面按名称筛选商品列表。核心代码长这样:
function filterItems(items, keyword) { return items.filter((item) => { return item.name.toLowerCase().includes(keyword.toLowerCase()); }); }这个函数看起来很正常,但某天测试人员发现,输入"苹果"能搜出结果,输入"APPLE"却搜不出英文商品。我第一反应是编码问题,于是有了下面这段黑历史对话。
我发消息:搜索的拼音和英文搜不出来,应该是编码问题,帮我修一下。
AI回复:可能是大小写问题,已改为统一转小写比较。你看我现在这个写法是兼容的。
然后它真的贴了一段看起来没问题的代码,我再跑一遍,英文确实能搜出来了,但中文全没了。我把问题丢回:中文坏了。
AI又回:可能是正则匹配到了中文标点,已调整。
就这样来来回回,半小时过去,代码变成了一个满是指南针注释、兼容各种奇怪情况的函数,最终我决定全部推翻,用四步法来重新对话。
7.2 盲目修复的信息缺陷复盘
复盘这一段黑历史,问题在于我的第一句话就把AI引向了歧路。我说"可能是编码问题",这是一个错误的甚至不存在的猜测。AI听到"编码问题"后,就会在一个错误的方向上寻找答案。它给出的修复只能越走越偏。
真正的问题原因是什么?后来我用四步法做了一次最小复现,传入英文关键字"APPLE"后,报错显示找不到结果。我又用console打印了item.name.toLowerCase()的值,发现某条数据的name字段里包含的是"Apple iPhone",而我的测试数据里根本没有"APPLE"这个全大写单词。也就是说,预期行为本来就是精确匹配,而不是子串匹配,这根本不是Bug,而是需求描述不清晰。
这个案例说明一个很扎心的问题:很多所谓"AI修不好的Bug",其实是提出需求的人没想清楚预期行为。四步法里的锁定问题这一步,迫使你先把需求想明白,这个价值比省下的时间更大。
7.3 低头用四步法之后的重来
我重置对话后,用四步法重新提交了一遍问题。这是我在新对话里写下的描述:
函数 filterItems 在第 12-28 行。当前行为是按子串过滤:items.filter(item => item.name.toLowerCase().includes(keyword.toLowerCase()))。输入 items 是商品列表,keyword 是搜索词。期望行为:当 keyword 是"苹果"时,只返回名称中包含"苹果"的商品;当 keyword 是"APPLE"时,只返回名称中包含"APPLE"的商品。实际存在的问题:搜索"苹果"时返回了"苹果汁"和"苹果酱",本应只返回纯"苹果"的条目。
我把报错原文和代码块都附上后,AI回复的第一句就让我心里踏实了:"明白了,你要的是精确匹配,而当前实现是子串匹配。有两种方案:一是改成一个更精确的判断函数,二是保留子串匹配但加字段区分。考虑到业务语义,我建议你把商品名称拆成别名数组,搜索时同时匹配名称和别名。"
这个建议虽然没有直接给代码,但它指出了一个我一开始完全没想到的方案。我采纳之后,AI在十分钟内给出了新版代码,并主动标注了它影响了哪些调用方。我按它的说明跑了一遍验证清单,一次通过。
7.4 重新走的这段路带来的改变
后来我又用同样思路处理过几次别的Bug,最大的改变不是代码质量提升多少,而是我的心态变了:从"AI怎么又错了"变成"我该怎么把问题讲得更清楚"。你一旦发现,当你把上下文喂到位之后,AI的准确率真的有质的提升,你对它的耐心也会大幅增加。而且,通过四步法我经常能反向发现业务逻辑里的模糊地带,这是以前靠自己手写代码时很难注意到的。
8. 常见问题速查与独家避坑心得
8.1 那个越修越心虚的瞬间,该怎么办
如果你在修改过程中发现AI的回答越来越空洞,或者它开始反复重复刚才说过的内容,那说明当前对话的上下文已经污染到无法挽救的程度。这时候最正确的操作不是继续追问,而是开启一个新对话,重新把问题按四步法描述一遍。
为什么新对话有效?因为每开一个新对话,AI对你的问题描述就拥有完整、干净的注意力。它不是变聪明了,而是不再被之前那些错误猜测所干扰。我把这个操作叫"重置对话止损法",它解决的是"对话上下文污染"这个很多人在Vibe Coding时踩最深的大坑。
止损的另一个信号是:当你发现自己为了说明一个Bug,不得不解释前面三次修改各自干了什么的时候,你就该停下。这种解释会让AI陷入"前一次修改是错的"的暗示中,它往往会试图回滚并补偿,而不是分析真正的根因。
8.2 速查表:从症状到操作
我整理了一张速查表,你也可以把它存下来,遇到类似情况直接对号入座。
| 症状 | 常见根因 | 按四步法的应对 |
|---|---|---|
| AI越修越崩 | 对话上下文污染 | 开新对话,按锁定问题重新描述 |
| 修A坏B | 调用方未考虑周全 | 让AI标注影响范围,做回归验证 |
| AI答非所问 | 给的上下文太杂 | 用最小复现,只保留相关代码 |
| AI始终改不对 | 预期行为没定义 | 明确输入、输出、期望结果 |
| 修复后代码难维护 | 打了太多补丁 | 推倒重写局部函数 |
| 同一Bug反复出现 | 没有做闭环验证 | 跑一遍完整验证清单再收工 |
8.3 我自己最常用的三个提示词小习惯
最后分享三个我觉得最实用的小习惯,也不算多高深,就是几个让我少走弯路的提示词技巧。
第一个习惯是在描述Bug后加一句"请先分析再给代码"。这句话能防止AI在没搞明白问题时就直接贴代码。当它先分析时,你能看到它的思路是否正确,一旦偏了可以立刻纠正,避免它闷头写完一大段才发现方向错了。
第二个习惯是要求AI在回复末尾列出"我改动的文件和函数"。这帮我养成了复核AI工作范围的习惯。很多时候我们被AI的回复带着走,忘了检查它到底碰了哪些不该碰的代码。它主动列出来,你心里就有数了。
第三个习惯是修复结束后让AI写一段"这段逻辑现在是怎么工作的"说明。这件事的好处有两层:一是促使AI用清晰的逻辑组织新代码;二是给你留下一份解释,下次你再看这段代码时,不用靠回忆去猜。每次做到这一步,我都会发现自己的项目可维护性上升了一个档次。
我自己用Vibe Coding这半年最大的感受是:AI不是替你写代码,而是你的结对编程搭子。你用粗话跟搭子沟通,搭子就还你一堆粗活;你用清晰的结构化的方式沟通,它回报你高质量的实现。四步法听起来可能有点麻烦,但只要你坚持用两次,你就再也不想回到那种修一个Bug、崩两个功能的原状态里了。