ARTICLE DETAIL

资讯详情

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

读 AI 生成的代码:从信任到验证的工程实践

读 AI 生成的代码:从信任到验证的工程实践 我正在读一段 AI 生成的代码。这不是一次普通的代码审查因为我发现AI code 最危险的地方不是它写错了而是它看起来太正常了变量命名规范注释完整函数的职责边界也很清楚。可就在我准备把它合入主干的前一分钟我看到回调函数里有一行日志会把一个外部服务的访问密钥直接打到日志系统里。如果这段代码上了生产密钥可能通过日志泄露给第三方日志平台影响面会比“代码写错”更大。这件事让我想通了一个问题AI 编程工具大幅提高了代码产出速度但真正决定工程质量上限的已经不再是“写代码的能力”而是“读代码的能力”。如果你不能认真阅读一段 AI 生成的代码你就没有资格把它放进你的项目里。这篇文章想聊的不是怎么安装某个 AI 编程助手也不是怎么让 AI 写得更好而是围绕一个看起来像宣言的句子展开I do read AI code。我愿意把 AI 生成的代码当成真正需要被审查、被理解、被验证的工程产物而不是“工具吐出来的答案”。1. 为什么“读 AI 代码”正在成为一项基础能力1.1 代码来源改变了默认信任模型也该改变过去很长一段时间我们读代码的动机来自“我要维护这段代码”。你可能是接手别人的模块需要改 bug也可能是同事提交了功能分支你需要做 code review。那时代码的主要来源是人类人类会犯错误但错误模式基本可预测命名不好、逻辑短路、边界遗漏、并发问题。现在不一样了。AI 编程工具成了越来越常见的代码来源。你输入一段需求描述它能在几十秒内生成一个函数、一个组件甚至一整套项目脚手架。Cursor、Claude Code、GitHub Copilot、通义灵码、OpenCode 这类工具正在把“从空白文件开始写代码”这件事变成“从一段生成结果开始改代码”。这个转变带来一个很隐蔽的后果你不再是代码的“作者”而是代码的“审核者”。但大部分人的审核能力还没有跟上。如果你在拿到 AI 生成代码后选择直接复制粘贴然后运行实质上你是在用“它看起来对”作为信任依据。可 AI 生成代码时并不像人类开发者那样拥有“我在什么项目里、有哪些依赖、核心业务规则是什么、哪些路径不能走”的全局上下文。它更像一个记忆力很强、但缺乏项目常识的外包工程师你给它一个局部任务它就可能基于统计上的常见模式补全出答案。所以默认信任模型必须改凡是 AI 生成的代码一律先当作不可信输入直到你读明白、验证过。1.2 “看起来能跑”和“真正应该跑”是两回事我在本地见过很多次这样的现象一段 AI 生成的 Python 脚本在 Jupyter Notebook 里能跑数据也能打印出来但把它接到生产接口上就会报错。原因是生成代码时它假设输入是一个已经清洗过的 DataFrame而生产接口进来的数据可能包含空值、重复字段、类型不一致。这种“看起来能跑”的错觉正是最危险的地方。传统代码写错了往往报错信息明显代码根本跑不起来。但 AI 生成代码经常会在“刚好能运行”和“正确解决问题”之间留一条很宽的缝。它可能使用了过时的 API、拼错了参数名但恰好被关键字参数兜住、或者调用了某个已经废弃的 SDK 方法只是老版本兼容所以没报错。更麻烦的是AI 生成的代码往往“面向测试样例优化”而不是“面向长期维护优化”。你如果只拿一两个 happy path 去验证它很容易通过但你换一批异常输入、换一个运行环境、把并发量提上去问题就会一个一个暴露出来。“能跑”通常只能证明流程没有断不能证明逻辑是对的。这是我在读 AI 代码时最深的一个体感。1.3 不读 AI 代码最贵的是后续维护成本很多团队引入 AI 编程工具的初期都会觉得“效率提升巨大”。这种提升是真实的但它隐藏了另一个数字代码库中不可理解的代码占比正在上升。如果 AI 生成了一段代码团队里没有一个人认真读过、理解过那么这段代码就变成了“遗产代码”。三个月后当业务需求发生变化你需要修改它的行为时你会发现你根本不知道它是怎么工作的也不知道哪里能动、哪里不能动。这时候你面前只有两条路要么花更长时间重新逆向理解这段代码要么直接删掉重写。而很多团队在压力下会选择“再加一层胶水代码”把问题包得更厚。所以我不把“读 AI 代码”理解成一个道德呼吁而是一个成本问题你现在不读将来一定会在调试、维护、交接时把这段时间连本带利补回来。早读其实就是省钱。2. 先看懂 AI 生成代码的几类典型问题读 AI 代码之前最好建立一个风险认知模型。AI 生成代码的问题不是“单一错误”而是分布在几个不同层面的系统性偏差。2.1 幻觉型错误表面完整实则调用了不存在的接口最常见的一类问题是 AI 基于训练数据中的模式生成了“看起来正确但实际不存在”的接口调用。例如你让它调用某个第三方 SDK 的图片压缩接口它可能直接生成一个client.compress_image()方法。可当你去查 SDK 文档时发现这个版本里根本没有compress_image只有一个process_image参数还完全不一样。这类错误在代码审查里最难发现因为函数名符合直觉参数类型看着合理IDE 的静态检查未必能捕捉特别是动态语言必须运行到对应分支才会报错我的处理方式很笨但很有效凡是 AI 代码里出现的第三方 API、SDK 方法、远程接口我会逐个去官方文档里确认名称和参数。这个方法慢但它能挡住绝大多数幻觉型错误。2.2 依赖幻觉安装了包项目却越来越不干净AI 还会“发明”一些不存在的依赖包。它可能觉得某个功能应该有对应的库于是生成import my_toolkit但 PyPI 或 npm 上根本没有这个包更有意思的是有些攻击者会提前注册一些常见但空白的包名如果你在安装依赖时没有仔细核对就可能在不知不觉中拉入一个来历不明的包。这类问题的排查链路通常是先看报错ModuleNotFoundError或Cannot find module再检查依赖文件是不是 AI 自动加了一个你没见过的包去包管理平台确认包名、维护者、下载量确认包版本范围内没有恶意提交最后才是安装并锁定版本所以我不建议让 AI 自动帮你安装依赖。让它生成代码可以安装依赖前一定要人工确认包名和来源。2.3 环境假设错配本地能跑换台机器就崩AI 生成代码时经常会默认环境里已经有某些配置。比如它假设系统已经设置好环境变量当前目录下有某个配置文件容器里已经安装了特定系统库数据库连接字符串存在于默认位置文件路径用的是 Linux 绝对路径这些假设在生成环境里可能全部不成立。我见过一个案例AI 生成的定时任务脚本在开发者的 Mac 上运行完全正常但部署到 Linux 服务器后由于路径分隔符和默认 shell 不同脚本第一个命令就失败。不是 AI 不懂跨平台而是它没有足够信息判断应该使用哪种路径风格所以它选择了一个最常见的写法。读这类代码时要特别关注“环境相关”的隐式假设。凡是涉及文件路径、环境变量、系统命令、权限、时区、编码的地方都要额外确认。2.4 安全与合规风险最容易被包装成“正常代码”AI 生成代码还有一个让人头疼的问题它可以把不安全的行为藏得很好。比如它可能因为业务需要而生成一段“把用户上传文件保存到本地”的代码但没有对文件名做任何过滤导致路径穿越也可能生成了一个网络请求但没对目标地址做校验还可能为了调试方便把敏感信息直接打印到日志里。互联网上有过一个非常经典的提醒不要把你理解不了的代码粘贴到浏览器 DevTools 控制台里执行。这个提醒同样适用于 AI 编程场景。当你让 AI 帮你“修复一下页面脚本”它给出的结果里可能包含一段外部请求代码。如果你没有读就直接执行等于把一个未知脚本引入了你的运行环境。安全审查不是安全工程师一个人的事。作为使用 AI 代码的人你至少要检查这几点代码里有没有网络请求请求发往哪里有没有读取环境变量、密钥、token有没有文件写入写入路径是否可控有没有执行系统命令命令参数能否被外部输入影响有没有把日志输出到第三方系统我经常用一张表格来快速评估一段 AI 代码的风险面。风险类型常见表现阅读时重点幻觉 API调用了不存在的函数、方法、参数逐个核对官方文档依赖注入import 了不存在的包或包名可疑检查依赖来源和包名环境错配依赖特定路径、环境变量、系统命令明确运行环境并做跨环境测试安全隐患密钥暴露、路径穿越、任意命令执行检查网络、文件、环境变量、命令调用逻辑偏差边界条件错误、业务规则不符合结合需求回归测试长期维护命名混乱、结构不清晰、没有测试关注可读性和测试覆盖3. 我读一段 AI 代码时具体在看什么读 AI 代码不是从头到尾逐行读而是带着问题读。我一般会读三遍。3.1 第一遍不看实现先看它打算怎么改变系统第一遍先不进入细节。我会把 AI 生成的代码当作一个“提案”先回答几个系统级问题这段代码会被谁调用它读哪些输入写哪些输出它会改动数据库吗会调用外部接口吗如果失败它会抛出异常、返回空值还是静默吞掉错误它会不会改变全局状态、缓存、配置文件这一遍的目标不是找 bug而是建立“这段代码在系统里的位置感”。没有位置感后面所有细节阅读都可能走偏。3.2 第二遍追输入、输出和异常分支第二遍开始贴近代码但只看数据流和异常流。对每个函数我会问输入参数有没有做校验空字符串、None、超长、非法格式怎么处理返回值是否符合调用方的预期类型稳定吗中间有没有改变原始输入对象出现异常时是向上抛还是内部捕获捕获后有没有记录上下文有没有过度设计为了“结构好看”而引入不必要的抽象AI 代码经常在 happy path 上表现得很好但异常分支往往只有一个笼统的try...except甚至把异常信息丢弃。这种代码最明显的问题不是“会挂”而是“挂了之后你不知道为什么挂”。3.3 第三遍找外部调用和副作用第三遍是读代码里最容易产生安全问题和运行事故的部分外部调用和副作用。我一般会用搜索功能把这几类关键词扫一遍http://、https://fetch(、requests.、axios.、curlexec(、system(、subprocess、eval(、Function(fs.write、open(..., w)、os.removeprocess.env、os.environ、getenvlogger.、console.log扫描完之后逐条确认三个问题这个调用的目的是什么它使用的参数来自哪里如果参数被篡改会发生什么这一步不需要自动化工具日常用 IDE 的全局搜索就够了。3.4 用最小验证代替肉眼信任读完之后还是要验证。但验证不应该是“把整段代码跑一遍”而是做最小验证。我会先构造一个最小输入只覆盖这段代码最核心的路径然后再构造一个明显越界的输入看它能不能正确处理。如果代码里有外部依赖我会用 mock 或者测试桩替换掉确保验证过程不依赖真实网络、真实数据库或真实密钥。这里有一个很实用的原则不要把 AI 生成代码第一次运行的输出当作正确结果。你至少要让它“错误一次”才能确认错误处理路径是真正有效的。3.5 一份可复用的 AI 代码审查清单我把上面这些整理成一个“四问”框架每次读 AI 代码前先走一遍它在做什么可以用一句业务语言描述出来吗它凭什么能工作依赖哪些外部条件、接口、数据它失败时会怎样有没有日志、异常、兜底方案如果三个月后是我来维护它我会怎么改如果这四个问题中有一个回答不上来就不要急着合入。先问 AI或者自己去看文档、写测试直到能回答为止。4. 工具和流程怎么配合“读代码”读 AI 代码不能只靠个人意志还得靠工具和流程提供支持。4.1 命令行的 AI 是新的写作入口但不是唯一的判断入口现在很多 AI 编程工具从 IDE 插件扩展到了命令行比如 Claude Code、OpenCode、Cursor 的命令行模式。为什么这些工具受欢迎因为它们把“和 AI 对话”变成了一种更自然的编程交互你可以在终端里描述任务AI 直接修改文件、执行命令、查看结果。这类工具确实提升了效率但它也带来一个诱惑把终端里的 AI 当成“权威”它说什么就是什么。我建议你换一个心态命令行的 AI 是帮你生成草稿的入口不是最终判断人。生成完代码后你仍然要打开文件用正常的 code review 流程过一遍。不要因为它在终端里直接执行成功了就跳过阅读。4.2 常见认证和安装报错先看密钥、再看区域、再看来源很多人第一次配置 AI 命令行工具时会遇到几种典型的报错。第一种是401 unauthorized有些服务会返回类似{code:api_key_required,message:...}。这个通常说明 API Key 没有配置或者配置的位置不对。排查顺序一般是检查环境变量名是否和工具文档一致检查 API Key 是否写入到了正确的配置文件检查 Key 是否有效、是否过期检查当前终端会话有没有重新加载环境变量第二种是区域限制报错比如{error:{code:unsupported_country_region_territory, ...}}。遇到这种结果不要试图用非常规方式绕过。先去看官方服务条款和支持范围确认当前账号或服务区域是否在支持列表里。如果你处于不支持的区域合规的做法是选用合规的服务或等待官方开放。第三种是“来路不明的安装脚本”。网上会有一些博主为了方便提供“一键安装”命令但这类命令经常会把一堆环境变量、代理配置、第三方脚本一并带进你的系统。我的建议是始终使用官方文档里的安装指令不要执行任何你不理解的安装脚本。注意无论什么时候都不要把你不理解用途的代码粘贴到终端、控制台或 DevTools 里执行。这个习惯比任何安全工具都重要。4.3 把代码审查固化到 IDE、Git 和 CI 里阅读 AI 代码这件事如果只靠“自觉”大概率会在 deadline 前失效。更好的做法是把审查流程固化到工具链里。在 IDE 层面开启 AI 生成代码的 diff 预览没有 diff 预览就不要直接生成。把 AI 生成前后的差异当成第一次 review 的最小单元。在 Git 层面所有 AI 生成代码的改动都应该走正常的 Merge Request 或 Pull Request 流程不要使用--no-verify跳过检查。提交信息里最好标明这部分代码是 AI 生成的方便后续回溯。在 CI 层面至少要加这些自动化检查单元测试和测试覆盖率依赖锁定检查密钥扫描防止把 token、密码提交到仓库静态代码扫描检查危险函数调用构建和跨环境运行测试自动化不能替代人读代码但它可以在人读之前先挡掉一批低级问题。4.4 善用“解释代码”代替“重新生成代码”遇到一段看不懂的 AI 代码时很多人的第一反应是“让它重写”。但我更建议先问它“请解释这段代码为什么要这样写。”这个动作有两点价值它强迫你把注意力放在逻辑上而不是急着得到一个新答案它能帮你识别 AI 是不是真的理解需求还是在模式匹配如果 AI 的解释含糊其辞或者只翻来覆去说“这样做更安全”“这是常见做法”那这段代码大概率需要重写。如果它能清楚说出权衡和边界你再决定是保留还是调整。5. 信任但要验证一套可持续的 AI 编程工作流最后我想把整个思路收束成一套可以放进日常开发里的工作流。5.1 先把 AI 当实习生而不是专家最影响 AI 代码质量的往往不是模型能力而是你怎么使用它。如果你把 AI 当专家给它一句模糊的需求它就会给你一个听起来很有道理、但实际上漏洞百出的方案。如果你把 AI 当实习生你会讲清楚背景和目标给出约束和边界要求它先说思路再动手对结果做 review让它在不理解的地方直接问这个心态转化比任何提示词技巧都重要。你越把它当实习生越会自然地去读、去验证、去追问它给出的代码你越把它当专家越容易在关键时刻放弃判断。5.2 推荐工作流约束 - 生成 - 阅读 - 测试 - 灰度 - 合入我目前比较推荐的工作流是这样的约束在让 AI 生成前先用自然语言写出需求边界、输入输出格式、不允许做的操作。生成让 AI 生成一个最小实现避免一次生成一个巨大模块。阅读按前面说的“读三遍”方法阅读生成代码确认自己理解了它的行为。测试补上最小用例至少覆盖 happy path 和一个异常分支。灰度把改动放到 staging 或小流量环境观察日志、错误率和性能数据。合入走正常的 code review 和 CI再合入主干。这套流程看起来不像“效率拉满”但它保证了一件事AI 生成代码被真正消化成项目资产而不是留在代码库里的定时炸弹。5.3 长期维护代码可读性比“一次性跑通”更重要AI 编程还有一个容易忽视的问题代码生成很便宜但代码阅读很贵。如果你依赖 AI 反复生成一次性代码短周期内可能觉得很爽但当多个模块堆叠起来你会发现代码风格不一致、抽象层级混乱、没有一个地方像“同一批人写出来的”。这会让后续的维护成本指数级上升。我在项目里会特别强调AI 生成的代码同样要遵守项目既有的代码风格和结构。不要因为它是 AI 生成的就默认接受不同的命名风格、返回类型和错误处理方式。如果一段代码就算跑通了但可读性很差我会倾向于让 AI 重写而不是改造。5.4 适用边界什么场景该用什么场景要谨慎不是说所有 AI 生成代码都不能用而是要分清场景。适合用 AI 生成并快速落地的场景包括样板代码和脚手架测试数据生成器与核心业务无关的脚本用于学习和探索的原型代码常见数据结构转换、格式化、工具函数需要更谨慎的场景包括核心交易逻辑涉及资金、权限、鉴权、隐私的模块安全敏感的文件读写和命令执行现有系统的复杂变更特别是测试覆盖不足的模块无人 review 的“小改动”判断标准可以很简单这段代码如果坏了影响多大如果影响大就必须读、必须测、必须 review。回到开头那句话。I do read AI code不是一句炫耀也不是一种保守主义。它是在 AI 生成代码越来越普遍之后一个开发者对自己写进项目的每一段代码负责的方式。AI 可以帮我们省下大量键入代码的时间但它不能替我们理解业务、判断边界、承担线上故障的责任。真正可靠的工程从来不是“AI 写得更多”而是“人理解得更多”。下一次当你准备把 AI 生成的代码直接提交时先停下来多读一遍。多读的那一遍可能不会让代码跑得更快但会让它活得更久。
返回列表