ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

AI代码如何不成技术债?从Code Review到测试用例的实践

2026/9/15 4:32:57 拓冰建站 浏览量
AI代码如何不成技术债?从Code Review到测试用例的实践 最近团队里在推进 AI 辅助编程效率提升确实肉眼可见以前要写两天的模块现在半天就能跑通。但真正让我后背发凉的不是 AI 写得慢而是 AI 写得“太快”。代码仓库里开始出现大量风格陌生、逻辑绕弯、完全看不懂为什么要这么写的“AI 代码”。我随手点开几个 diff心里咯噔一下——这些代码如果今天没人管半年后就是一笔砸在团队头上的技术债而且是最难还的那种。这个事儿不是个例。朋友圈里天天有人晒 AI 写代码的截图但真正在做的老手都清楚AI 生成代码的质量永远存在一个“看着对实则没法维护”的灰色地带。这篇文章不聊那些虚的就基于我最近大半年在真实项目里用 AI 写代码、改代码、做 Code Review 的经历把“别让 AI 代码变成技术债”这件事拆开揉碎说说 AI 代码为什么容易欠债、AI 代码如何做 Review、用 AI 改代码要注意什么、怎么让 AI 自动写测试用例以及最关键的——AI 来了工程师的活到底怎么干。1. 先搞清楚一件事AI 代码为什么天生带着“债”1.1 AI 最擅长的是“看起来能跑”而不是“长期能维护”先讲一个我自己的真实经历。上个月我让 AI 帮忙写一个订单模块的金额计算函数输入需求后它几秒钟就给了完整实现逻辑看起来天衣无缝有入参校验、有精度处理、有边界判断甚至把注释都写好了。我图省事直接提交结果第二天同事在 Review 时问了我三个问题我一个都答不上来这里为什么要用Math.floor而不是Math.round四舍五入在金额场景是有问题的你是故意的还是 AI 随手写的这个函数同时处理了美元、日元和韩元但日元的货币精度是 0为什么代码里统一用了两位小数异常处理里吞掉的InvalidCurrencyException在现有日志系统里能不能查得到那一刻我意识到一个问题AI 生成代码最大的陷阱是它擅长把所有常规情况包装得很精美但对于业务上下文和设计初衷它是完全无感的。代码在语法上是通的在测试用例上可能是绿的但在“为什么这么写”这个维度上它其实是在一本正经地编造一个合理的解释然后把风险留给下一个接手的人。技术债的本质是什么不是功能缺失而是认知缺口。你看到一个函数知道它做什么但不知道它为什么这样做、在什么约束下这样做、有什么坑是不能踩的。AI 批量生产的代码恰恰能制造大量这种认知缺口。它把“必要性”藏在了“可能性”的假象里。1.2 AI 代码的技术债通常分为三类我后来在团队内部做了一个简单分类大家在复盘时直接对号入座效率高了很多债务类型典型表现积累路径认知债务代码无法解释为什么要这样写缺少业务背景每次改动都需要重新考古结构债务模块边界混乱AI 为满足一个功能而“顺便”改动无关代码重构时牵连面爆炸验证债务测试覆盖是绿色的但测的是“AI 自己以为的应该”而不是“业务真正要求的必须”出问题时完全无感结构债务特别值得一提。我用 AI 改过一个老接口它非常“贴心”地帮我把一个函数的签名改了还把调用方一起改了甚至连单元测试都顺手更新了。表面看是好事但问题在于这次改动明明只是加一个参数AI 却把原本清晰的分层架构硬塞成了扁平的杂烩。因为它不理解“为什么这一层要存在”它只知道“这样改能跑通所有现有测试”。这就是 AI 代码和人类代码最大的区别。人类写代码的时候脑子里有整个架构地图知道每一块是为了什么而存在会克制自己去破坏边界。 AI 没有这种克制它的优化方向是“通过当前所有验证”而不是“让系统之后的十年都好维护”。1.3 “代码降 AI 率”这个方向根本就走偏了顺便说一句网上现在流行一个说法叫“代码降 AI 率”意思是通过各种手段让代码看起来不像是 AI 生成的。我非常不推荐大家在这件事上花时间。代码是要给机器执行、给人维护的不是用来参加“AI 生成器检测大赛”的。你花心思把变量名改得混乱一点来骗过检测表面上是在保护自己的“原创性”实际上是在给未来的自己和同事挖坑。代码不像作文不需要证明“这是人写的”。真正需要证明的是这代码能不能在半年后被人快速看懂、安全改动。与其琢磨怎么降 AI 率不如把心思花在怎么给 AI 代码做 review 上。2. AI 代码的 Review 方法不能只看 diff要学会“审问”2.1 传统的 Code Review 清单在 AI 代码面前不够用很多人现在 review AI 代码用的还是老一套看变量命名规不规范、函数拆得细不细、有没有明显 bug、注释写没写。这套东西不是没用但在 AI 代码面前远远不够。因为 AI 代码的问题很少出在“语法不规范”这种层面它的问题几乎都出在**“语义正确但意图可疑”**的层面。我试过一次很典型的场景。让 AI 实现一个 Redis 缓存更新逻辑它写出来的代码不仅正确而且性能很好缓存更新用了 pipeline失效策略用了双 key。但问题是我们的业务场景根本不需要这么高级的策略系统高峰也就几百 QPS这个复杂逻辑带来的心智负担远大于它省下来的那点资源。传统的 Code Review 只会问“这个代码对不对”但 AI 生成的代码需要你额外问一句“这个代码该不该出现在这里”。这句“该不该”包含了很多维度这个复杂度是不是当前业务必需的还是 AI 在“炫技”这段逻辑的存在是不是因为 AI 没有理解某个历史原因而重复造轮子这些边界条件是业务真实需要还是 AI 为了让覆盖面好看而编造出来的2.2 我总结的“AI 代码四问”Review 法在反复踩坑之后我给自己定了一条铁规矩凡是 AI 生成的代码Review 时必须过“四问”不过关就直接打回。第一问这段代码的每一行成员能不能真正解释清楚这里不是问“这个函数是干嘛的”而是随便指着一行核心逻辑问“这一行为什么要这么写”。如果一个函数里出现了某个让所有人都说不清动机的写法那不管测试怎么绿都必须当场把上下文补齐。认知债就是在这些“说不清”里悄悄积累的。第二问如果业务需求明天改变这段代码是更容易改还是更難改AI 代码经常是“为了跑通而写”的它不会为未来留扩展位。比如一个支付回调处理函数AI 把所有渠道的差异逻辑全写在了一个大 if-else 里某种程度上是能运行的但下个月新接入一个渠道你就得在这个大混沌里找地方改。Review 时碰到这种就算当前功能没问题我也一定会要求拆开。第三问测试是在验证“业务需求”还是在验证“AI 的理解”这是最容易翻车的地方。AI 自动写测试用例的时候它会更倾向于“验证自己写的实现逻辑正确执行了”而不会去“验证业务方真正要求的结果”。这两个东西在大多数时候是一致的但当需求有隐含条件的时候AI 写的测试会完美地遗漏那个隐含条件。Review 测试代码时我会把一个测试拿出来盖住实现部分只看断言然后问同事“如果业务规则是 A这个断言验证的是不是 A”经常能得到否定的答案。第四问这段代码是让整个系统更简单了还是更复杂了很多 AI 生成代码看似优雅实则是在用一个复杂的模式试图掩盖另一个简单的方法。Review 时如果感觉某个地方“过度设计”了不要犹豫直接提出来。系统复杂度的累积速度和技术债的累积速度是成正比的。2.3 一个 AI 代码 Review 的真实案例上个月我们组处理过一个 AI 生成的数据导出模块Review 过程就很有代表性。AI 写了一个通用的 CSV 到处工具支持任意数据类型自动转字符串、自动加引号、自动处理转义。代码看着很漂亮泛型、策略模式、反射全用上了测试也全绿。但真正业务上只需要导出一个固定的表结构。我拿“四问”过了一遍立刻发现问题这个通用工具引入了大量运行时反射性能差了十倍不止同时因为“太通用”复杂的转义逻辑导致导出的数字变成了字符串在 Excel 里直接是文本格式用户没法做求和统计。最后我们把这个 AI 生成的“通用”代码换成了一个针对业务字段结构的、朴素的硬编码导出函数。代码量从 300 行降到 80 行性能提升十倍业务方再也没报过错。所以 Review AI 代码核心原则就一句话**AI 的产出是“可用”你的工作是确保“适用”。**不要因为代码能跑就觉得可以合入你要为系统的长期演进负责。3. 用 AI 改代码的实操经验别让“顺手优化”变成“顺手埋雷”3.1 我踩过的坑AI 完全没有“范围感”很多同学喜欢让 AI“帮我把这段代码优化一下”然后直接接受 diff。这是我见过最危险的操作没有之一。AI 的“优化”完全没有范围感它不像人一样知道“我只想改这个函数其他不动”它会因为觉得“另一个地方也怪怪的”而顺手改掉。表面上这很贴心实际上一旦它改动了一个你没想到的模块可能连带触发一系列你没有意识到的连锁反应而测试环境还不一定能覆盖到。打个比方你请人帮忙修洗手间漏水的水管师傅来了之后不仅修了水管顺手把你的承重墙砸了理由是这样采光更好。你验收时发现洗手间确实不漏水了但整栋楼的结构已经埋下了隐患。AI 改代码就是这样它只关心局部目标不理解全局约束。3.2 让 AI 改代码的正确姿势把“自由发挥”锁死后来我摸索出了一个在团队内部推广的效果很好的工作流核心思想就四个字缩小授权。具体分三步第一步先圈出改动边界。在给 AI 的指令里明确说清楚“只允许修改 xxx 函数其他任何文件都不得改动”。把涉及的函数签名、文件路径、依赖关系全都写清楚不给 AI 留下“自由发挥”的空间。第二步让它先解释再修改。我会先让 AI 说明当前代码存在什么问题、准备怎么改、改动会影响到哪些调用方。等它把思路说清楚了我再决定要不要真让它动手。这一步非常管用因为 AI 一旦“说”出自己的计划那些不合理的思考就会暴露出来你可以在它动手之前及时喊停。第三步改完做“最小 diff 检查”。让 AI 完成修改后我会刻意检查一遍 diff只看“实际改了多少行”。如果一次预期改动只有 10 行结果 AI 改出了 50 行那就说明它的动作变形了直接回退重来。控制 diff 的规模就是控制技术债的增量。3.3 让 AI 看代码也要有“Skill”意识“ai 看代码的 skill”现在也是一个热门话题。很多人指望 AI 能像资深工程师一样扫描代码库自动指出 bug 和设计不合理的地方。我的实测结论是能做但要给足上下文并做好期望管理。你会发现当你直接扔给 AI 一个仓库让“看看有没有问题”时它通常会给出泛泛而谈的大路货建议比如“建议增加错误处理”、“建议提取公共方法”。这类意见不能说错但基本等于废话对你的代码质量提升毫无帮助。但如果你先给 AI 喂入“项目背景说明 关键模块的职责说明 你关心的具体风险点”再让它针对性地扫描它往往能给出质量高得多的发现。这就好比体检你告诉医生“我最近胸闷活动后加重”医生会直奔心肺去做检查你只说“我不太舒服”医生只能给你开一个最普通的常规套餐什么都查不深。你如果真的想借助 AI 扫描代码 bug 和设计缺陷我建议这样操作圈定范围不要让 AI 扫描全库一次只扫描一个模块或一个服务。指定关注点把你在意的点列出来比如“并发安全、事务边界、异常处理、状态机完整度”。要求输出格式让它按“问题位置、问题类型、影响场景、修复建议”的格式输出方便直接跟进。用“关键决策问题”倒逼深度分析比如直接问 AI“这个函数在并发调用时会不会出现脏数据为什么”有压力的输入会逼它真正去分析而不是套路式回答。4. AI 自动写测试用例的正确打开方式从“凑覆盖率”到“锁业务”4.1 用 AI 自动写测试用例最怕的是“自证清白”AI 自动写测试用例这个能力确实很香我们团队现在也经常用。但这里有一个必须警惕的点AI 写出的测试本质上是在为 AI 写的实现做辩护。什么意思呢如果 AI 先写了实现函数 A然后又为这个函数写测试用例 B那么 B 只会验证“A 在逻辑上自洽”它很难发现“A 实现的业务规则与需求文档不符”。因为 B 源自 A而不是源自需求。这就是为什么我坚持一个原则AI 写的测试要么是业务方先定义好断言要么是 reviewer 用需求文档反向核对断言指望 AI 全自动搞定是不现实的。我的具体做法是这样让 AI 写测试时我会先把接口的输入条件、期望输出、边界值这些内容直接写在指令里并明确告诉它“不要修改实现代码只根据这些业务规则来写测试”。这样测试就变成了对实现的约束而不是对实现的附和。4.2 用 AI 做自动测试、自动生成的实战流程目前我们团队在用的流程是“人工定断言 AI 补案例”的配合模式我先从需求文档里提炼出 5-8 条核心业务规则写成测试断言的骨架。然后把这些断言连同接口定义一起丢给 AI让它补全具体的测试数据、异常分支和边界情况。AI 补完用例之后我会执行一次完整的测试重点关注那些“出乎我意料”的失败用例——因为 AI 额外生成的边界值往往能暴露出一些我事先没想到的实现问题。最后会把 AI 生成的测试名称和需求条目映射起来确保每条测试都能追溯到一条业务需求而不是凭空而来。实测下来这个流程的好处是显而易见的测试覆盖率不仅上去了而且覆盖率的质量也上去了不再是那种“每个函数都执行了但是啥也没验证”的虚假绿。另外AI 自动写测试用例还有一个隐藏好处它能督促我们把业务规则写清楚。AI 是无法在模糊的需求面前写出好测试的你必须先把“什么场景下、输入什么、期望什么”说清楚。这个过程本身就是对我们自己业务理解的一次反推。5. AI 时代工程师的核心能力反而是“更值钱”的5.1 “AI 抢走写代码工作”之前先抢走的是“不思考的习惯”最近“ai 抢走写代码工作谁来培养工程师”这个话题被反复讨论。我个人的看法是单纯的“写代码”这个动作确实正在被 AI 冲击但“写代码”从来都不是工程师的核心能力“决定代码该怎么写”才是。AI 可以在 10 秒内生成一个 Redis 分布式锁的完整实现但它没法判断你的业务是否需要分布式锁AI 可以一键把代码格式化成最规范的风格但它没法判断这个模块的边界是否应该在这里AI 甚至能自动帮一个函数补全所有参数校验但它没法告诉你这个函数的调用方在异常情况下应该怎么表现。这些决策能力从哪里来只能从真实的工程实践中来。而最佳的工程实践训练场恰恰就是 Code Review。让新人跟有经验的工程师一起 Review AI 代码从“AI 写的这个分支真的必要吗”这种问题开始讨论就是在培养 AI 时代最稀缺的技能——在代码里做判断和取舍的能力。如果一个团队把所有 AI 代码的 Review 全都交给最资深的一个人新手只看结果不参与判断那这团队不是在用 AI 提效是在自断后路。5.2 我实操中沉淀的几条 AI 代码使用规范在团队里推行 AI 辅助编程半年多之后我沉淀了几条非常朴素的规范直接分享给大家拿去就能用AI 产出的代码默认视为“陌生同事提交的代码”必须经过完整 Review 才能合入没有豁免权。AI 生成的核心业务逻辑不允许直接进主仓库至少要经过“让 AI 先解释再由人来验证”的环节。阶段性地做“AI 代码债务巡检”每月抽两个下午挑几个 AI 参与度最高的模块专门去检查有没有“看起来能跑、实则与业务不一致”的逻辑。不在 AI 工具上追求“一次生成零修改”因为这个诉求会把我们推向相反的极端——让 AI 固化它那套自我一致但不合理的逻辑导致我们丧失对代码的掌控力。说到底AI 是你的杠杆但杠杆的支点必须是你自己的判断力。如果支点是沙子肩膀上挑的东西越多摔得越快。5.3 给团队管理者的一个建议如果你是一个技术管理者正在团队里推动 AI 编程赋能请务必在“提效指标”旁边加一个“代码可维护性指标”。我见过团队 KPI 只盯着“AI 代码占比”“需求交付速度”的结果三个月之后review 成了走形式代码里开始出现团队成员自己都说不清来历的“神秘代码块”。不要追求 AI 参与率百分之百宁可追求“AI 生成代码的返工率”走在合理区间。返工率高说明大家在严格把关短期看着慢长期看反而是最稳的。最怕的是大家为了省事把 review 变成“看绿灯就点合入”那才是真正把 AI 变成了技术债加速器。6. 常见问题速查遇到这几种情况赶紧停下最后整理一个速查表都是我们团队实战中遇到过的典型现象。如果哪天你在代码里发现这些苗头可以对照着快速检查一下现象可能原因处理建议AI 生成代码出现大量“泛化”“通用化”设计AI 在追求抽象美感而非业务适配回到业务场景按需简化测试全绿但联调时行为不符合预期测试是 AI“自证清白”的产物用需求规则反向重写断言一次小改动动了几十个文件AI 没有“范围感”顺手改了不该动的回退重来缩小改动授权代码没有注释也没有 commit message 解释团队把 AI 当“最后一公里”工具没做 review建立 AI 代码 mandatory review 制度你发现自己对某段 AI 代码“完全没印象”说明合入时根本没认真看翻 git 历史找提交人补做 review代码里出现“不必要的复杂模式”反射、动态代理等AI 为了显得“高级”对标业务复杂度重新实现看到这里你应该也明白了AI 写代码不是原罪不做质量把控的 AI 写代码才是。技术债并不是 AI 产生的而是“把 AI 的输出直接当成最终结果”的流程产生的。我个人在实际操作中的体会是AI 编程这件事很像开车从手动挡换到自动挡——操作门槛确实低了一大截但正因为操作门槛低了你才更需要时刻盯着路况、看着后视镜。代码仓库就是你的车AI 是新的发动机但方向盘和刹车必须还牢牢握在人的手里。如果这篇文章能给你留下一个可执行的动作我希望是这一条下一次拿 AI 生成的代码去提交前先点开阅读一下试着用“四问”过一遍。这个过程可能会多花十分钟但它大概率能帮你省下未来十个小时的排查时间甚至是一个通宵的线上事故。