ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

AI改代码实战指南:从代码审查到Agent的安全工作流

AI改代码实战指南:从代码审查到Agent的安全工作流 用 AI 改代码这件事最常听到的两种说法是一种说“AI 能帮我把代码写得更优雅”另一种说“AI 生成的东西根本不能用”。我实际跑过一段时间之后结论更偏中间AI 确实能把代码改好但前提是你得把它当成一个需要明确任务书的协作对象而不是一个丢一段代码就能自动优化的黑盒工具。这篇文章不讲概念讲一套我自己一直在用的实操流程覆盖代码审查、局部重构、补测试、批量调整、报错排查和 AI Agent 的边界。适合正在用或准备用 AI 编程工具的开发者看尤其是那些已经过了“让 AI 写个爬虫试试”的阶段、想真正把 AI 嵌进日常开发流程里的人。最值得关注的一点是AI 改代码是否靠谱大概率不取决于模型选得多新而取决于你在交给它任务之前有没有把上下文、约束、验证方式和验收标准交代清楚。下面按我从环境准备到最终合入的真实顺序拆开讲。1. 先用一句话说清楚AI 改代码到底改的是什么1.1 判断代码有没有更好的三个维度先说“更好”的定义。不同场景里的“更好”完全不是一回事至少可以拆成三个维度。第一是可读性。命名是否清楚函数是否过长逻辑是否绕注释是否解释了“为什么”。这类改动 AI 做得最稳因为它不需要理解业务只需要遵循编码习惯。第二是正确性。有没有漏掉边界条件异常路径是否被吞掉状态更新是否遗漏并发场景下是否存在竞态。这类改动 AI 能发现一部分但最终确认必须由人来做。尤其是业务规则相关的正确性AI 没有真实业务背景经常会把“看起来合理”当成“实际正确”。第三是可维护性。重复代码是否被提取模块边界是否合理依赖方向是否正确新功能能否低成本加进去。这一维度最难因为涉及项目历史和团队约定AI 在单次对话里基本看不到全貌。所以结论很简单AI 最适合改第一类可以辅助第二类第三类要慎重。只要把任务落在这三个维度里AI 就不会变成“瞎优化”。1.2 AI 擅长什么不擅长什么我把实际用下来比较稳定的能力列一下。擅长的事单个文件内的局部重构比如把一个 300 行的函数拆成几个小函数。补充单元测试尤其是纯函数、工具类、数据转换这类输入输出明确的代码。解释陌生代码生成调用关系说明。遵循已有的 lint 规则修代码风格问题。替换弃用 API 调用统一 import 路径。定位明显的空指针、未处理异常、变量作用域问题。不擅长的事跨多个模块甚至跨服务的架构重构。需要业务判断的删改比如“这个字段是否还需要保留”。真实性能问题AI 只能凭经验猜不能替代压测。安全边界判断尤其是涉及权限、认证、敏感数据的代码。保持“团队历史风格”的自觉性AI 很容易把局部代码改得比全项目超前一个版本。这部分认知很重要。你会发现凡是 AI 擅长的都有一个共同点任务边界清楚验收标准明确。凡是不擅长的都需要大量项目上下文和人为经验。因此工作流设计的目标就是尽量把任务变成前者。2. 开始之前先把环境和工具链准备好2.1 三类接入方式按场景选择目前常见的接入方式大致有三类。不用纠结选哪个“最强”按任务类型选更合适。接入方式典型场景特点我常用的判断IDE 内 AI 插件边写边补全、代码审查、快速解释上下文自动带出操作轻量适合日常小改动和学习命令行 AI 编程助手项目级重构、批量任务、按指令改动多个文件能读整个项目结构执行链完整适合做单文件和批量改动比如 Claude Code、OpenCode 这类工具直接调用 API沉淀成团队内部工具、CI 集成、自动化脚本可控性最强需要自己处理提示词和上下文适合做成代码审查机器人之类的固定流程我在日常开发里会用 IDE 插件做实时辅助用命令行 Agent 做稍大规模的改动。两类工具不冲突甚至可以串起来用先用 Agent 做批量调整再用 IDE 插件逐段 review。2.2 项目条件比工具数量重要不管用哪类工具项目本身必须满足几个前置条件否则 AI 给的改动根本无法验证。第一代码必须在版本管理里随时能回滚。这是最硬的条件。没有 git 这类版本管理工具AI 的一次大改动就可能让你丢失原有可用版本。我见过不止一次AI 重构之后功能测试挂了最后全靠git checkout恢复。第二构建和测试命令必须可复现。建议在项目根目录写清楚npm install npm run build npm testAI 工具在执行改动前通常会尝试跑构建和测试。如果命令本身在你的机器上都跑不通那 AI 在改动后也无法判断结果。所以要先保证一个干净的基础环境。第三AI 的改动放在单独分支里。不要直接在开发主干上让 AI 折腾。独立分支的好处是diff 历史清晰出问题不影响其他人合入前还能再做一次完整检查git checkout -b ai-refactor/xxx第四输入文件要稳定。编码、换行符、生成文件路径这些细节很容易被 AI 在重构时顺手改掉造成大量没有意义的大 diff。2.3 常见报错先查 API Key 和环境变量AI 编程工具接入时报错最多的不是模型本身问题而是认证和配置。我遇到过最典型的报错类似unexpected status 401 unauthorized: {code:api_key_required,message:api key required}这个报错基本不用怀疑代码逻辑直接按顺序检查三件事。先看 API Key 是否真的配置了。很多工具通过环境变量读取而不是直接写在对话框里。确认环境变量名是否和工具文档完全一致echo $ANTHROPIC_API_KEY echo $OPENAI_API_KEY再看 Key 权限范围。有的 Key 只允许访问部分模型或部分接口权限不足也会返回 401 或 403。可以在命令行里先发一个最小请求验证 Key 是否有效而不是直接跑完整项目。最后看请求是否真的带上了认证头。有些代理配置、脚本封装、自定义命令行工具会在转发请求时把 Header 丢掉导致服务端识别不到身份。遇到 401 先查 Key 和环境变量不要急着换工具或重装。能把日志完整读一遍的人问题已经解决一半。3. 一套能落地的 AI 改代码工作流3.1 先让 AI 解释代码不急着让它改拿到一段要改的代码最忌讳的操作是上来就发一句“帮我优化这段代码”。因为 AI 没有和你共享思维它不知道这段代码在业务里扮演什么角色也不知道哪些边界必须保留。我的做法是先让它用人类语言复述代码逻辑。可以这样问请先解释这个函数做了什么。输入是什么输出是什么有哪些副作用函数被哪些地方调用这一步有三个作用。一是验证 AI 是否真的理解代码。如果它把核心逻辑说错了那后续任何改动都不可信这时候应该换更小的上下文或者换提问方式。二是让 AI 在回答过程中建立起对代码的“心理模型”。后续让它改代码时它会更倾向于保留原始行为。三是你自己也能借这个过程重新整理一遍代码逻辑。很多时候代码写久了你以为自己知道它干嘛真让你讲一遍反而讲不清楚。3.2 单文件、小目标做可回滚的局部重构通过解释验证没问题之后再进入修改阶段。第一原则是单文件、小目标。比如一个文件里有两个重复的函数目标是“抽取公共函数”。动作就只做这一件不要同时改命名、加注释、换格式、调日志。每多一类改动review 成本就指数上升而且出了问题很难定位是哪一步引入的。具体步骤可以这样选定一个文件先完整理解逻辑。告诉 AI 只改这个文件只解决一个明确问题。让 AI 给出 diff而不是整个文件重写。把 diff 应用到代码跑构建和测试。确认通过之后再进入下一个文件或下一个问题。diff 比全量代码好 review 得多。我看代码合入时几乎不看 AI 重写的整个文件只看它实际改动了哪些行。3.3 补测试优先于改逻辑对有测试覆盖的项目我强烈建议一个顺序先让 AI 基于当前行为补测试再根据测试结果决定是否修逻辑。原因是AI 直接改逻辑时很容易把一个“应该被修复的问题”和“当前系统依赖的行为”一起改掉。测试的作用就是先把当前行为冻结住。具体操作请为这个模块补充单元测试。测试范围正常输入、边界输入、异常输入。不要修改被测代码。然后运行测试。如果测试全部通过说明当前代码行为和你预期的行为一致那就不需要动逻辑最多做重构。如果有些测试跑红了说明当前行为和你预期不一致。这时候让 AI 看测试失败信息再决定动哪个位置的代码。这个流程可以把“AI 改坏了”的概率压到很低因为你先定义了行为再允许它调整实现。3.4 批量任务要按“单一改动类型”拆分到了批量场景任务拆分比单文件重要得多。我见过一个团队让 AI 一次性做四件事统一命名风格、加类型标注、修所有 lint 警告、把 Promise 改成 async/await。最后 diff 大到没法 review而且四个目标之间互相干扰。正确做法是每一轮只处理一类改动第一轮统一命名规范。第二轮补类型标注。第三轮修 lint 警告。第四轮换异步写法。每一轮单独提交单独跑测试。这样做的好处是如果你的测试覆盖足够某一轮出了问题可以直接回滚这一轮提交不影响其他已经完成的工作。批量任务还要特别注意输出命名。AI 在处理多个文件时很容易生成临时文件、备份文件或者把原有文件覆盖到错误位置。批量跑之前一定要在独立分支里操作并且设置明确的输出目录和命名规则。4. 提示词怎么组织AI 才不瞎改4.1 有效提示词的四个要素我把这些年摸索出来的提示词套路总结成四个要素。上下文。告诉 AI 它正在处理什么项目、什么语言、什么框架代码路径是什么。不要只丢一个函数片段就让它猜整个项目。约束。明确告诉 AI 哪些不能动。常见约束包括公共接口不能变、外部依赖不能换、不要引入新的设计模式、只修改指定文件。验证方式。告诉 AI 改完代码后可以用什么命令验证结果的正确性。这会让 AI 在改动时自动避开容易破坏测试的方案。输出格式。要求 AI 按一定格式输出比如先说明问题再给出 diff再解释每处改动理由。这样不容易把“无用改动”混在“必要改动”里。4.2 一个可直接改用的代码审查提示词示例下面是我比较常用的一个审查提示词你可以根据项目情况改你是这个项目的资深开发者。请对一个函数做保守的代码审查。 第一步解释这个函数现在做了什么包括输入、输出和副作用。 第二步列出潜在问题按严重程度排序严重、一般、轻微。 第三步对每个问题给出最小改动建议。不要重写整个函数不要改变对外行为不要引入新的抽象。 输出格式 1. 函数行为说明 2. 问题列表 3. 最小改动方案这个提示词的关键词是“保守”和“最小改动”。没有这两个词AI 很容易进入创作模式把简单函数重构成你觉得高深但项目里没人能维护的代码。4.3 模糊指令是代码变糟糕的根源“帮我优化一下”“让这段代码更好”“代码不够优雅帮我改进一下”——这类模糊指令是 AI 把代码改坏的最大原因。为什么因为“优化”没有度量标准。AI 只能猜测你想要的优化方向。它可能把循环改成 map你可能根本不想引入函数式写法它可能把多个参数封装成对象你反而觉得这样调用更啰嗦。所以每次提需求之前先问自己一个问题这次改动的验收标准是什么验收标准是“函数能从 300 行拆成 80 行以内”那任务清晰。验收标准是“代码看起来更高级”那任务不清晰请先别让 AI 动手。清晰的任务描述才可能得到稳定的输出。模糊的任务描述只会得到随机的代码改动。提示词里出现“提高”“优化”“增强”这类词时建议同时把“但仍然保持”的约束写清楚。没有约束的优化等于让 AI 自由发挥。5. 验证 AI 改完的代码不能只看能不能跑5.1 先逐行看 diff再决定是否合入AI 说你改好了不等于代码真的改好了。我合入 AI 改动前做的第一件事永远是看 diff。git diff看 diff 时重点看三类内容一是被删除的代码。AI 特别喜欢把一些看起来没用的 catch 块、空注释、旧分支删掉。这些代码里有些确实没用有些是历史遗留的防御逻辑。删除之前必须确认真的没有副作用。二是被新增的抽象层。AI 对“封装”有天然冲动动不动就新增一个中间层、基类、工厂函数。如果项目里没有这个习惯建议让它用最直接的方式写。三是测试文件的改动。如果一次重构里测试文件也发生了大量修改要特别警惕。正常重构应该保持测试行为不变测试被大面积修改说明实现行为可能变了或者 AI 为了通过测试调整了断言标准。5.2 测试通过不等于改得对只要项目测试覆盖足够测试通过是基本要求。但测试通过并不代表改动就是对的。我一般会在测试通过之后做三轮补充检查。第一轮是类型检查。如果有 TypeScript、MyPy、Flow 这类工具一定要跑一遍。AI 改代码时很容易留下隐式 any、动态属性或者把类型定义改宽了。npx tsc --noEmit第二轮是 lint。AI 写的代码可能风格一致但不一定满足项目的 lint 规则。跑一遍 lint 能过滤掉大量低级问题。第三轮是手工验证关键路径。挑一个和这次改动关系最紧密的用户场景手动跑一遍。比如你改的是登录模块就至少跑一遍登录成功和登录失败两个场景。5.3 三个很容易被 AI 改动带偏的坑第一个坑是形式主义重构。AI 把代码拆得很漂亮注释、命名、空行都很规范但核心逻辑完全没变甚至比以前更绕。验收时不要只看结构一定在脑子里过一遍改动前后行为是否一致。第二个坑是过度设计。AI 会为了“可扩展性”引入将来用不到的配置项、策略模式、插件机制。如果项目当前只有一种场景这些抽象就是负担。约束里可以直接写不引入新的设计模式不为不存在的需求预留抽象。第三个坑是自我证明幻觉。AI 在解释自己改动时往往会用非常肯定的语气描述“这次修复解决了某问题”但代码未必真的处理了根因。要拿日志、断点、测试断言去验证而不是信它的总结。6. 从单文件到全项目AI Agent 的用法与边界6.1 适合交给 Agent 的批量任务随着命令行 AI 编程助手这类工具越来越成熟很多人开始把整项目交给 Agent 处理。这里有一个很重要的判断边界有些任务适合有些任务绝对不能适合。我目前愿意交给 Agent 批量执行的任务包括统一替换旧 API。比如某个第三方库发布了新版本旧函数全部标记 deprecated可以让 Agent 在项目里自动替换。补类型标注。给 JavaScript 项目迁移 TypeScript 时先让 Agent 给变量、函数签名、模块导出补上基础类型。批量生成单元测试。对输入输出清楚的工具函数Agent 可以用很高的效率生成测试用例。清理 lint 警告。从项目根目录跑一次 lint把报告里的警告按类型分组分批让 Agent 处理。整理 TODO 注释并生成问题清单。这些任务的共同点是规则统一、目标明确、验证容易。Agent 每次改动之后只要有完整的测试可以跑就能确认是否引入回归。6.2 不适合交给 Agent 的敏感任务反过来这些任务我坚决不让 Agent 直接执行架构级重构。比如把单体拆成微服务或者把核心模块的数据流方向改掉。这种任务需要大量业务上下文和架构判断Agent 没有能力也不该负责。安全相关改动。权限模型、认证逻辑、支付流程、敏感数据脱敏这些代码可以辅助分析但不准直接自动改写。需要真实用户反馈的交互流程。比如 UI 状态的变更、表单校验规则如果只看代码AI 可能觉得没问题但真实用户会感知到差异。涉及数据迁移的修改。删字段、改表结构、改缓存 key这类改动一旦出错恢复成本很高。必须由人设计迁移方案AI 只负责执行它那部分。6.3 用 Agent 之前先画安全护栏在让 Agent 真正动项目之前我会先做几件事。第一确认初始 git 状态是干净的所有已有改动都提交到分支上。第二明确 Agent 的工作目录和可修改文件范围。不要让 Agent 随意在项目根目录自由发挥。第三检查 Agent 可能会执行的命令。很多命令行 Agent 会自动安装依赖、运行脚本、调用外部 API。如果它提出的命令里包含 curl 下载文件、绕过某些检查、修改权限之类的内容我会手动拒绝并重新评估。一个很通用的安全提醒是不要往终端或开发者工具里粘贴你不理解的代码。这套逻辑现在同样适用于 AI 编程——AI 给你的命令如果看不懂它做了什么就不要直接执行。Agent 辅助编程时角色应该是“执行者”而不是“决策者”。决策权必须在你手里。7. 我踩过的坑和现在的使用习惯7.1 三个典型翻车场景翻车场景一过度抽象。有一次清理一个订单状态判断函数我给 AI 的指令是“减少重复代码”。结果 AI 把函数重构成三个抽象层加了策略模式和状态映射表。逻辑确实变复杂了但业务可读性显著下降最后我放弃了这次改动。后来我意识到重复代码有时是合理重复尤其当几处逻辑未来会朝不同方向演化时强行合并反而增加耦合。翻车场景二删除“无用”代码。某个历史遗留的错误处理分支AI 判断它永远不会执行顺手删掉了。结果三个月后一个极端输入触发了空指针。这类问题在代码审查时很难发现因为删除动作看起来很小。我的规避方式是所有“删除冗余代码”类的请求我都会单独标注“如果这块代码的作用不明确先不要删标记出来由我决定”。翻车场景三测试全绿但核心路径没覆盖。AI 给一个文件生成了 20 个测试用例全部通过我差点直接合入。后来手工看覆盖率才发现核心的高风险分支根本没被测试到。它生成的全是简单路径测试。从那以后我只看“测试覆盖了哪些分支”不再看“测试数量多不多”。7.2 现在的工作流和判断标准踩过这些坑之后我现在的使用习惯稳定成一套固定流程。第一步给 AI 不超过一个文件的任务目标是生成可验证的结果。第二步先让 AI 解释和列出改动计划我确认方向后再让它动代码。第三步所有改动都必须给出 diff不允许直接覆盖整个文件。第四步跑构建、测试、类型检查、lint四关全过才考虑 review。第五步亲手跑一遍关键业务路径。第六步合入前看最终 diff确认没有任何多余改动。这套流程看起来笨但效率其实最高。因为它把每次 AI 改动的风险控制在一个小范围内真出问题也容易定位和回滚。7.3 适合哪些人用不适合哪些人用最后说适用人群。适合用 AI 改代码的人至少要能读懂 AI 的改动。你不一定要成为精通 AI 的工具玩家但你必须能看懂 diff能判断逻辑是否被改变。这也意味着 AI 改代码的理想使用者是已经具备一定开发经验的工程师而不是完全不懂编程、只想让 AI 自动生成项目的门外汉。不适合的人包括项目本身没有版本管理和测试改完也不知道是不是坏了。完全不会 review 代码只能全盘相信 AI 输出。预期是“丢一个需求进去自动得到完整项目”的人。团队里没有人工 review 机制AI 改动可以直接上生产环境。AI 在代码上的真正价值是帮有判断力的人把重复劳动吃掉而不是代替人做判断。我现在的日常状态是AI 负责把代码问题暴露出来做批量改动生成测试和文档我负责看 diff、跑关键路径、做业务决策。这套配合稳定下来之后代码质量确实在往上走。如果你打算开始尝试我建议不要从“让 AI 重构整个项目”开始先找一个小文件、一类问题、一次提交把最小闭环跑通。这个流程一旦熟练再逐步扩大到更复杂的任务会踏实很多。
返回列表