单位 6 / 12

调试和根本原因分析

收益:

  • 能够将错误减少到最小的可重现实例,并在充分证明的情况下将其转移到人工智能
  • 能够用最便宜的控制来测试基于证据的假设并找到根本原因
  • 能够解决根本原因并通过回归测试确保其安全,而不是修补症状

调试是找出软件行为异常的原因并修复它的过程。这是开发人员花费时间最多、最累的工作;因为大多数时候错误并不在出现的地方,而是隐藏在几步之后。人工智能是一个强大的思维伙伴,可以加速这项研究——但前提是你给它正确的证据。没有证据的调试是人工智能产生最多幻觉的领域。

在本单元中,我们建立了从生成错误到找到根本原因的严格流程:澄清症状、收集证据(错误消息、堆栈跟踪、日志、条目)、生成假设、测试假设并验证修复。人工智能在每一步都提供帮助;但“固定”决定是通过看到错误实际上已经消失而做出的。

为什么证据就是一切?

法学硕士不会像你那样看到错误;他只知道你告诉他什么。像“应用程序崩溃”这样的句子几乎没有给模型提供任何信息,模型用预测(即幻觉)填补了空白。反过来,完整的错误消息、堆栈跟踪 - 发生错误的函数调用的详细信息、触发错误的输入以及预期的结果等。给定观察到的行为,模型可以对真实概率进行排名。

在调试过程中,将人工智能视为侦探的助手:提供的证据越多,它生成的假设就越准确。如果没有证据,助理只会猜测,可能会误导你。

提示:在将错误移植到 AI 之前,请将其减少到最小的可重现示例。触发错误的最小代码和输入使您和模型的事情变得更加容易;大多数情况下,在减少的过程中,您会自己找到原因。

逐步:根本原因分析流程

  1. 明确症状。 “发生了什么事,你预计会发生什么?”将两者写在一句话中。
  2. 收集证据。完整的错误消息、堆栈跟踪、相关日志行、触发条目、版本信息。
  3. 生成假设。来自 AI“解释此症状的 3 种可能原因以及如何针对每种原因进行测试?”问。
  4. 首先测试最便宜的假设。添加日志、打印值、运行测试。证据证实了假设吗?
  5. 解决根本原因,而不是症状。与其通过补丁来消除症状,不如解决根本原因。
  6. 验证并添加回归测试。看到错误消失;然后编写一个测试来捕获该错误,这样它就不会再出现。

三个迷你箱

情况 1 — 堆栈跟踪指向正确的文件。应用程序对某些请求返回 500 错误。开发人员向 AI 提供完整的堆栈跟踪和触发请求;该模型假设错误是由日期解析层中的 None 值引起的。开发人员在该行添加了日志,验证并在 15 分钟内解决了问题;前一天浪费了 2 个小时进行未经证实的实验。

案例2——幻觉导致走错路。另一位开发人员简单地写道“数据库连接正在断开”。 AI在没有任何证据的情况下指责连接池设置;开发者花了 40 分钟修改这个设置。真正的原因是网络端超时,只有通过查看日志才能发现。教训:没有证据的假设只是可能的,并不可靠。

案例 3 — 发现片状错误。有一个测试偶尔会失败。 AI被给予测试代码、失败消息以及“有时通过,有时失败”的信息;该模型表明测试的共享时间/顺序依赖性。审查确认测试是基于系统当地时间的。一旦时钟被固定(模拟),测试就变得稳定。

四个可复制模板

基于证据的假设生成:

我正在调试一个错误。以下证据。- 预期行为:{{预期}}- 观察到的行为:{{观察}}- 错误消息/堆栈跟踪:{{trace}}- 触发输入:{{输入}}- 环境/版本:{{版本}}列出解释此症状的 3 个最有可能的根本原因。对于每个:我如何测试(最便宜的检查)以及如何修复它(如果是真的)。如果证据不充分,请告诉我您需要哪些额外信息。

解释堆栈跟踪:

阅读此堆栈跟踪。区分错误可能从哪一行(根)开始以及哪些行只是链的延续。建议首先查看 1-2 个地方。相关代码:{{code}}跟踪:{{trace}}

最小重现减法:

下面的代码会产生错误。将其减少到仍会触发错误但丢弃任何不必要的内容的最小实例。不要假设您删除的每个部分都不会影响错误,而是添加一条注释,说明“如果删除此部分后错误消失,这就是原因”。{{code}}

校正后验证和回归测试:

假设根本原因是 {{cause}},我进行以下修复:{{fix}}。1)此修复是否确实修复了症状,是否有任何副作用?2)编写一个回归测试,以便将来捕获此错误。

弱提示/强提示

弱:“代码不起作用,为什么?”
强:“Node 20 / Express。当正文中的 items 为空字符串时,POST /orders 返回 500;应该返回 400。堆栈跟踪:TypeError:无法读取未定义的属性(读取“0”) - 附件是完整的跟踪和关联的处理程序。请给我解释此症状的 3 个最可能的原因以及如何测试每个原因。[跟踪 + 代码]”

强大版本;它提供环境、端点、触发输入、确切的错误类型和预期行为。模型不再能够进行预测,而是能够进行分析。

步骤

人工智能的贡献

你的控制

收集证据

需要什么证据,提醒

确实收集了证据

假设生成

列出可能的原因

根据上下文确定优先级

假设检验

推荐测试方法

亲自操作和观察

修正

补丁推荐

它能解决根本原因吗?这是真的。

回归

写一个测试

验证测试是否已损坏

解决根本原因,而不是症状

大多数时候,人工智能会建议一个补丁来快速消除症状:添加一个 try/catch,进行空检查,吞掉错误。这有时是正确的,但往往是危险的;因为最初的原因仍然存在,并从其他地方再次爆发。每次修复时,问问自己:“这是否修复了错误的原因,或者是否使错误变得不可见?”一旦找到根本原因,修复措施通常会更小、更稳健且永久。

注意:默默吞下异常(空 catch)并不能解决错误;它只是掩盖了并使未来的诊断变得不可能。如果人工智能提出这样的“解决方案”,请不要在不质疑根本原因的情况下接受它。

常见错误

  • 没有证据就提问。模棱两可的句子使模型陷入幻觉;提供完整的错误、跟踪和输入。
  • 锁定第一个假设。 AI 的第一个建议可能不是最有可能的;从最便宜的可控假设开始。
  • 修补症状并忽略根本原因。沉默的错误返回。
  • 关闭修复而不验证它。在类似生产的情况下看到错误实际上消失了。
  • 不编写回归测试。如果不添加测试,则在以后的版本中将默默地返回相同的错误。

综上所述

在调试中,人工智能的力量与你提供的证据成正比:没有完整的错误消息、堆栈跟踪、触发输入和预期行为,模型只是推测。严格的流程——澄清症状、收集证据、生成假设、使用最便宜的控制进行测试、修复根本原因、验证并添加回归测试——可以快速且永久地消除错误。人工智能是一个假设生成器;您才是决定 bug 是否真正得到解决的人。

应用任务

选择您最近遇到的真实错误(或重现测试错误)。首先进行“最小复制”步骤;删除触发错误的最小代码和输入。然后通过“基于证据的假设生成”模板从AI中获取3种可能的原因和测试方法。自己测试最便宜的假设,找到根本原因,修复它,最后编写一个回归测试,在将来捕获这个错误并验证测试是否确实被破坏。

清单

  • [ ] 在将其转移到 AI 之前,我将误差减少到最小的可重现样本。
  • [ ] 我将完整的错误消息、堆栈跟踪、输入和预期行为添加到提示中。
  • [ ] 我从最便宜的可控方案开始,而不是局限于单一的假设。
  • [ ] 我确认我已经解决了根本原因,而不是修补了症状。
  • [ ] 我观察到该修复实际上修复了该错误。
  • [ ] 我为每个已解决的错误添加了回归测试。