ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

从黑箱到留痕:AI 改代码的依据追溯与工程实践

从黑箱到留痕:AI 改代码的依据追溯与工程实践 上次AI帮我改完那个定时任务过了三周业务方跑过来问“当时为什么把重试次数从3改到5”我盯着 git 里的 diff 看了半天只看到几行新加的边界判断改动背后的推演过程全都不见了。那一刻我才意识到AI 改代码最大的成本不是生成速度而是追溯能力——它改完之后你却说不清楚它为什么这么改、依据是什么、下次还怎么接着维护。这篇文章想聊的就是 AI 辅助编程里的“依据丢失”问题AI 改完的代码怎么留痕怎么让每一处变更都有据可查怎么让代码审查、版本管理、上下文记忆形成一个可追溯的闭环。我会把这几年来自己和团队在 AI 辅助编码过程中踩过坑、用过的办法、沉淀下来的流程全部摊开讲内容适合正在用 AI 写业务代码的开发者也适合带着团队做代码审查的 tech lead 参考。1. AI 改代码的“黑箱”困境——为什么每次改动都像拆盲盒1.1 我遇到的那个“说不清”的改动先把这个场景完整还原一遍。项目里有个订单状态机AI 帮我重构了状态流转逻辑改完之后单测全绿看起来一切正常。结果两个月后新同事接手发现某个状态从“已支付”到“已取消”的路径里多了一个 5 分钟延迟判断——他翻遍 commit message 和代码注释都没找到这段逻辑的出处。最后我是从聊天记录里翻出来的当时产品提出“支付回调有抖动取消操作要尽量晚生效”AI 基于这个需求建议加一个延迟窗口我当时觉得合理就让它改了。理由是有的但理由只存在于我和 AI 的那次会话里并没有沉淀到代码库里。这就是“依据丢失”的典型症状改动结果在代码里决策过程在空气里。代码可以重构但 AI 做决策时的需求约束、权衡取舍、备选方案全都没有被记录。对维护者来说这段代码就是凭空冒出来的连“为什么”都问不出来。1.2 “依据”到底指什么要把换可追溯先得定义清楚“依据”这个概念。我拆了拆一段 AI 改出来的代码完整依据应该包括四层改动意图为什么要做这个改动。对应的是产品需求、bug 描述或性能目标而不是“AI 觉得这样更好”。方案选择在众多实现方式里为什么选了这种。比如“用延迟窗口代替直接抛异常因为要兼容回调抖动”。边界与假设代码成立的前提条件。比如“订单状态机只会被单实例调度器消费所以不需要分布式锁”。影响范围这次改动动了哪些模块可能影响谁。AI 经常只关注自己改的那一行却忽略了上下游调用方。配套的工具或流程如果没有专门设计这四层信息往往是散落在聊天记录、个人记忆和代码注释里的碎片。我们要做的就是让它们以一个规范、稳定的形式附着在代码库上让后续任何人打开项目都能按图索骥。我用一个生活类比来说明这件事。你让同事代你写一份项目复盘报告他能交出漂亮的结论。但你要是想搞清楚这个结论基于哪些数据、为什么排除另一个方案你一定会期望他把中间的推演草稿也一并留给你——代码就是那份报告而“依据”就是推演草稿。AI 改代码也是一样它负责把报告写出来我们负责把草稿留住。2. 第一道防线把代码审查从“看结果”变成“问过程”2.1 审查 diff 时要追问的三个问题AI 改完代码第一步应该是审查而不是直接合入。但很多人的审查只看“功能对不对”“语法有没有错”这远远不够。我给自己定了个规矩审查 AI 的 diff 时必须追问三个问题第一个这段代码为什么出现在这里如果 AI 加了一个判断我要它明确说出触发条件尤其是“什么时候走分支 A、什么时候走分支 B”这种边界。AI 对边界条件的理解经常和业务预期有偏差一问就能问出来。第二个这个数值或条件是哪里来的AI 特别喜欢生成魔法数字——重试次数 3 次、超时 5000 毫秒、并发上限 20。每当看到这种硬编码的数值我都会要求 AI 给出依据来源是配置项、产品需求、还是它自己拍脑袋如果是后者我会立刻纠正让配置显式化。第三个原有逻辑被它动过吗有些 AI 工具会顺手“优化”它认为冗余的代码删掉防御性判断、简化分支、甚至重命名变量。这种无意识的越界行为最危险因为 diff 里往往只显示“删了几行”根本不会显示“为什么删”。审查时我通常会对比改动前后的执行路径确认它的“顺手优化”没有改变原有行为。这三个问题问下来很多问题都会在合入前暴露。更关键的是每问一个为什么AI 都会给出理由而这些理由正好可以作为后续追溯依据的第一手素材。2.2 让 AI 在动手前先交“变更计划”在审查 AI 的成果之前还有一个更前置的做法让 AI 在改代码之前先写一份变更计划说清楚它打算怎么改、为什么这么改、影响哪些文件。我试下来这一招能把“依据丢失”的问题解决掉一大半。具体做法是在给 AI 下任务的时候不要只丢一句“帮我把 XX 功能实现一下”而是加一个前缀要求让它先输出“分析结果”再进入“编写代码”。我的提示词模板如下你要完成一个代码变更任务。开始之前请先按以下格式输出变更计划 1. 需求理解把用户的诉求转成具体可验证的目标。 2. 当前实现分析指出与需求相关的现有代码位置和现有逻辑。 3. 方案与理由列出你认为可行的实现方案说明为什么选择其中一种。 4. 改动清单逐个列出要修改的文件和修改点预估影响范围。 5. 风险声明列出可能被影响的边界条件、下游接口或潜在回归点。 我的期待先输出以上计划在我确认之后你才开始编写代码。这段提示词看起来朴素但价值非常大。第一它强迫 AI 把思维过程显式化第二它把“需求到实现”的映射关系固化成了一个可保存的文档第三它在心理上把 AI 从“快速出结果的工具”变成了“需要被评审的协作者”。我还会把这份计划直接贴进 commit message 或者项目里的决策日志——具体怎么贴后面会详细说。反正每次这么做之后两周后再看那段代码我基本都能快速回忆起当时的背景而不是像以前一样对着 diff 干瞪眼。2.3 把 AI 的解释沉淀成“看得见的话”审查过程中AI 会因为追问而给出很多解释。比如我问“为什么这里用 Map 而不是 for 循环”它会解释说数据量小、为了可读性之类的。这种解释如果不记录下来转脸就忘。我的做法是要求 AI 把关键解释浓缩成一两行注释直接写在对应的代码上方。比如// 支付回调存在抖动取消操作延迟 5 分钟给回调留有处理窗口 // 若直接抛异常会导致用户在支付成功后看到未支付状态 ORDER_CANCEL_DELAY Duration.ofMinutes(5);这种做法有两个好处一是后续查看代码的同事不用翻 commit 历史就能理解意图二是它天然形成了一个“依据层”。我特别强调要让 AI 把解释写成对“人”讲的话而不是算法说明——比如“用 map 是为了应对 N1 查询”这种就很好但“map 是 HashMap平均 O(1)”这种价值就低很多。我把这套审查流程总结成一句话不要只看 AI 给了你什么要追问它为什么给你这个。每次追问都是一次依据补全审查一次项目就清晰一分。3. 建立 AI 改代码的“决策日志”——让依据有迹可循3.1 决策日志应该记哪些内容光靠审查问答还不够因为审查时生成的对话是碎片化的。要想长期可追溯我强烈建议在项目里维护一份“AI 变更决策日志”也就是把 AI 改代码时的关键决策沉淀成一个独立文档。我踩过很多坑之后确定了四类必记内容需求来源那个让 AI 动手的最初诉求是什么是 PRD、bug 单、还是口头沟通。记录来源比记录“AI 加了 5 分钟延迟”重要得多因为来源决定了改动合理性的评判标准。可选方案与取舍这次改动前 AI或我考虑过哪些替代方案为什么淘汰了它们。这部分信息在三个月后最值钱它会拦住后来的“优化党”避免有人凭直觉推翻一个其实深思熟虑过的决策。关键参数与假设所有硬编码的数值、依赖的外部条件、临时标记的默认开关都值得写清楚。比如“重试次数从 3 改成 5因为第 4、5 次重试之间增加了退避时间不会雪崩”。风险与回滚方案AI 改完这次代码后最可能出问题的地方在哪、怎么回退、怎么止血。别等线上出事故了才想方案当场记下来。这四类内容拼起来就是一个完整的技术决策记录。我看 GitHub 上不少开源项目会用 ADRArchitecture Decision Record文档我们的 AI 变更决策日志其实就是 ADR 的轻量变体只不过把“架构决策”换成了“每次 AI 改动的决策”。3.2 三种轻量记录法从零成本到高回报有些人一听“维护日志”就觉得负担重。我试过几种方法按成本从低到高排列你可以根据自己的项目节奏选一种。第一种“聊天记录存档法”。把和 AI 对话中关键的部分复制到一个 Markdown 文件里放在项目 docs/decisions 目录下。成本几乎为零缺点是内容杂、结构乱适合个人项目或改动频率不高的场景。第二种“变更标题 正文法”。在 commit message 的正文里写决策依据标题用规范格式呈现主要信息。Git 本身就是可追溯系统把依据塞进 commit 是最顺手的做法。这个我强烈推荐成本极低、收益极高。后面第 4 节会展开讲 commit 怎么写更有效。第三种“独立决策日志法”。建一个格式化的决策日志文件每次 AI 改动都追加一节。适合多人协作、改动频繁的商业项目。我目前用的就是这种模板固定查起来一目了然。不管选哪种核心原则是“当场记、即时沉淀”。AI 改完代码的那十分钟是记忆最好的时候拖到第二天你和 AI 的对话还在但背景细节已经开始模糊了。3.3 为什么“决策日志”比“让 AI 记住”更靠谱有人可能会说新一轮对话难道不能帮我们回顾历史吗我可以给模型提供上下文。这个想法我也试过但实际效果受限于几个现实问题会话上下文长度有上限旧对话会被截断很多 AI 编程工具在重启或切换会话后之前的记忆会消失就算模型能看到旧上下文它回答的“依据”也可能存在幻觉未必真的还原当时决策。相比之下决策日志是你能掌控的、可验证的事实。它不会被截断、不会被遗忘、不会被重写。把 AI 当作“没有独立记忆的实习生”把决策日志当作“交接班记录本”这个定位最符合现实。我给自己的要求是合入一次 AI 改动就补一条日志有点像写工作日志不占几分钟但长期价值巨大。尤其是项目交接或者你休假回来翻一遍决策日志整个项目的来龙去脉就全回来了不用再一条条查聊天记录。4. 把可追溯性写进版本管理——Commit 规范的实战细节4.1 用规范的 Commit 格式给 AI 改动“贴标签”决策日志是给自己看的commit message 是给所有人看的。我见过太多的 team 直接把 AI 生成的 commit message 原样合入结果就是“fix stuff”“update code”这类无信息量的标题三个月后谁都不知道这次提交动了什么。我的做法是在团队里推行一套带标签的 commit 规范尤其适用于 AI 参与的改动。标题格式如下type(scope): subject [AI-generated] body - 背景为什么这次要改 - 依据AI 建议此方案的理由 - 影响改动文件范围涉及哪些模块 - 测试已经跑过的测试或注意的回归点举个例子fix(order-state-machine): 调整支付回调窗口防止取消误触发 [AI-generated] 背景支付回调存在抖动用户支付成功后偶发收到取消通知。 依据AI 建议增加 5 分钟延迟窗口让回调有时间落地状态 比抛异常方案更平滑不需改造第三方回调重试机制。 影响仅修改 OrderStatusTransitioner 中 STATUS_CANCEL 的流转分支 不影响对账统计接口的消费逻辑。 测试已跑通状态机单测和支付回调模拟场景回归风险低。这套格式的优势在于第一个是检索友好git log 里一眼能看到哪些提交是 AI 生成的第二个是依据明确“背景/依据/影响/测试”四段把所有追溯信息装进去第三个是约束性一旦约定成习惯任何没有写依据的 AI 改动都会在 code review 时被拦下来。4.2 哪些注释必须保住别让 AI 顺手删掉AI 在重构代码时有一种让我很头疼的习惯它会把“看起来没用”的注释当成垃圾清理掉。但那些注释里可能藏着当时特别重要的决策信息——比如“这个循环不能改并行因为共享状态有竞态”“这个字段不能删旧客户端还在用”。这些注释就是最原始、最贴近代码的“依据”。我在提示词里专门加了一条规则除非用户明确要求否则禁止删除或重写现有注释对于关键边界条件和魔数必须在旁标注注释说明来源。真要让 AI 重构代码我会在任务描述里写明“保留所有解释性注释只修改逻辑代码”并在 review 时专门检查注释是否被误删。另外对于 AI 新生成的代码我要求它遵循一个“注释分级”策略魔法数值必须有注释复杂分支逻辑必须有注释业务规则必须有注释纯技术实现细节如“初始化一个数组”可以不要。这样既能避免注释泛滥又能保证追溯依据落在关键点上。4.3 版本历史与决策日志如何互相引用Commit message 里写了依据决策日志里也写了依据两者如果各写各的很快会出现不一致。我的经验是让它们互相引用保持单一信息源。做法很简单commit message 的正文里把完整依据写在决策日志里然后 commit 里加一行指向性说明比如“详见 docs/decisions/2024-05-20-order-cancel-delay.md”。反过来决策日志里也记录本次提交的 commit hash方便从日志跳回代码历史。这样一来追溯路径就变成了双向的从 git log 出发你可以顺着 commit 找到决策日志从决策日志出发你可以顺着 commit hash 找到具体改动。两条路都能到达同一个“依据”不会再迷路。5. AI 辅助编程工作流的实战建议——从工具链角度解决追溯难题5.1 别让 AI “裸奔”在你的代码库上如果直接给 AI 一个臃肿的代码库让它“自己看着改”大概率会收获一堆来路不明的大改。我给自己的项目定了几条约束都是实操换来的教训。第一条限制改动范围。在 prompt 里明确指定“只允许修改 src/order/service 下的文件其他文件一律不要动”。AI 工具普遍有“过度扩散”的倾向给出明确的边界能让它收敛。第二条逐块验证。让 AI 每次只改一个点比如只改状态机的流转逻辑改完跑一遍测试再进入下一项。这个习惯有效抑制了 AI 同时改多处导致问题来源交叉的情况——出问题的时候你能精确知道是哪次改动引起的。第三条保留原始版本。在让 AI 动手之前先把当前稳定版本创建成一个单独的分支或打一个 tag。AI 改坏了可以直接回滚不用对着 git 后悔。这不是对 AI 不信任而是把追溯的锚点提前放好——你知道上次能跑的代码长什么样改动的“前因”就有了参照物。5.2 维护“上下文账本”防止AI会话失忆AI 的对话记录会丢工具更新后会丢会话超时后会丢。所以我和团队在项目里维护了一个轻量级的“AI 上下文账本”本质上就是一个固定路径下的文档每次跟 AI 合作时先读它再开工改动结束后再更新它。这个文件的内容包括项目的技术栈和目录约定当前正在进行的改动清单上次对话遗留的问题下一步计划以及已沉淀的决策日志索引。我一般命名为 AI_CONTEXT.md 或者 dev-log.md放在仓库根目录。“上下文账本”解决的是 AI 换会话后的“失忆”问题。因为有了这个文档即便是全新的对话我也可以把关键信息贴给它让它直接从已有的上下文中续写而不是重新瞎问。对开发者自己来说这其实也是一份“我个人超强工作记忆”的外挂——换电脑、换同事、换接手人它都能让新的人站在前人的肩膀上继续工作。5.3 用“结对程序员”心态替代“自动补全”心态我们经常陷入一个误区把 AI 当成更快的自动补全工具出结果就抄写不出依据也不要紧。但真要在生产环境维护代码这种心态迟早会让你付出代价。我更推荐用“结对程序员”的心态来用 AI。结对程序员意味着AI 提出方案我来决策AI 写代码我来审查AI 给出建议我来判断。这个角色的转换带来的一个直接变化就是——我会要求 AI 把“依据”作为改动的一部分交付就像同事在 code review 里会解释设计思路一样。具体到操作上我每个月都会做一次“AI 改动可追溯性自查”挑一个两周前由 AI 改过的模块尝试不看聊天记录只靠 commit message、注释、决策日志去还原当时的改动依据。如果还原不了就说明这套追溯方案有漏洞需要补。这个自查习惯看起来有点自虐但确实能逼着整个流程越做越扎实。6. 常见问题排查实录——那些 AI 改代码后真正会踩的坑6.1 高频问题速查表下面是我整理的一个问题速查表覆盖我见过、踩过、帮别人排过的高频问题你可以直接存下来当排查清单。症状可能原因解决路径两周后看 AI 改的代码完全不懂为什么这样写决策只存在于聊天记录没沉淀到 commit 或日志补写决策日志给关键代码补注释以后强制在 commit body 写“依据”commit message 是“fix stuff”不知道改了什么直接采用了 AI 生成的默认 commit 信息手动填写规范标题用git log --format格式化查看历史AI 顺手删了几行看似无用的防御性代码AI 认为代码冗余做了越界“优化”review 时强制检查删除块prompt 里明确禁止清理未指定代码会话丢失AI 不再记得上次的设计工具没有持久化上下文或上下文超过限制维护 AI_CONTEXT.md、决策日志开工前先贴上下文改动范围失控一次提交涉及几十个文件prompt 没有指定改动边界在任务描述里限定文件范围拆成多次改动逐个合入关键参数魔数、默认值来源不明生成时没有说明依据要求 AI 给每个魔数写注释在决策日志和 commit 中记录来源后来的人推翻了一个“看似奇怪但其实深思熟虑”的设计决策日志缺失方案取舍不被理解建立 ADR 风格日志提交时写明备选方案与淘汰理由6.2 真实案例AI 把账号体系重命名了分享一个印象最深的真实事故。当时我给 AI 布置了一个任务“把用户角色判断逻辑抽成一个工具类”。结果 AI 在完成这个任务的同时顺手把某个接口里的accountId重命名成了userId理由是“为了统一命名风格”。它认为这只是一处无害重构但那个接口是给老客户端用的客户端那边传的参数名是固定的——重构一上线老版本客户端开始报参数缺失线上告警直接拉响。事后复盘问题出在三个环节prompt 没有明确“只准新增工具类不准修改接口签名”review 时只看了新增代码没细看被重命名的调用点commit message 只写了“extract user role utility”完全没有提到它还做了命名调整。这个事故让我把一条规则写进了团队规范AI 的 diff 中凡是出现了“与任务不直接相关的改动”一律要求解释或回退。你可以把这个规则加进 code review checklist效果立刻就有。后来我们让 AI 给改动加标记——新增、修改、删除、重命名每一类都单独列出来审查的人不会漏掉任何角落。6.3 排查思路如何快速找出“依据”在哪个环节丢了如果你遇到一个“找不到依据”的改动我建议按下面这个顺序层层排查不用从头瞎找第一步先看 commit message。如果标题带[AI-generated]看 body 里有没有“背景/依据/影响”字段。有就直接拿到答案。第二步看代码注释。AI 生成的关键逻辑或魔数旁边如果有注释那也是依据的一部分。没有就继续往下。第三步查决策日志。翻 docs/decisions 目录找时间点匹配的那一节看是否记录了这次改动的需求来源和方案向量。第四步翻开发工具的会话记录。现在不少 AI 编程工具支持会话存档和回放如果工具里有历史可以直接搜索关键词。第五步也是最后一步找当事人。如果以上全部落空说明当时的流程有重大漏缺——这时候诚实标注“依据缺失”主动补一份说明文档比隐瞒风险更专业。这个排查顺序本质上就是“由近及远、由代码到记忆”能让你用最短路径恢复信息。我这么跑过几次之后发现大部分“依据丢失”都能在一两步内解决真正需要翻聊天记录的情况非常少。结尾做这套追溯体系做了大半年我最大的体会是AI 改代码的能力越强我们越需要给它的产出配上“来路证明”。代码生成只是第一步让代码在被生成之后依然可解释、可重建、可维护才是 AI 辅助编程真正成熟的标志。现在我每次让 AI 动手改代码都会先花十分钟要求它输出方案和依据再让它开工。项目里每一处 AI 改动都带着理由的时候三个月后再回头维护你会感谢当时那个多做了一步的自己。
返回列表