AI写代码越改越乱?多文件修改中的上下文、依赖冲突和代码冲突
使用 ChatGPT、Codex、Cursor 等 AI 编程工具时,修改一个函数通常比较顺利,但任务一旦涉及多个文件,错误就会明显增加。
常见情况包括:
- 修改了后端接口,却忘记同步前端参数;
- 调整了数据结构,但部分调用位置仍使用旧字段;
- 新功能可以运行,原有功能却出现异常;
- 同一个方法在不同文件中被重复实现;
- AI改完代码后,项目能启动,但业务逻辑已经前后不一致。
问题并不一定是AI不会写代码,而是多文件修改本身就涉及更复杂的上下文、依赖关系和协作逻辑。
一、AI看到的上下文并不等于完整项目
很多人认为,把项目文件交给AI后,AI就能像开发者一样理解整个系统。
实际上,AI通常只能基于当前能够读取到的文件、对话内容和代码片段进行判断。项目文件一多,就容易出现上下文缺失。
例如一个用户登录功能,可能同时涉及:
- 登录页面;
- 请求封装文件;
- 后端控制器;
- 用户服务;
- 数据库模型;
- 权限中间件;
- 路由配置;
- 环境变量。
如果AI只看到了登录页面和后端接口,就可能忽略权限中间件仍然使用旧的身份字段。
最终结果是:登录接口返回成功,但进入其他页面后仍然提示没有权限。
因此,多文件任务的难点不只是“需要修改几个文件”,而是AI能否发现这些文件之间的真实关系。
二、文件之间存在隐性的依赖关系
代码依赖并不只体现在导入语句中。
除了明显的函数调用,项目中还存在大量隐性依赖,例如:
- 前后端约定的字段名称;
- 数据库表结构;
- 配置文件中的变量名称;
- 缓存中的数据格式;
- 消息队列中的消息结构;
- 日志和监控规则;
- 测试用例中的固定数据;
- 第三方接口返回格式。
假设原来的用户对象使用:
userNameAI将它统一修改成:
username表面上只是修改了一个字段名称,但实际上可能影响数据库映射、接口返回、前端展示、登录校验和自动化测试。
只要有一个位置没有同步更新,系统就可能在特定场景下报错。
这也是为什么多文件修改完成后,不能只检查AI明确修改过的文件,还要继续排查所有关联位置。
三、AI容易局部正确,但整体不一致
AI生成代码时,往往会优先解决当前文件中的问题。
例如,某个页面需要增加“用户状态”字段,AI可能会完成以下修改:
- 在页面中增加状态显示;
- 在接口返回中增加状态字段;
- 在数据库模型中增加对应属性。
单独看每个文件,代码可能都没有明显问题。
但放到整个项目中,仍然可能出现:
- 创建用户时没有写入默认状态;
- 更新接口不允许修改状态;
- 查询接口没有包含该字段;
- 管理员和普通用户使用了不同的状态值;
- 前端使用数字,后端使用字符串。
这类错误最麻烦的地方在于,它们通常不会立即导致项目启动失败,而是在某个业务流程中才暴露出来。
所以“代码能运行”并不等于“修改已经正确”。
四、修改顺序错误会产生连锁问题
多个文件通常存在修改顺序。
比较合理的顺序可能是:
- 明确数据结构;
- 修改公共类型;
- 修改底层服务;
- 修改接口;
- 修改调用方;
- 修改页面;
- 更新测试。
但AI有时会先修改调用方,再回头调整底层结构。
在修改过程中,前后文件可能基于不同版本的设计生成代码。
例如:
- 第一个文件假设接口返回对象;
- 第二个文件改成返回数组;
- 第三个文件仍按照对象读取数据。
如果任务执行时间较长,AI还可能在后续修改中“忘记”前面已经确定的约定,从而产生前后冲突。
五、旧代码没有删除,容易形成重复逻辑
AI修改功能时,通常更擅长增加代码,不一定会主动清理旧逻辑。
因此项目中可能同时存在:
- 新旧两个接口;
- 两套参数校验;
- 两个名称相近的工具函数;
- 重复的数据转换逻辑;
- 已经失效但仍被调用的旧方法。
这种情况短期内可能没有报错,但后续维护时很容易调用错版本。
例如,AI新增了一个getUserInfoV2方法,却没有替换所有旧的getUserInfo调用。
结果就是部分页面使用新数据结构,部分页面仍使用旧数据结构,项目行为逐渐变得难以预测。
六、多人开发时还会遇到代码冲突
在真实项目中,AI修改代码的同时,其他开发者可能也在修改相同文件。
常见情况是:
- AI基于旧分支生成代码;
- 其他人已经修改了公共组件;
- 合并代码时只解决了文本冲突;
- 实际业务逻辑发生覆盖。
Git提示的冲突只是文本层面的冲突。
即使代码能够正常合并,也可能存在逻辑冲突。
例如,一个开发者修改了订单状态判断,AI同时修改了订单状态枚举。两部分代码虽然没有产生Git冲突,但状态值已经不再对应。
所以使用AI批量修改文件时,仍然需要开发者了解当前分支、最近提交和其他人的修改范围。
七、一次修改范围太大,错误率会明显上升
很多人在使用AI编程工具时,会直接输入类似指令:
帮我重构整个用户模块,同时修改前端、后端、数据库和权限系统。
这种任务看起来省事,实际上风险很高。
因为任务范围越大,需要同时维持的一致性规则越多。只要其中一个环节理解错误,后续修改都会建立在错误基础上。
更稳定的方式是把任务拆开:
- 先整理当前调用关系;
- 再确定新的数据结构;
- 先修改后端;
- 再修改前端;
- 最后补充测试和清理旧代码。
每完成一个阶段就运行一次测试,比一次修改十几个文件后再统一检查更可靠。
八、AI修改多个文件后应该检查什么
1. 检查修改文件清单
先确认AI到底修改了哪些文件,有没有改动任务范围之外的代码。
重点关注:
- 公共组件;
- 配置文件;
- 数据库模型;
- 权限模块;
- 请求封装;
- 公共类型定义。
2. 搜索旧字段和旧方法
使用全局搜索检查旧名称是否仍然存在。
例如修改了接口字段,就要搜索:
- 旧字段名;
- 新字段名;
- 相关类型;
- 序列化和反序列化代码;
- 测试数据。
3. 检查接口两端是否一致
前端发送的参数、后端接收的参数、接口返回格式和前端读取方式必须保持一致。
不要只看接口是否返回成功,还要检查异常状态、空数据和权限不足等情况。
4. 检查公共类型
TypeScript类型、Java实体类、Python数据模型等公共定义,通常会影响多个模块。
公共类型发生变化后,需要重点检查所有引用位置。
5. 运行原有测试
AI增加的新功能可以正常运行,不代表旧功能没有受到影响。
除了测试新增功能,还要运行原有单元测试和关键业务流程。
6. 查看Git差异
不要只阅读AI最终输出的说明,应直接查看代码差异。
重点观察:
- 是否删除了必要逻辑;
- 是否加入重复代码;
- 是否修改无关文件;
- 是否把配置写死;
- 是否改变异常处理方式。
九、怎样向AI描述多文件任务更可靠
与其直接要求AI“完成整个功能”,不如先让它分析。
可以按照下面的顺序提问:
第一步:
先分析这个功能涉及哪些文件和依赖关系,不要修改代码。
第二步:
列出准备修改的文件、每个文件的修改目的,以及可能受影响的旧功能。
第三步:
先修改数据模型和公共类型,完成后暂停。
第四步:
根据已经确定的数据结构修改后端接口,不要改变其他接口。
第五步:
最后修改前端调用,并检查是否仍有旧字段和旧方法。
这种方式虽然多了几个步骤,但可以明显降低AI理解偏差后连续修改多个文件的风险。
十、总结
AI修改多个文件容易出错,主要不是因为它不会生成代码,而是多文件任务同时包含了:
- 不完整的项目上下文;
- 显性和隐性的依赖关系;
- 数据结构的一致性;
- 修改顺序;
- 旧逻辑清理;
- 多人协作冲突;
- 回归测试。
在实际开发中,AI更适合执行边界清楚、可以逐步验证的任务。
对于涉及前端、后端、数据库和权限系统的改动,最稳妥的方法仍然是:先分析依赖,再拆分任务,每完成一步就进行检查和测试。
AI可以加快修改速度,但项目整体是否一致,最终仍然需要开发者判断。
