ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

AI生成代码的“生成即规范”实践:规则引擎与可观测性

AI生成代码的“生成即规范”实践:规则引擎与可观测性 从第三十弹之后我就一直在琢磨一件事AI生成的代码越来越快但Review打回率却一直压不下去。三十二弹那次我做过一个统计团队里AI参与度最高的几个模块一次通过的PR不到四成。这个数字让我意识到问题不在AI写得不够好而在我们一直在用事后补救的思路对待AI代码——先让它写写完再审查审出问题再改。改一次、两次、三次成本全耗在循环里了。所以从三十三弹开始我把整套思路翻了过来不做生成后审查改成生成即规范。这篇第三十六弹就把这段时间沉淀下来的设计思路、规则层实现、调测配套和最近的新尝试一次讲透。1. 为什么我坚持生成即规范而不是生成后审查1.1 事后修复的代价曲线一次Review打回背后的隐性成本先看一个实际场景。以前我们团队让AI生成一个分页查询接口AI吭哧吭哧几十秒给出几百行代码。乍一看挺像样类的命名、注释都有。但Review的时候问题来了分页参数没有校验、返回结构不统一、日志裸奔没有traceId、异常被吞掉直接返回了null。这些问题是靠人眼扫出来的。一个开发同事要从几百行代码里逐个挑出这些毛病挑出来之后还要在聊天框里一句一句描述哪里不对、怎么改AI再改一版又引入两个新问题再打回。一来一回一个下午就没了。这个循环里最贵的不是AI生成代码的时间而是人的阅读时间、上下文切换时间、沟通成本。我当时做了一个粗糙的统计一次中等复杂度的AI生成任务平均要经过2.8轮修改才能进入合并。每一轮Review大概耗时40分钟到1小时。也就是说一个看起来只花了5分钟写出来的接口实际团队付出的总工时接近4个小时。这个代价曲线和物理世界的工程问题一模一样——水电管线埋好之后你想再挪一个插座麻烦程度远高于最初布线的时候。代码也是生成阶段不堵住问题后面每一层都会加倍放大。1.2 生成即规范的三层理解我后来把生成即规范拆成三层来落地每一层解决一个具体问题。第一层是产出符合规范。AI生成出来的代码在风格、结构、命名、异常处理这些维度上直接满足团队约定。不是生成之后让人去对规范清单而是生成的那一刻就已经是规范的样子。第二层是规范不依赖人的记忆。这个很关键。团队里总有新人Review的人也总有疏忽的时候。规范如果只存在于某个文档或者某个人的脑子里那它就是不可靠的。所以在我们的生成器里规范是固化在模板和规则里的AI只是在这个约束空间里发挥而不是自由发挥之后等人纠偏。第三层是生成过程可追溯。你让AI生成了一段代码这段代码是照着哪个模板来的、为什么用了这个模式、哪些规则被触发过、哪些规则被显式豁免了这些东西要能查。因为技术债最大的来源就是不知道当初为什么这么写。如果生成过程本身留下痕迹后来的人接手代码的时候就能顺着线索理解设计意图这就从源头上把注释债和文档债也堵住了一部分。2. 技术债在AI生成代码里的三种典型形态谈到源头杜绝技术债你得先知道AI生成的代码到底会留下哪几种债。我观察了很长时间总结出三种最典型、也最隐蔽的形态。2.1 命名垃圾债data、result、item 满天飞AI生成变量名特别喜欢用泛化词。你让它实现一个订单状态流转逻辑它能给你写出OrderService里全是data、result、tempList、item这种名字。单个看、当场看好像没什么问题但一个月后回头维护就抓瞎了——data到底是订单快照还是支付回调result是校验结果还是保存结果读代码的人必须沿着调用链去猜猜错了就改错。这种债我称之为命名垃圾债。它不会让系统立刻崩溃但它会持续消耗每一个后来看这段代码的人的心智。AI为什么爱这么干因为大模型训练数据里充斥着各类含糊命名AI没有这个名字要被团队其他人看一年的意识。所以这件事不能靠AI自觉得靠生成器在模板里强制约定命名模式业务字段用业务词典的术语局部变量用意图性命名禁止裸泛化词。2.2 结构债贪吃蛇式方法体第二种形态更难看出来因为它不是一眼能扫到的错误而是结构上的问题。AI生成代码的时候非常偏爱把所有逻辑塞进一个方法的做法。你给它一个需求它噼里啪啦在一个方法里完成了入参解析、权限校验、状态机判断、缓存读写、仓储调用、异常转换、结果组装。方法长度动辄两三百行。圈复杂度直线飙升。这种结构被AI拉出来的时候缺点特别隐蔽——它能跑通单测还能过。但一旦需求变了你想在状态机判断那里插入一个新状态你会发现改动会影响方法里的其他六块逻辑。你不得不先花半天时间把方法拆开理解每一块的边界然后才能下手。这就像一棵树AI把所有枝桠都长在同一个主干上看着茂盛风一来全晃。我们在生成器里对方法体长度、嵌套深度、圈复杂度做了硬约束超标的生成结果直接判定不合格强制AI拆分。2.3 契约债接口参数与返回值像没有合同一样第三种形态是最让人头疼的因为它直接影响系统间的协同。AI生成的接口方法参数经常不加合法性校验返回值那边也经常不明确说明会不会是空。你调用一个loadUserProfile(id)它可能返回null可能返回空对象可能抛异常——但这三种情况在签名上完全看不出来。调用方为了安全只好写一堆防御式代码先判id为空、再判返回为null、再包try-catch。每一个调用方都堆一份代码量膨胀逻辑分散真正的业务逻辑反而被淹没了。这就是契约债。它最可怕的地方在于它会传染。一段没有契约约束的代码被三个服务引用三处都会长出防御逻辑。AI生成代码的时候特别容易忽视这一点因为它擅长写出能编译通过的代码但并不擅长定义双方都满意的契约。所以我们的生成器在模板层就把契约固化参数必须带约束注解、返回值必须明确标注可空性、异常类型必须在文档块中声明。AI生成的代码如果漏了这些直接不通过生成校验。3. 规则层设计把规范变成生成约束如果规范只是写在文档里的建议那AI生成时根本不会理它。要让生成即规范真正落地必须把规范变成生成流程里的硬约束。这一节讲规则层的具体设计。3.1 模板资产库把团队共识变成生成骨架我们做的第一件事是搭建一个模板资产库。核心逻辑很简单团队里已经有大量被验证过的代码模式比如统一返回体ResultT、统一异常处理器、分页请求模型、幂等校验工具。这些是团队共识但以前共识只在人的脑子里现在要把它们做成AI生成时使用的骨架模板。以REST接口为例模板骨架里预埋了统一的Controller层结构参数校验、权限注解、日志埋点、异常转换各就各位。服务层接口与实现分离接口定义契约实现类只负责业务编排。仓储层方法命名规范化findById、updateByXxx、existsByXxx这类命名由模板强制约束。状态机、策略模式等场景的骨架代码AI只需填充少量业务规则不需要自己重新发明结构。这个步骤的意义在于AI不是从一张白纸开始自由发挥而是从一个已经合格的骨架上开始填充血肉。骨架决定了风格的底线AI再怎么写风格都不会漂移到规范之外。3.2 生成后的四道自动闸门模板保证了风格的基线但AI在填充业务逻辑时还是可能自作主张。所以我们又建了四道自动闸门每次生成之后自动跑。第一道AST结构校验。用语法树级别的检查器直接分析生成代码的结构特征。查命名规范是否匹配团队词表、方法长度是否超标、嵌套层级是否过深、类职责是否臃肿。AST校验的好处是不需要编译速度快生成后几秒内就能给出结果AI可以根据反馈立即自我修正。第二道静态规则扫描。接入团队已有的静态分析体系把SonarQube、ESLint、Checkstyle那一层的规则同步到生成校验里。两道闸门的分工是AST查结构风格静态扫描查潜在缺陷比如空指针风险、资源未关闭、垃圾回收隐患。第三道编译与最小单测。AI生成的代码必须真实编译通过同时生成器自动补一个最小冒烟测试验证主链路能跑通。这一步直接过滤掉一大批看起来对、跑起来挂的生成结果。第四道风格漂移比对。我们维护了一个历史代码样本库每次生成后把新代码与同模块的历史代码做特征比对注释密度、方法平均长度、命名分布、异常处理覆盖比。如果风格特征漂移超过阈值生成器会提示与历史代码风格偏离过大建议参考XX模板重写。这道闸门特别有用它防的不是绝对的对错而是模块内部的一致性——同一个模块里代码风格天南地北这本身就是技术债。四道闸门全部通过AI生成的代码才算合格才会被提交。这个流程跑下来之后我们的Review打回率从四成降到了一成以下。最关键的变化是Review过程从逐行纠错变成了看业务逻辑有没有漏洞工作效率提升非常明显。4. 易调测的落地可观测性和测试同步生成4.1 易调测在生成器里具体指什么很多代码生成器只关注能不能跑不太关注出了问题好不好查。但真实业务里代码写出来只是开始后面还有联调、测试、线上排查。一套代码如果只在刚生成的那一刻觉得满意上线出问题时却查不出头绪那维护成本照样爆炸。我在设计这个生成器时把易调测当成一等公民来对待。易调测至少包含三个层次第一代码运行时的状态可观测也就是有日志、有trace、有关键指标第二代码的行为可验证也就是有单测、有边界用例第三问题出现时能快速定位到具体模块和方法也就是日志里有上下文、异常里有线索。第三十六弹的版本里我把这三层全部做到了生成流程内部。4.2 调试辅助信息的自动埋点先讲日志和trace。生成器的模板里预置了埋点能力每个关键业务方法自动生成日志语句内容包括类名、方法名、关键入参、耗时。比如一个订单状态流转方法生成的日志大致是LOGGER.info([OrderFlowService.handleStateChange] orderId{}, from{}, to{}, elapsed{}ms, orderId, fromState, toState, costTime);这段日志不是AI临场发挥写的而是模板里写死的规则关键操作必须记录入参和出参状态变更必须记录前后值。我们做过统计线上排查问题时70%的Case靠某笔订单从A状态流转到B状态这个动作没有被记录就找到了根因。调测成本降下来很大程度上是靠这种看似不起眼的埋点。4.3 单测同步生成让代码与测试一起出生另外一个重点是测试同步生成。以前AI只生成生产代码测试代码要人后补——后补测试这件事本身就很容易被拖延。现在生成器会在生产代码通过四道闸门之后自动生成配套的最小单测集逻辑是这样的从模板中提取方法签名的入参类型自动构造正常值、边界值、非法值。从静态规则扫描结果里提取风险点比如可能返回null的路径自动补空指针回归测试。从异常处理块识别可能抛出的异常类型自动补异常路径的断言。对有外部依赖的方法自动识别依赖类型并生成mock桩。以我之前做的一个订单状态机服务为例。生成器产出了生产代码和一个二十个Case的小规模测试集覆盖了从待支付到已支付的正常流转、重复流转被拒绝、非法状态跳转报错、并发流转时状态冲突、仓储返回空时的兜底逻辑。这套测试集不是AI随便编的而是根据状态机的状态迁移表和校验规则推导出来的。它可能不是完整的全量测试但它保证了最关键的主链路和最容易出错的边界路径都有验证。这比代码写完了、测试以后再说的思路健康太多了。4.4 生成窗口里的即时修改调测友好还有一个容易被忽略的点修改闭环。AI生成代码后我看了一眼AST校验报告提示说某个方法缺少对参数非空的约束静态扫描又提示说路径上有空的返回值风险。如果是在IDE里我得切出去打开文件定位那一行然后亲手改。但在生成器里我直接在生成结果的反馈区把这个消息丢回对话里根据AST校验请给saveOrder方法补充参数非空约束根据静态扫描请修复xxx路径的空返回值风险。AI马上应用修改然后又跑一遍四道闸门。这个闭环的核心速度优势在于人不需要在大量代码里找一小处问题生成器直接告诉你问题在哪AI直接改。调测这件事参数和边界的确定性越高后面的工作就越轻松。5. 第三十六弹的新尝试任务分级路由与提示词收敛前几弹讲的基本都是生成器的规则引擎和模板体系到了第三十六弹这个节点我花了比较多精力做两件新事一是按任务复杂度把生成请求路由到不同的模型二是把团队规范彻底收敛进提示词上下文。5.1 按任务复杂度路由模型别让高射炮打蚊子AI编程工具包括Codex这类付费AI编程软件圈子里的一个现实情况是不同模型对同一段提示词的产出质量、稳定性和成本差别很大。不区分任务难度一律用最强模型成本高不说某些简单任务还容易出现杀鸡用牛刀反而过度设计的情况——一个获取列表数据的接口AI给你抽象出三层继承两个工厂一个策略模式看着很酷维护起来只想哭。我在生成器里加了一层任务分级路由。判断标准有三个接口数量、依赖深度、业务规则复杂度。接口数量看一次生成涉及几个对外入口依赖深度看有没有跨服务调用、有没有外部系统交互业务规则复杂度看有没有状态机、计算逻辑、权限分支。按这三项打分简单任务走轻量模型生成快、成本低、不会过度设计复杂任务走强模型上下文窗口大、逻辑推理稳、风格更贴近团队模板。实测下来生成质量几乎没有下降但单次生成的模型成本降了大概四成响应速度也快了不少。5.2 提示词收敛把规范写进生成上下文第二件事是提示词优化。第五弹的时候我就强调过提示词对输出质量的影响但这一弹做得更彻底。以前是把需求描述交给AI规范什么的靠模板隐式约束。现在生成器每次发请求之前会先拼装一段项目级规范上下文团队代码风格、禁忌清单、本模块的技术栈版本、线上排查需要的日志埋点要求、最近三个同类任务的生成经验。这段规范上下文不是写死的是从项目配置里动态读取的。不同项目、不同模块的规范侧重点不同生成的代码就不会千篇一律。这里有个踩过的坑要提醒一下提示词收敛和模板约束不能互相替代。模板决定的是骨架和结构提示词上下文决定的是AI填空时的偏好。如果你只靠模板AI还是会按它自己的惯性填业务逻辑可能跑偏。如果你只靠提示词AI可能写出风格正确但结构涣散的代码。两者必须配合模板是钢筋提示词上下文是水泥规则层是监理。少了一样结果都要返工。最后一件事这套玩法最值钱的不是代码是规范的长尾效应上文聊的都是怎么让AI生成规范的代码但我在实际落地里最深的一个感受是这套玩法的长期价值其实集中在规范本身的长尾效应上——它让团队的保守经验变成了一种可以自动传承的资产。以前代码规范存在文档里文档会过时新人会忘记翻。现在规范嵌在生成器的模板、规则、提示词上下文里AI每次生成的每一行代码都在替你执行这些经验。规范不再是一份没人看的文件而是一个能持续输出合格代码的管线。如果你也想做类似的事我的建议是先别急着追求大而全。先挑团队里最痛的一种代码类型比如REST接口或者数据访问层做好模板建立四道闸门里最基本的编译和AST校验跑通之后再加静态扫描和风格比对。一点一点补不要想着一步到位。等这套流程稳定了你再回头看那些被AI代码折磨的夜晚就会觉得这一套规则引擎和模板资产库花的时间全都值回来了。这一弹就分享到这下一弹我打算拆解一下任务分级路由里具体的评分维度和阈值设计有兴趣的可以先对照自己项目里最耗时的生成任务琢磨一下。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进