1. 先别急着读代码,先分清楚黑盒到底黑在哪几层
1.1 vibe coding 是怎么把代码变成黑盒的
vibe coding 这词最近在开发圈里被提到得越来越频繁。我第一次用某个 AI 编程助手写一个数据处理工具时,体验确实惊艳:我把需求用几句话描述清楚,它噼里啪啦给我生成一整段可以跑的代码,我复制运行,结果正确。那一刻你会产生一种错觉——写代码的门槛已经不存在了,我只负责告诉机器做什么就行。但两周之后,这个"工具"出了点问题,我需要修一个边界条件下的 bug。我打开那段曾经让我赞叹的代码,盯着长长的函数看了十分钟,脑子里只有一个问题:这东西到底是怎么写的?我当时甚至不敢动它,生怕哪一行是我没理解的隐藏逻辑,一改就崩。
这就是 vibe coding 后的黑盒问题。所谓"vibe coding",简单讲就是开发者用自然语言描述意图,让 AI 大规模生成代码,开发者主要负责验收、微调、再生成。它把我们从打字员变成了审稿人,节奏看起来快了,但有一个隐患被整个流程掩盖了:AI 写代码时,你并没有跟着它的思考过程走。你跳过了所有语法细节、框架约定、边界处理,这些细节并没有消失,它们只是变成了你仓库里的一段段代码。你跳过它们的时候,顺带把"理解它们"这件事也跳过了,于是代码对你来说就成了一个黑色箱子。
1.2 黑盒不只是"看不懂",而是四层风险叠加
我踩过几次坑之后,发现代码黑盒不是一种模糊的感觉,而是可以拆成四种具体的风险。
第一是逻辑黑盒。你看到函数名和返回值,但不知道内部算法是怎么设计出来的,很多分支是 AI 根据它的经验脑补的,它的判断依据你完全不可见。第二是依赖黑盒。AI 写出来的代码通常会隐式依赖某些库、某些全局状态、某些外部服务,它不会主动告诉你用了哪个版本的库、这个接口在什么情况下会抛异常。第三是状态黑盒。特别是涉及文件、缓存、数据库的代码,AI 可能生成一段看起来没问题的读写逻辑,但数据到底在什么时候写入、什么时候失效、并发下会不会互相覆盖,都是隐藏状态。第四是性能黑盒。代码跑起来可能很慢,但慢点在哪一条路径上,你不跑压力测试根本无从判断。
这四层风险叠加在一起,导致一个很尴尬的局面:代码能跑的时候,你觉得自己很行;代码一崩,你发现自己连从哪里下手都不知道。这也是我写这篇文章的原因——我想分享一套我自己验证过的方法,帮大家把 AI 生成的黑盒代码重新变成可控的、可解释的、可维护的代码。
2. 打开黑盒之前,先把测试和验收标准立起来
2.1 需求边界不清,AI 才会自由发挥
拆黑盒不是从"读代码"开始的,而是从"重新读需求"开始的。我见过不少刚开始用 AI 写代码的同学,正好在 prompt 里写"帮我实现一个用户注册功能",AI 就啪啪啪生成了包括验证码、邮箱确认、密码找回在内的一整套东西。当时看着很惊喜,后来维护起来就是灾难。因为你没说要验证码,AI 按照"一个完整的注册功能"的默认模板给你补了一堆你没要求的逻辑,这些逻辑以后可能触发安全问题,甚至和你们现有的用户体系冲突。
根子在于需求描述得太模糊。给 AI 的输入里没有任何验收标准、没有边界条件、没有"不要做什么",它只能凭概率猜测你要什么。所以我现在会强制自己在让 AI 写代码之前,先写下几件事:这个功能的输入是什么、输出是什么、哪些边界情况必须要处理、哪些功能明确不做。不需要写成正式文档,几条要点、几个输入输出的例子都行。哪怕只有五行话,AI 的自由发挥空间也会小很多,黑盒的范围从一开始就被收紧了。
2.2 没有测试兜底,AI 代码就是定时炸弹
第二件必须提前做的事,是测试。我有个很深的体会:AI 生成的代码,最怕的不是跑不出来,而是跑出来结果"碰巧对",但你在回归的时候完全没有护网。如果一段代码没有测试,当它变成黑盒之后,你连"它之前是好的"这个结论都没有,改起来每一步都是摸着石头过河。
所以我的做法是,让 AI 写完代码之后,第一件事不是拿真数据去跑,而是先为它写一组测试。这里有个小技巧:我会把需求里那些输入输出的例子直接变成单测用例,再补两个边界用例,比如空输入、超大输入、非法字符、时间跨时区之类的。把这些测试在 AI 生成的代码上先跑一遍,如果挂了,就让 AI 看着测试输出继续改。这个过程还有一个意想不到的好处:测试其实是在逼你去想清楚"代码应该有什么行为",只要测试写出来了,你就已经对黑盒的"外部行为"有了把握,后面拆代码时心里有底。
注意:测试写得好不好的判断标准不是覆盖率,而是它能不能区分"代码行为符合预期"和"代码行为碰巧正确"。黑盒代码尤其要重点测非法输入和极端边界,因为 AI 最喜欢在这些地方产生看似合理、实则有问题的代码。
3. 拆黑盒的核心方法:从行为探测到代码考古
3.1 第一板斧:先画调用边界,不急着钻进细节
真到拆黑盒代码的时候,我强烈建议不要一个人闷头从第一行读到最后一行。那样效率极低,而且很容易看着看着被某个 AI 生成的小分支带走,绕了一圈回来忘记主线。我自己的顺序是:先站在远处看结构,再做行为探测,最后才钻进代码细节。
"站在远处看结构"具体怎么操作?第一步,找出这段代码的入口和出口。入口就是外部怎么调用它,出口就是它返回什么、写了什么副作用。如果是一段服务端接口代码,入口是 HTTP 路由的那几行,出口是响应体;如果是一个处理函数,入口是参数,出口是返回值或抛出的异常。第二步,看它的调用链。用 IDE 的调用关系图或者直接搜引用,确认它调用了哪些模块、哪些库、哪些外部服务。第三步,把这个结构画出来——画成简单的伪代码流程图或者依赖清单都可以。我通常只是用注释把这些入口、出口、关键调用写在文件顶部,相当于给自己做一个快速导览。
这一步的意义在于:你不需要理解每一行,就能先知道这个黑盒"和外界有哪些接口"。后面一旦出问题,你至少能判断问题出在接口的哪一侧,排查范围瞬间缩小。
3.2 第二板斧:按"签名、主路径、边界分支"三层读
结构摸清楚之后,才轮到逐行读代码。但我读 AI 代码时也不是平均用力,通常分三个层次。第一层只看函数签名和类型标注。这一步很快,但信息量巨大:参数类型、返回值类型、有没有抛出异常,能把黑盒的很多属性直接暴露出来。比如一个函数接受两个时间字符串、返回一个整数,你立刻能猜它是"计算两个时间差",那 AI 大概写的是什么就八九不离十了。
第二层是读主路径。把 if/else 里的主要分支找出来,不关心异常处理,先把"正常情况下这个函数怎么执行"跑一遍。大部分 AI 生成的代码,主路径通常写得比较直白,无非是取数据、处理、返回,这一层读下来你基本就掌握了核心逻辑。第三层才是边界分支:空值判断、错误处理、超时重试、资源释放,这些通常是 AI 最爱犯错的地方,也是真正决定代码能不能上生产的地方。我遇到过的最典型问题,就是 AI 生成的代码在主路径上毫无问题,但某个分支里 catch 住了一个异常之后默默吞掉,导致出问题时不报错、也不返回错误值,线上一切"正常",数据却悄悄写错了。
读的时候最好同步写注释。不用写多,在每个关键分支上面写一句话:这里在做什么、为什么这么做。如果发现自己完全写不出"为什么",那个地方往往就是 AI 自己脑补的逻辑,需要重点标记,后面用实验或者替换的方式处理。
3.3 第三板斧:用最小实验做行为探测,别靠猜
有些时候,光读代码是读不出来的。特别是 AI 生成的逻辑特别绕的时候,靠人脑去静态模拟数据流向,既慢又容易错。这个时候我建议直接做行为探测:写一小段实验代码,给这个黑盒输入特定的数据,然后观察它的输出和副作用。
具体做法我很常用的是三步。第一步,选三组输入:一组是最普通的正常输入,一组是边界附近的输入,一组是明显非法的输入。第二步,在这段代码周围加打印或者用调试器单步跟踪,记录每组输入对应的输出、中间变量、局部状态。第三步,把观察到的行为和你的预期对比,差异点就是你需要重点研究的区域。整个过程有点像拆炸弹前先拿探针碰一碰,成本很低,但能快速暴露出黑盒的"脾气"。
这里有一个重要的纪律:做行为探测之前,一定先把代码提交到本地版本库里,或者至少打一个快照。然后,实验代码要最小化——只加打印、只加断言,不顺手优化、不顺手重构。我见过好几个同学在调试 AI 代码的时候,调试到一半顺手把变量名改了、把某个分支简化了,结果 bug 没找到,还引入了新问题,最后连"原来是啥样"都搞不清了。探测是观察,不是修改,这两件事一定要分清楚。
3.4 第四板斧:让 AI 当翻译,但默认它也会骗你
读 AI 代码其实还有一个天然优势:你身边有写这段代码的"作者",也就是那个大模型本身。你完全可以直接问它:"这段代码是干什么的?""这里为什么要这样处理?""这个分支在什么情况下会走?"它给出的解释通常比你自己硬读要快得多,尤其是它自己生成的代码,它对自己意图的"记忆"往往还在上下文里。
但这里必须要留个心眼。大模型的解释是根据概率生成的,它可能知道自己的代码,也可能一本正经地编出一个合理但完全对不上的解释。我遇到过不止一次:AI 给我解释了一个分支的意思,我信了,后来一测才发现它的解释是错的。所以,AI 的解释只能当作"旅游指南",不能当作"官方地图"。怎么验证?很简单,每拿到它的一句解释,就把它转成一个输入输出的预测,然后实际跑一次。比如它说"这个分支处理空列表的情况",你就给它传一个空列表,看它是不是真的走了那个分支、返回了它说会返回的东西。验证通过的解释才是真的。
这一步还有一个变体:让 AI 帮你生成代码的文档。你把它生成的代码丢给它,告诉它"用 README 的格式给我讲清楚这个模块的设计、每个函数的职责、使用注意点",它的输出通常有一定的可用性,但同样需要人工过一遍。我的经验是,这类文档当草稿起点很好,直接发布还是算了。
4. 按风险地图做优先治理,别想把黑盒全部拆开
4.1 先分两类:必须懂的代码和可以保持陌生的代码
很多人面对 AI 生成的大堆黑盒代码,第一反应是"我要把它全部搞懂",这个想法我其实不建议。项目里不是每段代码都平等,有的代码生死攸关,有的代码就算完全不理解,对项目影响也不大。你要是平均用力去拆所有黑盒,大概率会把自己累死,而且进展缓慢。
我习惯把 AI 代码分成三类。第一类是核心路径代码,比如涉及账号、支付、数据落库、主流程逻辑,这种代码必须被完全理解,否则风险不可接受。第二类是外围胶水代码,比如格式化、拼接、转换、简单工具函数,这类代码你可以只理解它的接口,不深入内部,只要测试够,就不急着拆。第三类是 AI 自由发挥的冗余代码——就是它自己脑补出来的那些"完整功能",这类代码的优先级反而是尽快删除,因为它们不但增加维护负担,还可能引入安全风险。
分类的关键是风险,不是代码量。所以我在项目里会用非常简单的风险评分:这段代码出错后,会导致资金损失、数据写坏、系统崩溃还是单纯界面显示异常?严重程度不同,投入读代码的精力也不同。很多项目其实只需要把其中 20% 的 AI 代码彻底拆明白,另外 80% 在测试保护下保持"灰盒"状态就行。
4.2 外部依赖、隐式状态、资源管理是优先检查点
拆核心路径黑盒时,有几个位置我会优先检查,因为它们最容易藏雷。第一是外部依赖调用。AI 生成的代码经常默认第三方库很友好,对超时、重试、异常类型处理得都很简单,甚至干脆不处理。比如有一次 AI 帮我写了一个外部 API 的封装,它没设置超时时间,生产环境对方服务慢了几秒,整个请求线程全部挂住,排查了整整一下午。这种问题你读主路径是读不出来的,必须专门看每个外部调用点周围有没有超时、重试、熔断、降级。
第二是隐式状态。单例对象、全局变量、进程内缓存、环境变量,这些状态藏在代码里,AI 不会主动告诉你。我遇到过一个 AI 写的缓存模块,它用了模块级的字典来缓存结果,却没有任何清理机制,数据量一大就把内存撑爆了。这类问题的特点是:单次调用看不出毛病,长时间运行才暴露。排查手段是全局搜一下模块级变量的赋值位置,以及所有静态变量、单例、缓存的创建和清理逻辑。
第三是资源管理。打开的文件、网络连接、数据库会话、临时文件,AI 写代码时很容易忘了关闭。查的方式也简单,找到所有新建资源的动作,确认它们在所有路径上都有对应的释放动作。顺手再查一遍异常分支——AI 很擅长在正常路径上正确释放,但在异常路径上却把资源释放忘了。
4.3 性能黑盒也要测:压出来的慢点比猜的准
另一个容易被忽视的检查点是性能。AI 生成代码的平均质量在功能层面已经很高,但在性能层面经常很离谱。我见过它用嵌套循环做高复杂度的事情,也见过它在 for 循环里不断查数据库,还有过它生成一个正则表达式,处理几百个字符就要好几秒。这些慢点靠读代码是能发现的,但 AI 代码本来就绕,纯靠静态分析效率太低,不如直接跑性能测试。
实操做法是先定一个可接受的时间阈值:这个接口多少比例的请求应该在多少毫秒内返回,导出功能最多能接受多少秒。然后用基准数据跑一轮,先用 profiling 工具看热点,统计每个函数消耗的时间占比,再看热点函数的源码。只要 profiling 出来的热点和分析的源码能对得上,这个黑盒的性能部分基本上就拆得差不多了。如果热点集中在某个 AI 生成的算法上,处理方法后面会讲到——通常是替换成自己清楚逻辑的实现,而不是去优化一段看不懂的代码。
5. 黑盒出 bug 时,怎么排查才不慌
5.1 第一原则:先复现,不要上来就猜
黑盒代码出 bug,最大的诱惑是"直接看着代码猜原因"。我之前就是这样,看到报错栈在某一行,就盯着那一行推理,推理十分钟,改了一行,重新跑,报错换了地方。为什么?因为 AI 生成的代码常常把真正的根因埋在前面好几层的地方,表面报错的地方只是"受害者"。
正确的做法是先复现。不管 bug 看起来多诡异,先拿到触发它的一组可靠输入,最好是最小复现样例。复现不了就疯狂补充日志,把输入输出、中间状态、环境信息全部打出来,直到可以在测试环境稳定地复现为止。为什么这么看重复现?因为只有稳定复现,你才能对黑盒做受控实验;有了受控实验,你才能验证你的每次猜测。对黑盒而言,代码读不懂不致命,猜了没法验证才致命。
如果 bug 是在很复杂的业务场景里才出现,复现成本高,那就在生产环境增强日志和链路追踪,把请求的关键上下文串起来。等日志攒够了,再回到测试环境用类似数据去模拟。我个人的经验是,黑盒 bug 花在复现上的时间占比应该至少一半,复现之后,真正的修复时间反而很短。
5.2 用二分法在代码丛林里定位坏区段
稳定复现之后,下一个难题是"代码太多,不知道坏在哪一段"。AI 生成的函数经常一个函数几百行,你不能逐行去审,这时候我会用二分定位法。
做法是这样的:沿着函数的主路径,在差不多中间的位置插入一个打印点或者断言,检查中间状态是否符合预期。如果中间状态是对的,说明问题在后面的半段;如果中间状态已经错了,说明问题在前面的半段。然后继续在出问题的那半段中间再插一个点,如此往复,每次把排查范围砍半。对几百行的函数来说,插五六次点就能把问题定位到几行十几行的小范围里。
这个方法看着简单,但我特别想提醒两个细节。第一,插入的打印点必须能反映出"对还是错",不要只打印原始变量,要在打印的同时做出判断(比如和预期值比较),否则你看到的还是一堆看不出对错的数据。第二,二分定位建立在主路径的假设上,如果 bug 只是在某个冷门分支里,你插的点可能一次都没走到,那就改成在分支入口附近插点,判断是否进入了不该进入的分支。
5.3 AI 的典型错误模式,按图索骥
和人类程序员比起来,AI 写代码的错误模式其实相当集中。就算你没完全读懂黑盒代码,记住下面几种典型错误,排查时按顺序检查,经常能直接命中。
第一批:错误吞掉和错误忽略。AI 写异常处理时,很喜欢在捕获之后做个空操作,或者干脆把异常记录下来就继续。这类 bug 的特点是没有报错、但输出不符合预期。搜索代码里的所有异常捕获语句,看每个捕获分支有没有真正处理。
第二批:边界差一和空值。循环条件里多一个等号少一个等号、数组下标从 0 还是从 1 开始、空集合会导致什么结果,这些是 AI 和人类程序员一样容易错的地方。第三批:状态污染和并发问题。模块级变量、共享对象、静态缓存,AI 在没有明确并发意识的情况下,写出来的代码默认"一次只有一个用户跑"。一旦并发起来,就是各种互相覆盖。第四批:时间、时区、字符编码和本地化。AI 对时区转换尤其头疼,经常把本地时间当协调世界时,或者反过来。第五批:多余代码。AI 经常在一个函数里同时实现了两个方案,或者留着一大段没被调用的"备选"逻辑,这些代码不报错,但让人困惑,而且可能在你做替换时误伤。
有了这张清单,排查黑盒 bug 就不是靠运气了。你只需要按清单过一遍,命中率非常可观。说实话,我现在排查 AI 代码的速度,已经比排查其他人写的代码还快了,就是因为它的错误模式太有规律。
6. 治理黑盒的三个策略:包裹、替换、重写
6.1 包裹策略:不明白核心逻辑,就先在外面加防线
拆黑盒不是唯一出路,有时候你不需要完全理解一段代码,也能让它变得安全可控。我用的第一个策略是包裹,就是在黑盒代码外面加一层"防腐层"。
举个例子:AI 写了一个接口,负责接收用户上传然后做解析。我暂时没时间把它的解析逻辑全部搞明白,但它有两个我很确定的需求:输入内容大小不能超过一定限制,解析失败必须返回明确错误。那我就在调用这个黑盒函数之前写一段校验:检查大小、检查类型、捕获异常并映射成标准错误。这样,哪怕黑盒内部有一些我没发现的坑,也会被外层防线挡住,不会直接炸到上层调用方。
包裹策略特别适合这么几种场景:黑盒代码已经稳定运行很久、暂时不想动它;黑盒代码涉及第三方接口和协议、重写成本高;团队马上要发版本、没有时间深挖所有细节。包裹不能降低内部出错的概率,但它能把出错的影响范围圈住,给你争取到后续逐层治理的时间。我在做过的项目里,很多 AI 生成的代码最终都是带着一层校验包裹先上线的,等后续有完整测试保护了,才拆掉。
6.2 替换策略:一层一层换掉搞不懂的代码
包裹只是防守,真正要把黑盒变成白盒,还是得靠替换。但替换我强烈建议"一层一层来",不要一口吃成胖子。把一个大黑盒拆成很多小的接口层,每次只替换其中一个层,替换完立刻跑完整测试,确认没有变化,再替换下一层。
比如有一段 AI 生成的数据处理流程,我把它拆成读入、清洗、转换、输出四个接口层。如果清洗层的逻辑我看不懂,我只重写清洗层一个函数,其它三层保持原样。重写的时候可以参照 AI 的输入输出行为:先用之前行为探测得到的测试样本把这些行为固化成用例,再写自己的实现。只要测试全部通过,我就能确信新代码和旧代码在行为上等价,风险降到最低。
替换成功的一个标志是:新代码删掉之后,你自己能清楚地解释它为什么这样写,每个分支都有说法。如果替换之后你发现新代码又变成了一个新黑盒——只是这次是"你自己写的黑盒",那说明替换的粒度太大了,应该再拆小一层。我见过一些人把 AI 的整段代码删掉重写,结果写出来的东西别人也看不懂,那其实毫无意义。
6.3 重写策略:最后的选择,但只重写最关键的那一小块
有些 AI 代码不是"看不懂",而是"看懂之后觉得不该存在"。比如它的设计思路根本就是错的,把整个流程绕成了一条奇怪的路,你怎么修都别扭。这时候才考虑重写。
但重写有一个大原则:只重写不得不重写的那一小块,而不是重写整段功能。我会先明确"新增了什么价值":这段 AI 代码重写之后,比原来强在哪些方面?如果只是"我写的我放心",那心理安慰价值不等于工程价值,应该放弃。真正值得重写的场景大概就这么几个:算法性能差到无法接受;AI 的设计和现有系统架构冲突太深,留它只会持续累积技术债;代码里藏了安全漏洞,修修补补不如换掉。
重写的时候最优的做法是复用你能看懂的部分。AI 生成的代码里也常有可用的数据结构定义、常量、工具函数,这些不需要丢。我会把旧代码当成一个"不完整的需求文档",把可用的骨架留下,把不可用的肉换掉,重写比例通常控制在三成以内。全量重写一个黑盒,失败的例子我见得太多了,务必克制。
7. 让黑盒不再出现的工程习惯
7.1 把"可解释"写进 AI 代码的验收标准
前面说的都是事后治理,但最好的策略是让 AI 代码从一开始就别变成黑盒。我在团队里推过一条规则:AI 生成的代码,合入主分支之前必须通过一次"可解释性检查"。这个检查不问代码能不能跑、测试通没通,只问三个问题:你能不能用一句话说清这段代码解决什么问题?你能不能在关键分支上解释清楚为什么这样处理?这段代码有没有任何你无法解释的副作用?三个问题里有任何一个回答不上来,就不能合入。
和代码评审放一起看,这个检查给 AI 开发流程加了一道保险。因为它迫使开发者回到代码里,而不是停留在"AI 写了所以我觉得没问题"的状态。有一次一个同事拿着 AI 生成的模块来找我评审,第一个问题就答不上来,我俩当场打开代码一起读,结果发现 AI 不但实现了他要的需求,还偷偷加了一段"友好的重试机制",会在失败时自动重试,完全没有考虑幂等性。如果没做这个检查就合入,这个重试机制迟早要闯祸。可解释性检查不需要花很长时间,但它逼着你把黑盒至少拆开一半。
7.2 让 AI 把注释、文档和决策记录一起写出来
AI 生成代码本身很快,但代码的黑盒感一半来自"没有文档"。幸运的是,我们完全可以让 AI 连文档一起生成。我现在会在让 AI 写代码的需求描述里就附上文档要求:每个文件加文件头注释,说明用途;函数加说明注释,说明参数、返回值、异常;模块级别写一段简短设计说明。
更关键的是让 AI 写"为什么",不写"是什么"。比如我在让 AI 重构一段逻辑时,会要求它在注释里说明"这里为什么用缓存""这里为什么用异步"这类决策。这些决策记录就是后期给黑盒接线的引线。AI 输出之后,我做的不是照单全收,而是让它给每一条"为什么"配一个反例:如果不用缓存会怎样,如果同步会怎样。配不上反例的解释,就是可疑的脑补。
团队里我还建议大家维护一份简短的"AI 使用决策记录",把这次为什么采用 AI 生成的方案、风险点、后续想替换的部分写下来。不用长,几十个字就有价值。等三个月后你回来看这段代码,这些记录比 AI 当时生成的十页文档有用得多。
7.3 定期开"AI 代码说明会",讲不清就重写
最后一个习惯比较"重",但效果很好:定期安排一次小范围的技术分享,每个人都挑一段自己最近用 AI 写的代码,讲给其他人听。讲清楚三件事:这段代码做了什么、为什么这么做、你踩了什么坑。讲得出来,说明你至少拆过了;讲不出来,台下的同事会帮你一起拆。
这个分享会最大的价值在于,它把拆黑盒从"开发者一个人的事"变成了团队共同的事。你不敢全部搞懂的代码,别人可能有过类似的经验;你完全没注意到的 AI 脑补逻辑,别人可能一眼就能看出来。而且分享会本身是一个很好的压力机制——没有人愿意在全组面前承认"这段代码我不知道为什么能跑"。我见过好几个同事,为了准备分享,把那部分 AI 代码从头到尾彻底读了一遍,然后分享会上讲得神采飞扬,从那之后对这段代码的掌控力明显上了一个台阶。
长期来看,AI 工具会越来越强,vibe coding 的工作流也会越来越普遍,但"开发者需要对代码负责"这件事不会变。代码黑盒能不能被接受,取决于你能不能回答那些最基础的问题:这段代码做什么?它怎么做到的?如果它错了,怎么发现?如果它能稳定运行,它的边界在哪里?这些问题没有 AI 能替程序员回答,因为使用者是你,负责的也是你。
8. 常见问题速查表
| 现象 | 可能原因 | 排查动作 | 预防手段 |
|---|---|---|---|
| 代码偶尔正常工作,偶尔返回错误结果 | AI 生成了隐式状态或隐式缓存,时序影响结果 | 全局搜索模块级变量、缓存清理逻辑 | 让 AI 明确设计状态生命周期 |
| 线上没有报错,但数据悄悄写错 | 异常被吞掉,错误路径没有返回值 | 检查所有捕获异常的目录分支 | 测试非法输入场景 |
| 接口整体偏慢 | AI 写了低效算法或循环内调用外部服务 | 用性能分析工具找出热点函数 | 核心路径读代码并做性能测试 |
| 改动一行代码后出现完全无关的 bug | AI 代码存在重复或冗余逻辑,改了一处漏了一处 | 全仓搜索同一逻辑的重复实现 | 可解释性检查时清理冗余 |
| 函数几十上百行,没人敢接手 | AI 生成长函数,结构混乱 | 按签名、主路径、边界分支分解重构 | 需求描述里约束函数长度和模块化 |
| 传入边界条件后直接崩溃 | AI 忽视了边界输入 | 行为探测三组输入并对比预期 | 需求描述时明确边界条件 |
最后再分享一个我自己的体会。vibe coding 真正舒服的时刻,是我把 AI 生成的代码管理得服服帖帖的时候,而不是它一口气给我生成三千行的时候。写代码的快感可以来自"AI 帮我写了很多",但长期的安心感一定来自"我理解了这些代码在干什么"。我会建议每个刚开始用 AI 写代码的朋友,给自己立一条规矩:每次合入 AI 代码前,至少能答出"这段代码里最危险的一个点是什么"。答不上来,就别合。别让 vibe coding 最终变成 vibe debugging 就好。