ARTICLE DETAIL

建站实战干货

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

代码审查与微重构:一套Prompt让AI给出可落地的改进建议

2026/9/8 21:52:01 拓冰建站 浏览量
代码审查与微重构:一套Prompt让AI给出可落地的改进建议 干几年开发谁还没在代码审查里被怼过几回。前阵子我搭了个专门的“代码审查微重构prompt”让大模型在审查代码的时候顺手给出可落地的微重构建议而不是空泛地说“这代码不够优雅”。用下来确实省了不少事今天把这套prompt的设计思路、完整模板、实操过程和踩坑记录整理出来想抄作业的直接拉到最后拿模板想搞懂背后逻辑的可以从头往下看。先说清楚这个prompt到底解决什么问题过去我们拿AI做代码审查经常得到一堆正确的废话——什么“建议添加注释”“建议提取方法”听着都对但看完不知道从哪下手。而真正有价值的审查应该包含两部分一是明确指出问题在哪、严重程度多高二是给出具体的、安全的、局部的修改方案也就是微重构。所谓微重构指的是不改动对外行为、单次改动范围控制在小函数几十行以内、风险低到可以立刻改完立刻合入的那种改进比如消除魔法数字、拆分过长的if条件、抽离重复片段、补充缺失的类型标注。这套prompt就是干这个用的。适合三类人一是自己写代码想快速过一遍质量的个人开发者二是团队里负责review MR/PR、想提高审查效率的工程师三是刚接触代码审查的小白想学习一段代码里到底有哪些典型的坏味道。1. 为什么要把“代码审查”和“微重构”放进同一个prompt先说结论审查和重构本质上是同一件事的两个视角。审查是在找“哪里有问题”重构是在解决“这些问题怎么改”。如果分开做先让AI审查一遍再拿着审查结果重新开一轮对话让AI给重构方案中间至少损失两样东西上下文连贯性和问题与方案的对应关系。1.1 审查和重构原本是两件事传统工作流里代码审查是reviewer的活重构是开发者的活中间隔着一次沟通成本。reviewer说“这个函数太长建议拆分”开发者要自己去理解哪段逻辑可以抽出来、抽出后有没有副作用。这个来回在团队协作里往往要耗费好几轮。而AI没有这个沟通成本只要你把上下文一次性给它它天然就能从“找问题”直接推进到“给方案”。问题只在于大多数人的prompt没有引导它这样做。我见过太多开发者给AI发一段代码就写一句“帮我审查一下这段代码”AI确实会执行审查但输出内容取决于模型性格有的偏保守回一句“代码整体质量不错”就结束了有的偏激进列出一堆重构建议但全是“考虑使用抽象类封装”这种降维打击完全没法直接落地。问题不在AI在prompt缺少对输出颗粒度和行为边界的约束。而把这些约束写清楚正是“审查微重构”一体化prompt的核心价值。1.2 拆开做容易踩的两个坑第一个坑是上下文断裂。代码审查是有上下文依赖的——这里为什么用字典而不是对象、那个异常为什么不处理、这个函数为什么这么命名。如果你把审查和重构拆成两轮对话第一轮的结论第二轮看不到了AI在给重构建议时很可能走样。尤其在ChatGPT这种有对话上下文的场景里拆开用不仅多花时间还容易让AI误解“这个被标出来的问题具体指哪一行”。第二个坑是结论与动作脱节。单做审查时AI倾向于说“第X行有魔法数字”但不会告诉你该把这个数字提成什么常量、放在哪个位置、命名是什么。等到你追问它给的方案又可能因为缺少上下文而产生偏差。反过来单做重构时AI根本不审查直接改代码改完你看不懂它为什么要这样改风险极高。把两者合并后AI需要先摆事实问题清单再给方案重构建议这个顺序本身就在强迫它给出有依据的建议。1.3 一个prompt同时干的优势合并以后最明显的变化是输出结构稳定了。因为我要求AI严格按“问题清单→重建议→示例代码”的顺序输出它的思考过程也被这个结构牵引着走。实测下来代码里的典型坏味道漏检率明显下降而且每个问题后面都跟着可操作的重建议review效率提高了不止一倍。再有就是“微”这个字起作用了。加了“不允许调整架构、不允许改变对外行为、不允许引入新依赖”的约束之后AI给出的建议明显更收敛不再是那种“建议改用微服务”的宏观话术而是老老实实告诉你“把这个条件判断抽成一个私有方法命名叫xxx”。这才是能直接落地的建议。2. 这个prompt到底该怎么设计很多人拿现成的prompt用效果不好就怪AI不行。实际上prompt设计是有方法论的尤其这种需要强结构和强约束的工程类prompt每一段都有它的作用。2.1 先说清楚角色和边界角色设定写的是“资深代码评审工程师”。这句话不是客套而是在告诉模型调用哪部分知识。大模型训练时见过海量代码评审案例角色设定越具体越能激活对应的专家知识输出就越像资深工程师。我自己试过“你是一个Python开发者”和“你是一位资深代码评审工程师擅长在小步重构中保持行为不变”两种角色后者的建议明显更贴合“先保证不炸再谈优化”的工程审美。边界则靠约束条款来实现。最重要的三个约束我在模板里都写死了不改变输入输出语义不删减功能——防止AI自作主张砍掉边界判断不引入新的第三方依赖——防止AI建议你用一堆你没装过的库提示意图不明确时给出两种合理推演——防止AI臆测需求直接改错。边界描述得越清晰AI的自由发挥空间就越小。很多人用prompt翻车就是因为角色给了、任务说了但边界没划AI一顿操作猛如虎最后代码跑不起来了。2.2 输出格式才是prompt的灵魂做工程向prompt我一直觉得输出格式比角色设定还重要。因为工程场景里你拿到结果后第一时间要做的是“定位”而非“欣赏”。如果AI给你输出一大段散文式的分析光找问题点就要翻半天效率反而更低。所以我在prompt里强制规定了三级结构先是【问题清单】每条问题占一行用“严重级别|问题描述|对应位置”的方式呈现方便快速扫视和排序然后是【微重构建议】强调“一句话说明怎么改”逼AI把建议压缩成可执行的动作最后是【示例代码】用短代码块展示改动前后对比让人一眼看懂变化。这个格式还解决了一个隐性需求reviewer在处理一大批代码时真正需要的是“先看问题分布再决定处理顺序”而不是通读一遍分析。三级结构正好匹配这个工作习惯高严重级别的问题先处理低严重级别的批量处理异常高效。2.3 约束条件与安全兜底代码审查场景里的安全兜底和别的场景不太一样。常规内容生成安全是指内容合规代码场景里安全则是指“改出来的代码不能比原来更烂”。AI重构代码最常见的事故有两种一是为了消除重复把逻辑抽成过度抽象的函数结果调用方反而看不懂了二是为了“更专业”引入设计模式导致代码膨胀、性能下降。针对这两种情况我会在prompt里明确要求“微重构只做必要且明显有益的动作不做过度设计”。还有一个容易被忽略的点处理同一段代码时AI对“什么算问题”的判断极不稳定。有时它把一小段不规范命名当成重大问题有时它对真正的空指针风险视而不见。解决办法是给问题定级标准。我在模板里要求“区分高、中、低三个级别高严重级别必须同时给出潜在负面影响说明”这样既给了AI一个判断依据又让输出结果具备可筛选性。3. 可直接抄作业的prompt与一次完整实操下面这段prompt模板是基于我自己的实践整理出来的你拿过去可以直接用。如果你的代码场景有特殊性在对应字段里改就行。模型建议选用GPT-4级别的推理能力强一些更老实的模型可能会忽略部分约束。3.1 完整prompt模板你是一位资深代码评审工程师擅长在保持代码行为不变的前提下做小步、安全的微重构。 请完成以下任务 1. 阅读我提供的代码片段指出其中影响可读性、可维护性、稳定性和性能的问题 2. 对每个问题给出“微重构建议”只允许做小范围、低风险的改进 3. 为需要修改的部分给出改动前后对比的示例代码。 输出格式必须严格遵循 【问题清单】 编号. 严重级别(高/中/低) | 问题描述 | 对应位置 → 微重构建议一句话说明怎么改 → 示例用短代码块展示改动前后对比 【改进后完整代码】 仅在改动点较多时输出 约束条件 - 不改变输入/输出语义不删减功能 - 不引入新的第三方依赖 - 不允许调整整体架构不做过度设计 - 如果当前代码无法明确意图用注释标出并给出两种合理推演 - 如果代码本身没有明显问题请直接说明“未发现明显问题”并给出2条可选优化方向 - 只针对你看到的内容做审查不要编造上下文 - 对于高严重级别的问题需额外说明潜在的负面影响。模板里的几个字段说一下设计意图。“严重级别”字段是为了逼AI对问题进行分类避免所有问题一股脑平铺“对应位置”字段是为了方便你回到原代码里快速定位减少搜索成本“仅在改动点较多时输出完整代码”是为了控制输出长度。最后一个“对于高严重级别的问题需额外说明潜在的负面影响”是我在一次安全事故后加上的当时AI建议移除一个看似多余的try-except结果那是处理用户权限异常的关键逻辑。3.2 实操演示拿一段真实代码跑一遍为了演示效果我准备了一段带典型坏味道的Python函数模拟购物车订单价格计算的场景。def calc_price(items, discount0): total 0 for item in items: if item[kind] book: total item[price] * 0.9 elif item[kind] electronic: total item[price] * 0.8 else: total item[price] if total 1000: total - total * 0.05 try: if VIP in items[0][tags]: total * 0.95 except: pass return total这段代码是我特意拼的毛病不少空列表访问会崩、裸except把所有异常全吞了、魔法数字满天飞、折扣逻辑散落各处、函数长且没有类型标注。把这段代码配合上面的prompt喂给大模型后得到的输出整理下来大致是这样的不同模型具体措辞会有差异但结构基本一致【问题清单】高 | 当 items 为空列表时items[0] 会抛出 IndexError且被裸 except 吞掉用户无法感知异常 | 第10-12行 → 微重构建议校验空列表并前置返回移除裸 except将 VIP 判断改为安全读取 → 示例改动前后对比见下中 | 0.9、0.8、0.05、0.95 等折扣率为魔法数字集中出现且无命名后续维护困难 | 第3-9行 → 微重构建议将这些折扣率定义为模块级常量并配置进映射表 → 示例改动前后对比见下中 | 函数名称 calc_price 语义泛化入参 items 缺少类型注解 discount 参数实际未被使用 | 第1行 → 微重构建议改名后再补类型注解删除未使用参数 → 示例改动前后对比见下低 | for 循环内 if-elif-else 结构可提取为字典映射减少分支层级 | 第4-8行 → 微重构建议用折扣率映射表替换分支判断 → 示例改动前后对比见下【改进后完整代码】BOOK_DISCOUNT 0.9 ELECTRONIC_DISCOUNT 0.8 OVER_THRESHOLD_DISCOUNT 0.05 VIP_DISCOUNT 0.95 DISCOUNT_RATE_BY_KIND { book: BOOK_DISCOUNT, electronic: ELECTRONIC_DISCOUNT, } def calc_price(items: list[dict], discount: float 0) - float: if not items: return 0.0 total 0.0 for item in items: kind item.get(kind) rate DISCOUNT_RATE_BY_KIND.get(kind, 1.0) total item.get(price, 0) * rate if total 1000: total - total * OVER_THRESHOLD_DISCOUNT if VIP in items[0].get(tags, []): total * VIP_DISCOUNT return total注意它在这版输出里把空列表校验提前了裸except也拆掉了。但我实际跑的时候发现一个问题它保留了items[0]判断VIP的逻辑这里其实是潜在的高风险点——因为当第一个商品不是VIP但后面有VIP商品时这个逻辑本身就错了。这是个业务逻辑bug不属于微重构范围但AI没标出来。这就引出了下面要讲的二次筛选问题。3.3 对AI建议做二次筛选的清单拿到AI输出后千万别直接复制粘贴进代码库。我把review的二次筛选习惯整理成了一张清单每次都按这个来过一遍目前效果比较稳定是否改变了函数的输入输出行为高严重问题里最容易踩的坑是AI顺手改了边界逻辑。原函数返回int它改成float虽然灵活但可能破坏调用方的断言。新增的命名是否符合团队现有约定AI按自己的习惯命名有时全team用的是camelCase它给一份snake_case合入后风格不统一。注释和类型标注是否与现有代码风格一致AI有时会过度注释把“给变量起个能自解释的名字”这种事也写成注释。删除的逻辑里有没有潜在依赖AI判断“这个参数没用”时可能忽略它是为了兼容旧调用方而保留的删了接口就变了。改动范围是否控制在“微”的级别如果AI建议的改动面覆盖了半个文件又牵扯到好几个函数之间的调用关系那就已经不是微重构了需要单独拉分支重做。这张清单本质上解决的是“AI的建议合理但风险未知”的问题。审查和微重构本身是低风险操作但如果没有人为把关低风险也会变成线上事故。4. 调优技巧与常见问题排查实录这套prompt不是一次写好的。我前后改过五六版遇到过各种奇奇怪怪的输出这里挑有代表性的几条记录一下。4.1 AI漏报、误报怎么办漏报是代码审查prompt最常见的翻车方式。AI对一段有明显空指针风险的代码视而不见反而去挑变量命名的毛病。排查下来发现问题出在prompt里没有明确“不同严重级别的标准是什么”。模型缺少判断依据时会把注意力放在最容易识别的表面问题上。我在模板里给问题定级逻辑补了三个判据影响正确性或稳定性为高影响可维护性或可读性为中风格或命名问题为低。加上这个判据后高严重级别问题的检出率明显提升裸except、空列表访问、外部数据未校验这类稳定性问题基本不再漏了。误报则通常出在AI不熟悉你的业务语义上。它看到那些看似无用的参数会误判为“可以删除”实际上那是给外部调用方预留的后门。这种误报防不住只能靠二次筛选兜底。另外还有一种误报比较隐蔽——AI把Python的鸭子类型特性当成问题来报说“应该加类型检查”这种属于过度审查需要在约束条件里加一句“如果语言惯例允许该写法请遵循语言惯例而不是教条”。4.2 输出格式乱的解决办法用这套prompt跑一段上百行的代码时AI可能会突然脱离模板输出一大段“总体评价”或者“思考过程”。这种情况在长代码场景出现的概率更高因为代码行数多了模型自身的“创作欲”会被激活。但也别急着怪AI我实测发现Root cause往往是我粘贴的代码行数太多几百行代码塞进去模型开始“阅读理解”而不是“代码审查”。两种解法都有效一是把输入代码切成几个合理单元一个函数一个prompt地审查二是在prompt最后加一句“如果代码长度超过阈值请按函数或模块分批输出”。另外输出格式如果偶尔乱一次一个小的处理技巧是直接在对话里追加一句“请重新按【问题清单】格式输出上一轮结果”比重新跑一遍整个prompt省事得多。4.3 微重构建议过于激进怎么拉回来有的模型生成能力太强给建议时控制不住最容易在“消除重复代码”这条路上走远。比如有一段重复逻辑出现了三次AI建议抽成一个装饰器再套一层泛型再搞一个注册表。听起来很高级但读代码的人大概率看不懂维护成本直线上升。针对这个问题我在约束条件里加了“不做过度设计”这条并补充了一句“微重构只做必要且明显有益的动作”。效果立竿见影建议明显收敛。如果你用的模型还是激进就在角色描述里加“你偏好小步变更每次重构只解决一个问题”。角色对行为的影响非常大这句话实测能有效压住AI的炫技倾向。4.4 迭代调优的几条经验最后分享几条这段时间攒下的调优经验第一个经验是prompt要版本化。从v1到v5我每次改动都记录改了哪一句、改后的效果是什么。有一次我把“严重级别”改成了“按影响范围划分高、中、低”高严重错误检出率直接翻倍。没有版本记录鬼都不知道是这句的功劳。第二个经验是温度参数必须调低。如果是通过API调用temperature记得设置在0到0.3之间。代码审查和创意写作不一样稳定性比多样性重要得多。温度一高同样的代码这次报5个问题下次报9个没法用。第三个经验是代码片段一定要完整。截取函数时不要只截中间一段缺了函数签名和return语句AI很难判断这个函数的输入输出语义给出的重构建议很容易错。我一开始图省事只贴函数体被重构后的代码直接没法跑后来改成整函数粘贴准确率才上来。第四个经验是对话历史越长越容易走偏。如果你在一个长对话里粘贴了多个文件的代码AI会在后面几轮开始串味把A文件的变量名安到B文件的逻辑上。我现在基本一个prompt只处理一段代码或者一个函数干脆利落。5. 把这个prompt放进团队流程里怎么用这节说说除了个人自用之外这套prompt在实际团队协作中还能怎么发挥作用。毕竟个人用prompt改进自己的代码是一回事把prompt变成团队的基础设施是另一回事两者差别很大。我自己在团队里推广这套方案时没有直接甩链接过去说什么“你用这个就行”那样大概率没人理。做了两件事一是把prompt模板放到团队的文档仓库里任何人提交MR之前可以先跑一遍自检同时约定reviewer收到代码时也可以用它做初筛二是打印了一份问题类别清单贴在工位上因为prompt输出的“高严重级别问题”正好对应我们review规范里“必须修改后才能合入”的那一类。实操下来这种组合确实能减少低级错误。以前reviewer需要从头到尾读一遍代码去发现空指针、裸异常、魔法数字这些问题现在AI先扫一遍reviewer的工作变成“复核AI的判断是否有误”以及“判断业务语义是否被AI误读”。这个转变非常关键因为AI此刻扮演的不是决策者而是助理侦查员的角色最终审查权仍然握在人手里。另外要注意配套动作。跑完prompt后如果AI给的改进建议被采纳了我建议把“改进后的代码重新跑一遍测试用例”。这是不可省略的一步。有一次我没有重跑测试就合入了代码结果AI把函数里一个变量的初始值从False改成了False看起来一样但类型不同下游逻辑直接崩了。从那以后我养成了AI改完代码必须过测试的习惯。还有一个小技巧是配合代码规范检查工具一起使用。prompt负责“语义层面”的审查比如逻辑错误、异常处理、重复代码lint工具负责“风格层面”的检查比如缩进、命名规范、未使用变量。两者侧重点不同互补性很强。如果你已经有ESLint、Pylint这些工具在跑那prompt里也可以加一句“不要在建议里包含风格类问题只报告逻辑和可维护性问题”输出会更有针对性。最后说一点个人体会。我自己把这套prompt固化成了工作流跑得越多越觉得它真正的价值不是让你省掉人工审查而是把“那些一眼扫过容易忽略的坏味道”重新翻出来摆在你面前。很多代码腐烂不是某一次大改搞坏的而是每次合入都带进来一点小问题日积月累成了大坑。AI帮你盯着每段代码里的魔法数字、裸异常、过长函数其实就是把腐烂的速度拖慢了。至于能不能根治还得靠写代码的人自己对“干净代码”有个标准prompt充其量是个手里拿着放大镜的监工。如果你也想试别指望一次到位。拿着前面的模板先跑一段真实的代码看看输出哪里不符合预期再回头改约束条件迭代个三五轮那才是属于你自己的顺手prompt。