接手过遗留系统重构的人应该都有感触真正让人头疼的往往不是手写代码而是那些由代码生成器批量产出的“标准化”代码。它们长得一模一样、注释齐全、命名规范但跑起来性能平平改起来牵一发动全身。这些年我做过不少代码生成相关的项目从早期基于模板的代码生成器到后来引入AI辅助生成踩过的坑不少也沉淀出了一套行之有效的“代码生成优化技术”方法论。这篇文章就围绕这个主题展开讨论如何让生成的代码从“能跑”进化到“能扛事”——性能更好、逻辑更稳、维护成本更低。先交代一下背景也方便不同基础的读者定位。代码生成并不是新鲜概念早在上世纪就有各种代码生成器近年AI辅助编程工具更是把生成代码的普及度推到了新高度。但无论用什么方式生成代码都会面临三个绕不开的问题代码质量参差、运行时性能不可控、长期维护困难。我接下来分享的内容重点不是某个具体工具的使用教程而是结合我在几个内部项目中的实操经验讲清楚生成代码的优化思路与落地手段适合正在使用或计划引入代码生成的团队参考。1. 先搞明白你要优化的代码是哪一种在动手优化之前必须先甄别生成代码的类型。不同类型的代码优化方向完全不同用错手段等于白费力气。我在实际工作中会把生成代码分为三大类每一类的优化重心都不同。1.1 模板引擎类代码问题集中在“结构重复”最传统的一类生成代码是使用模板引擎常见的有代码模板工具、或自研的代码生成插件根据数据模型生成的基础CRUD代码、接口定义代码、数据库访问层代码等。这类代码的特点是结构高度统一生成一次之后基本不再修改。这类代码的核心问题在于生成时使用的是通用模板所以对具体业务场景毫无感知。在某个订单管理系统中代码生成器为所有数据表生成了等价的查询方法无论这张表有多大、查询频率有多高生成的SQL都没有分页、没有索引提示、没有只读最优处理。这种情况优化起来反而好办针对高频模块重写定制模板让模板“懂业务”。1.2 AI辅助生成代码问题集中在“逻辑正确性不可控”随着大语言模型辅助编程的普及越来越多的团队把AI当作主要代码来源之一。AI辅助生成的代码优势是“思路广”劣势是“细节糙”。同样的功能需求AI给出的方案经常带着不必要的间接层、冗余防御逻辑甚至过时的API用法。这类代码的优化不能靠手改一遍必须建立“生成-审查-固化”的闭环把优化经验沉淀为新的提示词约束或后处理脚本。我见过不少团队把AI生成的代码直接合入主干分支结果运行时出现性能问题定位半天才发现是AI在循环里调用了一个重量级方法。这种问题靠人工排查效率太低必须前置拦截。1.3 元编程/动态生成代码问题集中在“反射与动态分派开销”还有一类生成代码是在运行时动态生成或加载的典型如反射生成代理类、表达式树拼接、IL动态编译等。这类代码的性能优化空间最大因为动态生成本身有额外开销但如果生成得得当也能达到甚至超过手工静态代码的性能。比如把运行时的反射调用优化为编译期表达式树虽然生成代码的复杂度上去了但调用性能提升明显。这一类的优化思路核心是“能静态就静态必须动态就缓存能复用就复用”。早年我在某个内部框架里用反射动态调用方法压测时发现这块占了20%以上的开销后来改成启动时生成一次表达式树运行时开销几乎归零。这就是典型的通过优化生成技术本身获得性能收益的案例。1.4 三类代码优化策略对照为方便理解我把这三类代码的特点与优化重心整理成一张表生成代码类型典型来源常见问题首要优化方向模板引擎类代码生成器、脚手架结构重复、缺乏业务感知定制模板、收敛通用逻辑AI辅助生成类AI编程助手、大模型对话逻辑冗余、API误用、不可控提示词约束、自动化检查、审查沉淀元编程/动态生成类反射代理、表达式树、IL生成动态分派开销、缓存缺失静态化替代、表达式树、结果缓存把类型分清楚之后再去谈具体的优化手段才有针对性。下面我按项目落地中最常处理的前两类为主展开动态生成类的技巧会穿插在相关章节中讲。2. 模板生成代码的优化实战从“能用”到“好用”模板引擎类生成代码的优化是我这些年做得最多的一个方向。表面上它是“改模板”的功夫但真正的优化点往往藏在模板的结构设计和生成后处理里。2.1 模板设计的第一原则让生成物“扁平”很多人设计代码生成模板时喜欢把通用的工具方法集中放在基类里生成的子类继承基类来复用。这个思路看起来优雅但副作用很大基类膨胀、职责模糊、子类之间被隐式绑定。我见过一个内部项目生成代码上百个类全继承了同一个基类基类里既有数据库访问、又有缓存逻辑、还有日志埋点。结果任何一个基类改动整个系统都要重新回归测试。后来我把模板改成了“扁平化生成”风格每个生成类尽量自包含公共逻辑抽取成独立服务类通过组合而不是继承来复用。这样虽然单次生成的代码量变多了但每个类的职责边界清晰改动影响范围小长期维护成本大幅下降。这是一个牺牲“短期代码量”换取“长期可维护性”的典型优化。2.2 生成后处理用脚本批量修正模板的“笨拙”模板代码的另一个通病是生成结果中存在大量可优化但模板没优化的细节。举个例子生成的数据访问代码里每条查询都先做个校验、再拼SQL这种防御式代码本身没错但在极端高并发场景下每多一次校验就多一分耗时。我的做法是在模板生成之后增加一道“后处理脚本”环节。脚本的工作包括删除明显冗余的null检查前提是业务已经保证非空、将重复调用的属性提取为局部变量、把多次出现的常量替换为枚举定义等。这一步看起来是“缝缝补补”但实际效果非常可观。有个报表类模块光是通过后处理脚本删除了生成代码中约30%的无效分支整体响应时间就下降了12%左右。2.3 参数化模板让业务信息直接注入生成结果模板优化中比较容易见效也经常被忽略的一点是模板的“参数化程度”。初期做代码生成器时很多人为了省事把模板中的参数只做成数据表字段名和实体类名两层。但真实业务需要的参数远不止这一层。具体来说我在模板优化中会往模板里补充这些业务参数模块所属领域影响命名空间和包名。读写比例影响默认生成的查询方法是否需要分页、是否需要缓存标记。数据敏感级别影响是否自动生成审计字段和脱敏处理逻辑。并发预期影响生成的代码是否默认带乐观锁或分布式锁骨架。把这些参数引入模板之后生成代码从一开始就带上了业务基因而不是纯粹的机械映射。这一步优化做得好后续的人工修正量会显著减少。2.4 模板版本治理生成代码最容易被忽略的“债”最后要提醒的是模板本身也是需要维护的代码。我见过很多团队生成器模板改了几轮但底层老模块的生成代码还停留在旧模板逻辑上。一旦模板出现安全性或性能更新老代码完全跟不上。建议的做法是把所有模板纳入版本管理并在生成代码的文件头自动写入“生成器版本号模板版本号生成时间”。后续做批量升级时直接按版本号筛选所有旧版生成文件重新生成或增量修补。这是一个代码生成优化技术里偏“管理”的手段但往往比技术优化更能避免线上事故。3. AI辅助生成代码的优化链路把“生成”变成“受控生成”AI辅助编程普及之后代码生成优化的重心从“模板怎么写”转移到了“提示词怎么给、生成结果怎么验收”。这一节展开我实际使用的优化链路。3.1 提示词设计把隐性要求写进约束很多开发者让AI生成代码时会说“帮我写一个用户列表接口”这太模糊了。AI给出的代码往往是教科书式示例三层架构、完整异常处理、甚至附带单元测试看起来很专业实则存在多个性能隐患。我经过多次实验总结了一套可复用的“生成约束模板”。在向AI描述需求时必须写清以下要素使用什么语言和框架版本禁止使用哪些重量级特性对关键路径的性能指标要求要求避免过度设计期望代码的复杂度和行数上限。比如我常这样描述请生成一个批量更新订单状态的函数语言Java 17框架Spring Boot 3.x禁止在循环中执行数据库操作要求单次批量提交函数行数不超过40行不要额外抽象接口除非有第二个实现类。这样约束下达后生成的代码“跑偏”概率显著下降。实际经验是提示词中每增加一条明确的性能或复杂度约束生成代码需要的返工次数平均能减少一半以上。3.2 生成结果的三道检查闸门AI生成代码不可直接信任这一点再怎么强调都不为过。我所在的某个内部团队定过一条规矩“AI代码必须过三道闸门才能合入主干”。这三道闸门分别是静态规则扫描、专属性能断言测试、人工代码评审。静态规则扫描执行的是常见反模式检测比如发现循环内调用远程接口、发现同步阻塞调用潜在线程池耗尽风险、发现大对象循环拷贝等。这个步骤能把大部分“看着对其实不对”的问题拦截在早期。性能断言测试则是针对关键模块生成的压测用例直接断言响应时间不能越过阈值。最后的人工评审不是全面重读而是让有经验的开发者重点审查“AI容易犯”的那几类错误如事务范围过大、资源未关闭、不正确的缓存用法等。3.3 审查记录的二次沉淀“优化飞轮”优化AI生成代码最有价值的工作是把一次次的评审意见沉淀成可复用的规则。具体操作是每次评审中发现的典型问题经过提炼后加入新的提示词约束、静态检测规则或代码生成器的后处理逻辑中。举个例子有段时间团队发现AI生成的多个服务方法都带有不必要的synchronized关键字。第一次遇到时是靠评审人工指出的但接着又出现了好几例。后来我把“不随意加同步锁除非明确存在多线程竞争”写进提示词约束同时在代码扫描规则里增加对应的检测项。此后这类问题基本绝迹。这就是我所说的“优化飞轮”AI生成代码 → 人工发现缺陷 → 沉淀规则 → 反馈到生成源头。每一轮循环都让后续生成代码的质量更高。这个思路和传统模板优化的“改模板”本质上是相通的只是AI场景下规则沉淀的载体变成了提示词和检测脚本。3.4 不要忽略“上下文”给AI一个完整的局部视图AI生成代码出问题很多时候不是因为模型能力不行而是上下文不够。有一次需要生成一个订单导出功能开发者只告诉AI“把订单数据导出成Excel”AI生成的代码里自定义了一套复杂的内存分页逻辑完全没有复用项目里已有的导出工具类。原因很简单AI不知道项目里有这个工具类。我的优化实践是在发送代码生成请求前先整理出与任务相关的现有接口签名、核心工具类位置、历史相似代码片段作为上下文一并提供给AI。这样生成出来的代码会更贴合现有系统架构而不是“凭空造轮子”。这个细节对生成代码的最终优化效果影响极大但往往最容易被忽略。4. 生成代码的运行时性能诊断用数据说话前面讲的是生成阶段的优化但生成的代码上线之后性能到底行不行靠“感觉”是不靠谱的。这一节分享我在诊断生成代码性能瓶颈时的具体手段以及几个高频问题的处理。4.1 通过压测先暴露“最坏情况”凡是涉及生成代码的核心模块我都会在测试环境做一轮相对严苛的压测再放行。注意这里的压测不是简单测吞吐量而是专门设计“极端输入比例”并发峰值、批量参数过大、部分数据倾斜等。生成代码有一个共性弱点——它们在“常规输入”下表现良好但边界条件处理得不够细腻。举个例子某个列表接口的生成代码在分页查询时使用了“先count再list”的两步查询单页数据量不大时毫无压力但压测模拟了单表500万数据、深分页场景之后count查询成了瓶颈。后来优化为覆盖索引count和游标分页性能才稳定下来。4.2 定位热点从“调用树”看生成代码的浪费拿到压测结果后我会先上链路分析工具抓调用树看看生成的代码到底把时间花在哪了。生成代码最容易出现的性能浪费集中在三处属性复制代码中大量使用反射工具类做深拷贝而非手写浅拷贝或使用编译期映射。重复查询同一数据因为生成的服务方法各自独立缺少方法间缓存设计。日志埋点过多且是同步输出在高并发下拖慢主链路。这些浪费有一个共同特征生成代码往往会为了“通用性”牺牲“效率”。定位到具体位置后优化方式通常有两种要么修改生成模板、要么对这些热点段做人工重写并固化到例外清单中。我的经验是少部分核心热点值得人工重写大部分非热点用模板修正即可不要过度优化。4.3 缓存的“生成式”落地针对生成代码的查询重复问题一个有效的优化模式是“一键缓存骨架”。我在代码生成器中增加了一个配置项为指定高频查询方法自动生成带有缓存注解的版本同时生成对应的缓存更新逻辑即写操作后同步淘汰或更新缓存。这件事如果是生成器自动完成会比人工后期加缓存高效得多也避免缓存逻辑散落各处。不过要注意自动生成的缓存代码需要额外配置有效期和失效策略。缓存有效期设置太短压力反而增大设置太长则数据一致性风险上升。在我落地的项目里把缓存有效期设为5分钟配合修改操作的主动缓存淘汰线上数据显示缓存命中率稳定在90%以上接口响应时间降幅显著。4.4 与手写代码的对比“体检”在组织内部技术分享时我常建议团队做一个“生成代码 vs 手写代码”的对照实验选定同一业务模块一半功能由生成代码实现一半由资深开发者手写。然后在相同压测模型下对比性能、代码体积和缺陷密度。这个实验不是用来分高下的而是用来校准生成参数的。几次对比下来我们找到了生成代码“性价比最高”的适用范围结构规整、逻辑简单、重复度高的模块适合全量生成而核心复杂领域、性能极其敏感、异常分支繁多的模块更适合人工主导、生成代码作参考。这个认知直接影响了我后续优化生成策略的方向避免在错误的方向上花大力气。5. 优化经验的长期固化从个人技巧到团队能力代码生成优化不可能靠一次性的人工修补收尾。前面提到过“优化飞轮”的做法这里再展开讲一下如何把个人层面的优化经验固化为团队可复用的能力。5.1 建立“生成代码红线清单”我在团队里推动建立了一份“生成代码红线清单”所有生成代码合入主干前都必须对照检查。红线的条目数量不多但每一条都是真实事故或性能问题换来的教训。大致包括不允许在循环内执行同步数据库访问或远程调用。不允许生成重量级深拷贝逻辑除非业务明确需要。不允许同步输出高频日志核心链路的日志必须异步化。不允许无差别重试必须有明确的幂等策略支撑。不允许动态SQL字符串拼接除非经过安全审计。这份清单不是一成不变的每次线上事故复盘或性能专项分析后发现新的共性风险就及时增补。长期坚持下来生成代码的“踩坑率”被大幅压低审查时间也随之缩短。5.2 生成代码的可观测性注入代码生成时顺手注入可观测性能力是性价比极高的优化手段。具体做法是在生成的服务方法入口自动埋入计数指标、耗时统计、调用方标识在生成的数据库访问层自动记录慢查询日志标识。这么做的意义在于后续做性能优化时不需要推翻代码去加监控所有生成模块的运行时状态都“看得见”。比如有一次排查对方的批量导入接口耗时异常就是因为生成代码里自动带了分段耗时统计快速定位到耗时不均匀的分段进而发现是某段数据量分布不均导致的。如果没有生成期的可观测性注入这种问题排查可能要耗费数小时甚至数天。5.3 模板代码的“回归防线”前文提到模板版本治理这里补充配套的回归防线为生成的代码配一批“模板基准测试”。也就是每次模板或生成器升级后自动生成同一批样例模块跑一次预置的功能与性能基线用例再与上一版本的基线结果做对比。如果新模板生成的代码性能比旧版有明显回退必须定位到具体变化点才能发布。这个机制保证了模板优化不会“按下葫芦浮起瓢”——今天优化了查询性能明天却把写入链路的资源释放弄坏了这种问题在模板迭代中真实发生过多次。5.4 内部分享与共建让优化经验流动起来最后想说的是代码生成优化技术本质上是一门“工程实践”而非“学术理论”。它需要团队内持续交流和迭代。我通常会在每个迭代周期做一次小范围分享内容就是一个主题这个周期里生成代码暴露了哪些典型问题、我们修改了哪些生成规则、效果如何量化。有意思的是很多优化建议是从使用者端反向反馈过来的。一线开发者在使用生成代码时会累积大量“使着别扭”的体感——某项生成代码总要多改几刀才能用、某个生成方法从来用不到却每次都生成。这些反馈汇总后会转化为生成器配置项的调整甚至推动模板的全面改版。我曾经主导过一个改造把某个通用模板从原来每个表生成20多个方法缩减到默认只生成7个核心方法其余方法按需配置生成。表面上看生成能力“变弱”了实际用起来反而顺手很多因为无用代码减少了代码阅读和维护的负担也下来了。这个改动就是源于一线反馈和数据分析的推动。回头看这些年做代码生成优化技术的经历最大的体会就是生成代码不能只生成不对症。当下游模块为了“补丁式修复”而疲于奔命时上游生成规则的每一次小优化都能在下游省下成倍的时间。把优化从“一次性的治理”转变成“持续迭代的规则沉淀”才是这笔投入能够持续产生价值的关键。未来不管代码生成技术本身怎么演变这套“生成-诊断-沉淀-反馈”的闭环思路应该都不会过时。