AI写代码质量治理:工程规范、代码评审与风险驱动测试实践

发布时间:2026/10/11 23:22:01
AI写代码质量治理:工程规范、代码评审与风险驱动测试实践
1. 当AI开始写代码质量治理为什么成了新命题这两年团队里用AI辅助编码的比例肉眼可见地涨起来了。去年还只是零星几个人在编辑器里装个补全插件今年已经是默认操作——写业务逻辑、补单元测试、生成数据转换脚本、甚至重构老模块第一反应都是先让AI出一版草稿。效率确实上来了一个中等复杂度的CRUD接口以前从设计到自测大半天现在半小时能跑通。但随之而来的问题也很集中代码能跑不代表能维护测试能过不代表覆盖了真正的风险点。我所在的团队大概二十来人前后端加测试都有过去半年我们踩了不少坑。最典型的一次是某个数据同步模块AI生成的代码逻辑上没问题但把一批本该分批处理的记录一次性加载进内存测试环境数据量小完全看不出来上线第二天数据量涨上来直接把服务打挂了。还有一次是AI补的单元测试断言写得漂漂亮亮覆盖率报告一片绿结果它测的全是happy path边界条件一个没碰真出问题的时候那些测试形同虚设。这些经历让我意识到一件事AI Coding带来的不是单纯的效率问题而是质量治理体系需要重新校准。传统那套“人写代码、人评审、人写测试”的流程默认了每个环节都有人的判断力兜底。现在代码是AI生成的评审的人容易产生“它写得挺规范应该没问题”的松懈测试也可能是AI自己生成的等于自己给自己出题自己判卷。整个链条上的判断力被稀释了风险就藏在这些稀释掉的缝隙里。这篇内容我想聊的就是我们团队这半年摸索出来的一套做法围绕三个抓手工程规范怎么定才能约束AI而不是束缚人、代码评审怎么改才能抓住AI代码的特有风险、测试怎么从覆盖率导向转向风险驱动。适合正在团队里推AI编码、或者已经被AI代码质量问题折腾过的同行参考。不管你是刚开始用AI写代码的新手还是已经在做质量把控的负责人这里面的思路和具体操作应该都能直接拿去用。2. 工程规范给AI划边界而不是给人上枷锁2.1 为什么传统规范对AI代码基本失效先说个反直觉的观察AI生成的代码在“表面规范”上往往比人写得更整齐。命名统一、缩进一致、注释格式规整lint工具跑下来几乎零告警。这恰恰是问题所在——传统工程规范检查的是格式和风格而AI最擅长的就是模仿格式和风格。你把ESLint规则配得再严它生成的代码照样能过因为格式合规对它来说是基本功。真正出问题的地方在规范管不到的区域。比如一个函数该不该拆、一个抽象该不该引入、错误处理该吞还是该抛、并发场景下共享状态怎么保护——这些属于“设计层面的规范”传统lint工具根本检查不了。AI在这些地方的表现很不稳定它倾向于生成“看起来合理”的代码但缺乏对业务上下文和运行环境的理解。我们内部做过一个统计把过去三个月AI生成的代码里出过问题的部分拉出来看格式类问题占比不到5%剩下95%全是设计层面和边界处理层面的问题。这个数据直接改变了我们对规范的理解规范的重点要从“格式约束”转向“结构约束和风险约束”。2.2 我们落地的三层规范体系基于上面的判断我们把工程规范拆成了三层每层的检查手段和约束力度都不一样。第一层是格式与静态检查层这层基本交给工具自动化。ESLint、Prettier、Checkstyle这类工具配好提交前hook跑一遍不过不让提交。这层对AI代码来说几乎不构成挑战但必须要有因为它能过滤掉最低级的错误比如变量未定义、明显的类型不匹配。这层的规则我们尽量保持宽松只留真正必要的避免规则太多导致AI为了过检查生成一堆无意义的规避代码。第二层是结构与设计约束层这层是重点。我们定了几条硬性规则专门针对AI容易出问题的地方单函数行数上限超过80行的函数必须拆分。AI特别容易生成超长函数因为它倾向于把逻辑一口气写完不做抽象。圈复杂度上限超过15必须重构。AI生成的代码分支嵌套经常很深尤其是处理多条件业务逻辑的时候。禁止裸的异常吞没catch块里必须有日志或重新抛出不允许空catch。AI有时候会生成“为了不报错而catch”的代码。资源必须显式释放文件流、数据库连接、锁必须用try-with-resources或defer这类机制。AI在简单场景下会记得复杂场景下经常忘。外部调用必须有超时和重试策略这条是血泪教训AI生成的HTTP调用默认不带超时线上出过事。这些规则我们写成了自定义的静态检查规则集成在CI里。规则本身不复杂但每一条都对应着实际出过的问题。第三层是风险标注层这层比较特殊不是自动检查而是要求开发者在提交AI生成代码时对特定类型的代码打上标注。比如涉及金额计算、涉及权限判断、涉及数据删除的代码段必须显式标注“AI生成-需人工复核”。这个标注不是形式主义它会在代码评审环节触发强制的人工深度检查评审人看到标注就必须逐行确认逻辑不能扫一眼就过。2.3 规范落地的几个实操心得规范定出来容易落地难。我们踩过的坑里有几个值得单独说。规则数量要克制。一开始我们雄心勃勃定了三十多条规则结果AI为了过检查生成大量绕规则的代码反而更难读。后来砍到十二条核心规则效果反而好了。规则太多会逼着AI“应试”生成看起来合规但实际别扭的代码。规则要能解释清楚为什么。我们在每条规则的文档里都写了“这条规则防的是什么问题”并且附上真实案例。这样做的好处是当AI生成的代码触发规则时开发者知道该往哪个方向改而不是机械地拆函数凑行数。定期回顾规则的误报率。有些规则在特定场景下会误报比如某些配置类的长函数确实不该拆。我们每个月review一次规则的触发记录误报率超过20%的规则要么调整阈值要么下线。规范是给人用的不是用来刷存在感的。提示规范体系刚上线的时候建议先跑一周的“观察模式”只记录不阻断看看AI代码实际触发哪些规则最多再决定哪些规则转成强制。一上来就全强制开发体验会很差容易引起抵触。3. 代码评审从“看格式”转向“抓风险”3.1 AI代码评审的三个特有盲区代码评审这件事在AI参与之后发生了微妙但重要的变化。以前评审人看的是同事写的代码心里有预期——这个人水平怎么样、这个模块他熟不熟、他最近是不是赶进度。这些背景信息会自然影响评审的注意力分配。现在代码是AI生成的评审人失去了这些背景线索容易陷入一种“无差别扫描”的状态反而抓不住重点。我们观察下来AI代码评审有三个特有的盲区。第一个盲区是逻辑正确性的“表面自洽”。AI生成的代码逻辑读起来往往很顺变量命名合理、流程清晰评审人读一遍觉得“没毛病”就过了。但AI可能在某个业务规则的理解上偏了比如把“满减”算成了“折扣”代码本身逻辑自洽但业务语义错了。这种错误靠读代码很难发现必须对照需求文档逐条验证。第二个盲区是边界条件的系统性缺失。AI倾向于处理“正常情况”对空值、零值、超大值、并发冲突这些边界场景覆盖不足。评审的时候如果只看主流程很容易漏掉。我们后来要求评审人必须专门问一句“这个函数的输入如果是空/零/负数/超大值会怎样”第三个盲区是依赖和副作用的隐蔽性。AI生成的代码有时候会引入一些不明显的依赖比如隐式地依赖某个全局状态、依赖某个方法的执行顺序、依赖某个外部服务的特定返回格式。这些依赖在代码里看不出来但运行时会出问题。评审的时候需要特别关注“这段代码假设了什么”。3.2 我们改造后的评审流程针对这三个盲区我们把评审流程做了改造核心思路是把评审从“通读代码”变成“定向检查”。评审前提交者需要填一个简短的评审说明包含三个必填项这段代码要解决什么问题、AI生成了哪些部分、哪些部分是人工修改或补充的。这个说明看起来增加了工作量但实际上大幅提升了评审效率因为评审人知道了该重点看哪里。评审时我们要求评审人按固定顺序检查先看业务语义对照需求确认代码做的事情和需求描述一致。这一步不看代码细节只看输入输出和业务规则。再看边界处理专门检查空值、零值、异常路径、并发场景。我们做了一个边界检查清单评审人对着清单过一遍。然后看依赖和副作用确认代码没有隐式依赖外部调用有超时和错误处理共享状态有保护。最后看可维护性命名、注释、函数拆分这些。这个顺序很重要因为人的注意力是有限的先看最重要的格式问题放最后。以前大家习惯从第一行开始逐行读读到后面注意力就散了反而漏掉关键问题。3.3 评审环节的独家避坑技巧说几个我们实际用下来很有效的技巧。“反向提问法”。评审AI代码的时候不要问“这段代码对不对”要问“这段代码在什么情况下会出错”。前一个问题容易得到“看起来对”的答案后一个问题会逼着评审人去构造异常场景。我们内部甚至有个小活动评审的时候比赛谁先找到AI代码的边界bug找到的人请喝奶茶氛围起来了评审质量也上去了。“最小复现”要求。对于AI生成的复杂逻辑我们要求提交者提供一个最小复现的测试用例证明这段代码在正常和异常情况下都符合预期。这个要求倒逼提交者在提交前自己先验证一遍很多低级问题在这一步就被拦住了。评审意见要具体到行。以前评审意见经常是“这里逻辑有点问题再看看”这种意见AI和人都不知道怎么改。现在我们要求评审意见必须具体到某一行说明“在什么输入下会出什么问题建议怎么改”。这条规则执行下来评审意见的有效性提升非常明显。注意评审AI代码的时候最危险的心态是“它写得挺规范的应该没问题”。规范只代表格式合规不代表逻辑正确。每次评审都要假设“这段代码可能有业务语义错误”带着这个假设去验证。4. 风险驱动测试告别覆盖率自嗨4.1 覆盖率为什么骗了很多人单元测试覆盖率这个指标在AI参与编码之后欺骗性变得更强了。原因很简单AI生成测试用例的能力很强但它生成的测试往往集中在容易测的地方。一个函数有十个分支AI可能给其中八个正常分支写了测试覆盖率报告显示80%看起来不错。但剩下那两个没测的分支恰恰是异常处理和边界条件是最容易出问题的地方。我们内部做过一次对比同一个模块AI生成的测试覆盖率85%人工补充测试后覆盖率92%看起来只差7个百分点。但把两次测试都跑一遍变异测试mutation testingAI版本的变异杀死率只有40%人工补充后到了75%。也就是说AI写的测试虽然覆盖了代码行但很多测试的断言太弱代码改了它也不报错等于白测。这个发现让我们彻底放弃了“覆盖率达标就行”的做法。覆盖率可以作为参考指标但绝不能作为质量门禁的唯一标准。4.2 风险驱动测试的落地方法我们转向了风险驱动测试核心思路是测试资源优先投在风险最高的地方而不是均匀撒开。第一步是风险识别。每个模块在开发前开发者需要标注这个模块的风险等级依据是三个维度业务影响面出问题影响多少用户/多少钱、逻辑复杂度分支多不多、状态多不多、变更频率是不是经常改。三个维度各分高中低组合起来决定风险等级。第二步是测试策略分级。高风险模块要求分支覆盖率100%、必须有边界测试、必须有异常路径测试、必须做变异测试且杀死率不低于70%。中风险模块要求分支覆盖率80%、关键边界测试、异常路径测试。低风险模块行覆盖率60%即可主要靠集成测试兜底。第三步是测试用例评审。AI生成的测试用例不能直接合并必须经过评审。评审的重点不是看覆盖率数字而是看测试用例是否覆盖了风险点。我们有一个检查清单空值测了吗、零值测了吗、最大值测了吗、异常输入测了吗、并发场景测了吗、外部依赖失败测了吗。对着清单过一遍缺的补上。4.3 变异测试检验测试有效性的利器变异测试是我们这套体系里最关键的一环值得单独说。它的原理很简单工具会自动修改你的代码比如把改成、把改成-、删掉一个条件判断然后跑你的测试如果测试没报错说明这个变异“存活”了意味着你的测试没覆盖到这个逻辑。存活率越高测试越无效。我们一开始只在核心模块跑变异测试后来发现效果太好逐步推广到了所有高风险模块。实际操作中变异测试跑起来比较慢我们一般放在 nightly build 里跑不阻塞日常提交。但高风险模块的变异杀死率是硬性门禁低于70%不允许上线。这里有个实操细节变异测试会产生大量“等价变异”改了代码但行为不变这些不算存活。工具一般会自动过滤但过滤不干净的时候需要人工判断。我们踩过的坑是早期没注意等价变异导致杀死率虚低白白优化了一堆没问题的测试。4.4 测试数据管理的经验风险驱动测试对测试数据的要求比传统测试高因为要覆盖各种边界场景。我们在这块也积累了一些经验。测试数据要版本化。边界测试用的数据比如超大值、特殊字符、并发场景的构造数据要单独管理不能散落在各个测试文件里。我们建了一个测试数据仓库按模块和场景分类测试用例引用数据仓库里的数据集。这样做的好处是数据可复用、可审查、修改一处全局生效。生产数据脱敏后用于测试。有些边界场景只有真实数据才能触发我们定期从生产环境抽样脱敏后导入测试环境。脱敏规则要严格涉及用户信息的字段全部替换但数据分布特征保留。这样测出来的边界问题更接近真实。测试数据要定期刷新。业务在变数据的分布也在变。我们每季度刷新一次测试数据集确保边界值仍然有代表性。有次我们发现一个测试用的“超大值”在业务增长后已经不算大了导致测试失效后来就把刷新机制固定下来了。5. 工具链与自动化让治理可持续5.1 我们实际在用的工具组合工具这块我不推荐具体产品只说类型和选型逻辑因为不同技术栈差异很大。我们团队是Java和TypeScript为主工具组合大概是这样的静态检查用主流的lint工具加自定义规则插件自定义规则主要实现前面说的结构约束层。CI集成用现成的流水线工具在提交和合并两个节点分别跑不同级别的检查。变异测试用开源的变异测试框架配置成nightly任务。测试数据管理用了一个轻量的数据版本工具自己写脚本对接的。选型的时候我们遵循一个原则工具要能集成到现有流程里不增加额外操作步骤。如果一个工具需要开发者手动跑、手动传结果基本活不过一个月。所有检查都挂在CI上开发者只需要正常提交代码检查自动触发结果自动反馈。5.2 自动化门禁的分级设计门禁设计我们分了三级对应不同的阻断力度。提交级门禁格式检查、基础静态检查。不过不让提交。这级门禁要快最好在10秒内出结果否则开发者会烦。合并级门禁结构约束检查、单元测试、覆盖率检查、高风险模块的变异测试。不过不让合并。这级门禁可以慢一点几分钟内能接受。发布级门禁集成测试、端到端测试、性能测试、安全扫描。不过不让发布。这级门禁最慢但发布频率低可以接受。分级的好处是日常开发不会被重型检查拖慢但关键节点该拦的都能拦住。我们一开始把所有检查都放在提交级结果开发者等检查等到崩溃后来拆开之后体验好多了。5.3 度量与反馈让质量看得见治理体系要持续运转必须有度量。我们跟踪几个核心指标AI代码占比、评审发现的问题密度、变异杀死率、线上事故中AI代码的占比。这些指标每月review一次不追求好看追求真实反映问题。有个细节值得说度量指标不要用来考核个人。我们一开始把评审问题密度和绩效挂钩结果大家都不敢提交AI代码了或者提交前反复检查导致效率下降。后来改成只做团队级度量用于发现系统性问题个人层面不做排名氛围才正常回来。反馈机制也很重要。每次线上出问题我们都会回溯是不是AI代码、哪个环节没拦住、规范或流程需要怎么补。这个回溯不追责只改进流程。半年下来我们的规范体系里有将近一半的规则是线上问题倒逼出来的每一条都有血泪教训。6. 几个真实踩坑案例的复盘6.1 内存溢出那次事故的完整复盘前面提到的数据同步模块内存溢出值得展开说。AI生成的代码逻辑是这样的从数据库查出所有待同步记录放到一个List里然后遍历List逐条处理。测试环境数据量几千条跑得好好的。上线后数据量涨到几十万条一次性加载直接OOM。问题出在哪AI没有“数据量可能很大”的意识它默认了“查出来处理就行”。评审的时候评审人看到的是清晰的逻辑也没意识到数据量的问题。测试的时候测试数据是AI自己生成的它生成的也是小数据集。后来我们的改进是所有涉及数据查询的代码必须显式声明预期数据量级并且必须分页或流式处理。这条规则写进了结构约束层静态检查会扫描数据库查询调用如果没看到分页参数或流式处理标记直接报错。同时测试数据里强制加入大数据集场景专门测内存和性能。6.2 权限判断被绕过的案例另一个案例更隐蔽。AI生成了一段权限判断代码逻辑是“如果用户角色是管理员则允许操作”。看起来没问题但业务规则其实是“管理员且属于该组织”才能操作。AI漏掉了组织维度的判断。评审的时候评审人看到“管理员允许操作”觉得符合直觉就过了。测试的时候AI生成的测试用例只测了管理员和非管理员两种情况没测“管理员但不属于该组织”的情况。上线后一个跨组织的管理员账号执行了不该执行的操作虽然没造成实际损失但暴露了严重的安全隐患。这个案例让我们意识到AI对业务规则的理解是字面级的它不会主动追问“还有没有其他条件”。后来我们在评审流程里加了一条涉及权限、金额、状态流转的代码必须由熟悉业务的人对照需求文档逐条确认不能只看代码。6.3 并发场景下的隐蔽bug还有一个并发相关的案例。AI生成了一段缓存更新代码逻辑是“先查缓存没有则查数据库然后写缓存”。单线程下没问题并发下多个请求同时发现缓存没有同时查数据库同时写缓存造成缓存击穿。这个bug在测试环境几乎不可能发现因为测试环境的并发量很低。我们是上线后通过监控发现数据库QPS异常升高才定位到的。AI生成这段代码的时候完全没有考虑并发场景它只是按“正常流程”写了一遍。改进措施是所有涉及缓存、共享状态、并发访问的代码必须显式标注并发风险并且必须经过并发场景的专项评审。我们还在测试环境引入了并发测试工具对高风险模块做并发压测专门触发这类问题。7. 团队协作与心态调整7.1 怎么让团队接受这套体系推这套体系的时候最大的阻力不是技术是心态。有同事觉得“AI写的代码挺好的搞这么多检查是浪费时间”也有同事觉得“这是不信任我的判断”。我们的做法是先用数据说话把线上事故的复盘拿出来让大家看到问题真实存在然后再推规范。另一个关键是让规范本身足够轻。我们反复强调规范是为了拦住真正的问题不是为了增加流程。每条规则上线前都问一句“这条规则能防住哪个具体问题”答不上来的就不上。执行过程中也持续收集反馈误报多的规则及时调整。7.2 AI代码的署名与责任我们内部有个约定AI生成的代码提交者就是责任人。不管代码是谁写的或者哪个AI写的提交的人对代码质量负责。这个约定很重要它避免了“这是AI写的不怪我”的甩锅心态。提交者在提交前必须自己先验证一遍评审人发现问题提交者负责修改。同时我们鼓励在提交说明里标注哪些是AI生成的、哪些是人工修改的。这不是为了追责是为了积累数据让我们知道AI在哪些场景下容易出问题后续可以针对性加强规范。7.3 持续迭代的心态这套体系不是一次设计出来的是半年里不断迭代出来的。我们每个月开一次质量回顾会看指标、看案例、调整规则。有些规则上线后发现没用就下线有些新问题出现就补新规则。保持迭代的心态很重要不要指望一套规范管一年。我个人最大的体会是AI Coding的质量治理本质上是把人的判断力重新分配到最关键的地方。以前人的判断力均匀分布在写代码、评审、测试各个环节现在写代码环节的判断力被AI替代了一部分那就要把评审和测试环节的判断力加强尤其是针对AI容易出问题的地方。这不是对抗AI是跟AI协作时找到新的平衡点。8. 后续可以继续深化的方向这套体系跑下来整体效果是正向的。线上事故里AI代码的占比从最初的六成降到了两成左右评审发现问题的效率也明显提升。但还有几个方向我们觉得可以继续深化。一个是AI代码的专项测试用例生成。目前测试用例还是人工写为主、AI辅助我们在尝试让AI针对风险点定向生成测试用例比如专门生成边界测试、异常测试然后人工评审筛选。初步试下来效果不错但需要给AI提供足够的上下文否则它生成的测试还是偏向happy path。另一个是评审辅助工具。我们在尝试用AI辅助评审让它先扫一遍代码标出可能的风险点评审人再重点看这些标出的地方。这个思路能减轻评审人的负担但AI标注的准确率还需要调优目前误报有点多。还有一个是跨团队的规范共享。不同团队用AI编码的场景不一样踩的坑也不一样。如果能有一个机制让大家共享规则和案例整体治理水平能提升更快。这个还在探索阶段涉及一些协作机制的设计。这些方向都不成熟但值得投入。AI Coding的实践还在快速演进质量治理的方法论也得跟着变。保持开放和迭代的心态比固守一套完美方案更重要。