调试
这一课你将能做到
- 用「假设→插桩→复现→分析→修复→验证」的科学调试流程,让 AI 高效参与
- 写出让 AI 能精准定位 bug 的最小复现和错误描述
- 区分「AI 能独立修的 bug」和「必须人工介入的 bug」
为什么要学
AI 时代调试的场景变了:以前是你对着代码想「哪里错了」,现在是 AI 生成了一段代码,跑着跑着出问题了,你要判断「是 AI 写错了,还是我的需求描述错了,还是环境/数据的问题」。
人话:AI 把「写代码」的成本降到接近零,但「调试」的成本没变,甚至因为代码不是你写的,理解成本更高了。不会调试的 Vibe Coder,就像不会修车的司机——车是租来的,坏了只能干瞪眼。
真实开发中,AI 辅助调试的最大价值不是「让 AI 替你找 bug」,而是加速「假设→验证」的循环:AI 帮你快速插桩、快速分析日志、快速生成测试用例,把原来半小时的排查压缩到五分钟。
先建立图像
AI 辅助调试的循环:
┌─────────────────────────────────────────┐
│ 1. 假设:AI 帮你列出可能的原因 │
│ 2. 插桩:AI 生成日志/断点/测试代码 │
│ 3. 复现:你跑一遍,拿到现象 │
│ 4. 分析:AI 解读日志,缩小范围 │
│ 5. 修复:AI 生成修复方案 │
│ 6. 验证:AI 跑测试确认没有回归 │
│ ↓ 如果没修好,回到 1,带着新信息 │
└─────────────────────────────────────────┘
跟着做
步骤 1:给 AI 一个「可调试」的错误描述
假设你的文章列表接口返回空数组,但数据库里有数据。差的描述:
接口返回空,帮我看看
AI 只能瞎猜。好的描述:
现象:GET /articles 返回 { code: 0, data: { records: [], total: 0 } },但数据库 article 表有 5 条数据。
复现步骤:
1. 启动应用(Spring Boot 3 + MyBatis-Plus)
2. 直接访问 http://localhost:8080/articles
3. 不登录、不带任何参数
相关代码:
[贴 ArticleController.list 和 ArticleService.list]
预期:返回 5 条数据
实际:返回空数组,total 也是 0
已排查:
- 数据库连接正常(其他接口能查到数据)
- 没有报错日志
步骤 2:让 AI 生成「排查清单」
基于以上信息,列出最可能的 5 个原因,按概率排序,每个给出验证方法。
AI 可能会给出:
- MyBatis-Plus 的 QueryWrapper 条件拼错了 → 打印生成的 SQL
- 分页参数 page=1, size=10 但插件没注册 → 检查 MybatisPlusConfig
- 字段映射问题,实体类字段和表字段不匹配 → 检查 @TableField
- 有全局拦截器/过滤器改了返回 → 检查拦截器链
- 逻辑删除了,但查询没加 deleted=0 → 检查 @TableLogic
步骤 3:让 AI 生成插桩代码
帮我生成临时日志代码,验证第 1 和第 2 个假设:
1. 打印 MyBatis-Plus 实际执行的 SQL
2. 打印分页插件是否生效
AI 会给你:
// 临时插桩:打印 SQL
Page<Article> page = new Page<>(pageNum, pageSize);
log.info("查询条件: {}", queryWrapper.getSqlSegment());
Page<Article> result = articleMapper.selectPage(page, queryWrapper);
log.info("实际 SQL: {}", page.getSqlSegment()); // 需要配置
log.info("返回总数: {}, 当前页条数: {}", result.getTotal(), result.getRecords().size());
步骤 4:执行、收集、反馈
把日志输出贴给 AI:
日志输出:
查询条件: (status = 1)
返回总数: 0, 当前页条数: 0
但数据库里 status 字段的值是 'PUBLISHED' 不是 1。
AI 立刻定位:status 字段类型不匹配,Java 里是 String,查询条件传了 Integer。
步骤 5:修复并验证
修复:查询条件用字符串 'PUBLISHED' 而不是数字 1。
同时检查项目里所有查询 status 的地方,确保类型一致。
修复后让 AI 跑测试:
跑一下 ArticleServiceTest,确认修复没有破坏其他场景。
步骤 6:区分「AI 能修的」和「必须人修的」
AI 能独立修的:
- 语法错误、类型不匹配、空指针(堆栈明确)
- 边界条件(off-by-one、空列表、null 值)
- 常见框架用法错误(MyBatis-Plus 分页插件没注册、Jackson 序列化格式)
必须人工介入的:
- 业务逻辑错误(AI 不知道「应该是什么样」)
- 并发/分布式问题(需要理解全局状态)
- 性能问题(需要 profiling 数据,AI 只能给通用建议)
- 环境/配置问题(AI 看不到你的服务器、网络、中间件)
讲清楚要点
- 错误描述的质量决定 AI 的排查效率:现象+复现+相关代码+预期vs实际+已排查项,五要素齐全,AI 一次定位;缺一样,AI 瞎猜。
- AI 的核心价值是加速「假设→验证」循环:不是替你思考,是帮你快速生成插桩代码、快速解读日志、快速列出可能性。
- 最小复现是调试的第一生产力:能把问题复现到一个 10 行代码的测试用例里,AI 修复率接近 100%;复现不了的问题,AI 也帮不了你。
- 业务逻辑 bug 必须人工把关:AI 不知道你的业务规则,它只能发现「代码写了什么」,不能发现「代码应该写什么」。
- 修复后必须跑回归测试:AI 修 bug 的特点是「头痛医头」,修 A 可能弄坏 B。测试套件是你的安全网。
你可能会懵的地方
-
AI 为什么有时候能找到 bug,有时候完全跑偏? 取决于错误信息的明确度。堆栈明确的语法/类型错误,AI 修复率极高;业务逻辑错误,AI 没有「应该是什么样」的知识,只能瞎猜。给它业务规则,它才能判断对错。
-
AI 生成的修复方案我怎么判断靠不靠谱? 三步:1. 理解修复思路(让 AI 解释为什么这么修);2. 检查是否引入了新的副作用(改了公共方法?改了共享状态?);3. 跑测试验证。三步都过才合入。
-
生产环境的 bug 能让 AI 调吗? 可以辅助分析(贴日志、贴堆栈、描述现象),但不要让 AI 直接操作生产环境。生产调试的权限必须留在人手里,AI 只出方案。
-
AI 建议我加一堆日志,会不会影响性能? 临时调试日志加 DEBUG 级别,确认问题后删掉。长期日志按级别分层:ERROR 必看,WARN 关注,INFO 记录关键流程,DEBUG 只在排查时开。
-
为什么 AI 有时候修复一个问题又引入新问题? 上下文不完整。AI 不知道你项目的全局约束(比如「这个字段不能改因为前端依赖」)。修复涉及公共代码时,把相关调用方也贴给 AI,让它评估影响面。
错法对照
| 错法 | 问题 | 正解 |
|---|---|---|
| 「接口报错了,帮我看看」 | 无现象无复现,AI 瞎猜 | 五要素错误描述 |
| 贴 500 行代码让 AI 找 bug | 注意力涣散 | 最小复现,只贴相关片段 |
| AI 说「可能是 X」就直接改 | 没验证就改,可能越改越坏 | 先插桩验证假设,再修复 |
| 修复后不跑测试 | 修 A 坏 B,回归引入 | 修复+测试是原子操作 |
| 生产环境让 AI 直接操作 | 风险不可控 | AI 只出方案,人来执行 |
卡点急救
- AI 反复修不对同一个 bug:停止循环,回到「最小复现」。写一个能稳定复现问题的测试用例,贴给 AI,修复率会飙升。
- 日志太多 AI 抓不住重点:用「关键时间点+关键字段」过滤。比如「用户 ID 12345 在 10:23:45 的请求,从进入 Controller 到返回的完整日志」。
- 问题只在特定环境复现:把环境差异(JDK 版本、数据库版本、中间件版本)写进错误描述。AI 不知道你的环境,环境差异是「本地好好的线上就炸」的常见原因。
面试常问
-
AI 辅助调试的工作流是什么? 高分回答:科学调试流程(假设→插桩→复现→分析→修复→验证),AI 在每个环节加速:生成排查清单、生成插桩代码、解读日志、生成修复方案、跑回归测试。但强调「最小复现」和「业务逻辑人工把关」两个边界。
-
AI 修复 bug 引入回归怎么控制? 修复前确保测试覆盖;修复后跑全量相关测试;修复涉及公共方法时评估影响面;用 git 分支隔离,方便回滚。
-
生产环境的高危 bug,AI 能参与吗? 可以辅助分析(日志解读、可能原因列举),但操作权限必须在人手里。AI 生成的修复方案需要人工审查+测试环境验证后才能上生产。
自测三问
- AI 辅助调试的六步循环是什么?
- 写出「可调试的错误描述」需要哪五个要素?
- 哪三类 bug 必须人工介入,AI 只能辅助?
小结一句话
AI 辅助调试不是让 AI 替你找 bug,是让你用科学流程驾驭 AI,把「假设→验证」的循环压缩到分钟级。
延伸
- Claude Code 官方文档:调试与错误恢复
- 下一课:版本控制——Git 与 AI 协作的原子提交和分支策略。