收益:
- 能够通过错误消息、堆栈跟踪和最小重现实例向 AI 有效描述错误
- 能够使用人工智能运行系统调试流程,通过假设和逐步缩小范围来找到根本原因
- 能够通过重现和回归测试来验证人工智能建议的修复是否确实解决了问题
调试是找出程序行为与预期不同的原因并修复它的任务,它消耗了大多数工程师的大量时间。良好的调试不是基于猜谜游戏,而是基于系统的缩小范围:澄清症状、假设、检验假设、找到根本原因。人工智能是这个周期中非常强大的伙伴;但前提是你给他正确的信息。说“代码不起作用,修复它”会迫使人工智能进行猜测并提出笼统的建议。给它完整的错误消息、堆栈跟踪和最小的再现样本,您将一起找到根本原因。
在本单元中,我们将了解如何向人工智能有效地描述错误,逐步缩小假设范围,并通过回归测试验证所提出的修复方案是否确实解决了问题。请记住:“修复”错误和“抑制错误的症状”是两件不同的事情;在没有找到根本原因的情况下进行的纠正会将错误转移到另一个地方。
概念: 堆栈跟踪:显示错误发生时以什么顺序调用哪些函数的转储。最小重现:触发错误的最简单、最短的代码/输入。根本原因:问题的真正根源,而不是症状。回归测试:确保相同错误不会重复的测试。
向 AI 描述错误
人工智能找到根本原因的可能性与您提供的信息的质量成正比。一个好的错误描述包括:您试图做什么、您期望什么、发生了什么、确切的错误文本和堆栈跟踪、涉及的代码、环境(语言/版本/操作系统)以及产生错误的最小样本。
- 明确症状。格式为“预期 X,实际 Y”。
- 粘贴完整的错误文本和堆栈跟踪。不要缩短它,审查它,但不要破坏结构。
- 给出最小的复制品。触发错误的最小输入和代码。
- 指定环境。语言版本、库版本、运行环境。
有效的错误描述提示:“我正在调试一个错误。信息:- 我正在尝试做什么:[X]- 预期行为:[Y]- 实际行为:[Z]- 完整错误消息和堆栈跟踪:[粘贴]- 环境:[语言/版本,库/版本]- 涉及的最少代码:[代码] 不要给我直接修复。首先按概率顺序列出 3 个最可能的根本原因,并告诉我要验证每个原因的检查。”
通过假设缩小流程
系统调试是一门消除可能性的艺术。使用AI生成假设并设计实验来检验每个假设;然后运行实验并返回结果。这个循环比随机更改和停止的习惯要快得多,称为“霰弹枪调试”。
二分搜索(二分)帮助程序提示:“这个错误昨天不存在,今天出现了。我想找出最后 20 个更改中的哪一个导致了二分查找错误。给我一个分步计划:我应该测试哪一点,根据结果我应该去哪一半。还要准确地告诉我每一步要检查什么。”
日志插入策略提示:“我找不到错误,因为我看不到这个函数中的中间值。告诉我在哪些点需要添加打印哪些变量的日志行。为每个日志添加‘我将从这个日志中学到什么’解释。还指定将阻止我记录机密数据的警告。”
提示:如果您无法解决错误,大多数情况下问题出在您错误假设的地方。问人工智能“我的哪些假设可能是错误的?”询问会打破你的盲目性。最严重的错误隐藏在你说“我确信这是正确的”的地方。
弱提示/强提示
弱:“我的代码出现错误,修复它:[200 行代码]”(结果:AI 不知道它是什么错误,预期是什么;它根据猜测给出一般建议,其中大多数都是无用的。)强:“我得到 NullPointerException。预期:应该返回用户列表。实际:调用 getUsers() 时爆炸。堆栈跟踪:[粘贴]。环境:Java 17。最小重复:当用户列表为空,但当它已满时则不是。相关 15 行:[代码]。解释根本原因以及为什么触发空列表,然后建议修复。”
强大的提示将错误放在上下文中:在这种情况下它会发生(空列表),在这种情况下它不会发生(完整列表)。这条线索(“空时发生”)几乎直接指出了根本原因。由于在弱提示中无法获得这些信息,AI 会进行盲目猜测。
验证修复
只有完成以下三件事的修复才是真正的修复:
控制
问题
如何验证
错误消失了吗?
相同的条目现在有效吗?
再次运行最小重现
没有新的错误吗?
还有其他东西坏了吗?
运行整个测试套件
不会重复吧?
会不会再次出现同样的错误?
为此场景添加回归测试
在没有找到根本原因的情况下进行的纠正往往会抑制症状。例如,用“如果为空则跳过”掩盖空错误会产生真正的原因:“为什么数据为空?”不可见,并且错误在其他地方再次发生。
迷你箱
案例 1——症状抑制陷阱。团队通过 try-catch 来消除偶尔出现的 null 错误;错误消失,但两周后数据似乎丢失。真正的原因是服务超时返回 null。当你问人工智能“为什么它会变成空?”时,根本原因就出现了;真正的修复需要 1 小时,但却是永久性的。
情况 2 — 最小再现能力。开发人员无法修复“偶尔会崩溃”的错误。它根据 AI 的建议将错误减少到最小的输入:问题仅发生在包含土耳其字符的文件名(编码错误)。当 300 行不确定性减少到 5 行明确再现时,解决方案就变得显而易见。
案例 3 — 抗回归测试。 AI修复了日期计算错误。工程师对此并不满意;添加了针对错误场景(月底,1 月 31 日 + 1 个月)的回归测试。 4 个月后,当另一个更改触及同一区域时,测试会变成红色,并且错误会在投入生产之前被捕获。
常见错误
- 这意味着“它不起作用,修复它”。没有错误文本、期望和重现,AI 会进行猜测。
- 不给出堆栈跟踪。堆栈跟踪通常直接指示根本原因。
- 继续进行随机更改。没有建立假设的实验浪费时间。
- 抑制症状而忽略根本原因。该错误在其他地方重生。
- 未通过回归测试确保修复。将来同样的错误会悄无声息地出现。
总之
有效的调试是系统地缩小范围,而不是猜测。为 AI 提供完整的错误文本、堆栈跟踪、最小复制和环境信息,会成倍增加找到根本原因的机会。使用AI生成假设并设计实验来检验每个假设;你进行实验。仅当您看到错误消失、没有引入新错误并且受到回归测试保护时,才考虑修复“完成”。
应用任务
考虑一个真实的或人为的错误。首先将误差减少到最小的再现(在输入中出现错误,在输入中不出现错误)。使用有效的错误配方提示,向 AI 询问 3 个根本原因假设以及每个假设的验证步骤。通过一一测试假设来找到根本原因,修复它,然后针对此场景编写并运行回归测试,以表明错误已消失并且测试提供了保护。
清单
- [ ] 我将症状澄清为“预期与实现”。
- [ ] 我向 AI 提供了完整的错误文本和堆栈跟踪。
- [ ] 我将错误减少到最小的再现。
- [ ] 通过一一检验假设,我找到了根本原因。
- [ ] 我没有抑制症状,而是解决了根本原因。
- [ ] 我添加并运行了针对相同错误的回归测试。