调试陷阱:如何陷入三小时追踪「完美」代码 bug
分析程序员常见的调试误区和认知盲点,看似完美的代码反而隐藏最难发现的问题。
分析程序员常见的调试误区和认知盲点,看似完美的代码反而隐藏最难发现的问题。
上周二,我花了三个小时追踪一个根本不存在的 bug。
代码看起来完美无缺。语法正确,遵循了最佳实践,甚至有贴心的注释解释每个函数的功能。问题是,其中一个函数在解决一个我从未要求它解决的问题。Claude 凭借其无穷的模式匹配智慧,决定我的 API 端点需要分页。我没有要求分页。我不想要分页。但它就在那里,以某种方式破坏了我的响应结构,诊断这个问题花费的时间比我从头写一遍还要长。
这就是 66% 问题。
根据 Stack Overflow 对超过 90,000 名开发者的最新调查,66% 的人表示对 AI 编码助手最大的挫折是代码"几乎正确,但不完全正确"。另外 45% 的人表示,调试 AI 生成的代码所需的工作量得不偿失。
我发现这些数字有种莫名的安慰。不是因为我享受痛苦,而是因为这意味着我没有疯掉。那些本应让我更快的工具引入了一类三年前不存在的新 bug:看起来像是有效代码的 bug。
问题在于完全错误的代码。它失败时很大声。它抛出错误。它拒绝编译。你的测试套件能捕捉到它。你修复它,然后继续你的生活。但几乎正确的代码呢?那是能通过你的测试、部署到测试环境的代码,然后在凌晨 2 点做出某些微妙的疯狂行为——此时你最大的客户恰好在运行一个你忘记他们在运行的批处理作业。
老的 bug 是诚实的。它们会宣布自己。这些新 bug 很礼貌。它们会等待。
我专业地写代码已有数十年……我犯过你能犯的每一个错误。我发布过 SQL 注入漏洞。我意外删除过生产数据。我曾经重新映像了一个生产数据库并把自己锁了出来。那些是我的错误,当它们爆炸时我立即理解了。反馈循环很紧凑:我做了蠢事,系统抱怨,我学会了不再这样做。
AI 生成的 bug 不是这样工作的。现在当出问题时,我的第一个问题不是"我做错了什么?"而是"AI 做了什么我没注意到的?"这是一种根本不同的调试方式。我不是在理解自己的逻辑,而是在逆向工程别人对我可能想要什么的假设。
微软研究院在今年早些时候发布了一项量化这一点的研究。他们在 SWE-bench Lite 上测试了九个不同的 AI 模型,这是 300 个真实世界调试任务的基准。最好的表现者 Claude 3.7 Sonnet 解决了其中的 48.4%。少于一半。这些不是奇特的边界情况。它们是那种不会绊倒经验丰富开发者的 bug。
这些模型在写代码方面非常出色。但它们在修复代码方面举步维艰。
当你想到它们如何工作时,这在某种程度上是有道理的。代码生成是模式完成。你给模型一个 prompt,它根据数十亿个例子预测接下来可能会出现什么代码。这对于样板代码、你忘记的语法、探索陌生的库来说确实很有用。但调试不是模式完成。调试是假设测试。它需要理解代码应该做什么,它实际上在做什么,以及为什么这两件事不同。
那个"为什么"正是一切崩溃的地方。AI 不知道你的系统为什么以这种方式构建。它不知道你的 CEO 在 2019 年坚持的那个业务规则,这个规则没有逻辑意义但占了你收入的 40%。它不知道你的数据库 schema 有一个怪癖,因为你在十五年前从 Oracle 迁移过来,没人想去碰它。它只是看到模式并匹配它们。
METR 在 2025 年 7 月的随机对照试验发现了一些应该让我们都关注的东西。他们让经验丰富的开源开发者在有和没有 AI 协助的情况下完成任务。AI 组平均慢了 19%。但令我夜不能寐的是:他们认为自己快了 24%。开始前,参与者预测 AI 会加快速度。完成后,即使结果更慢,他们仍然认为它有帮助。
我们不仅仅得到了几乎正确的代码。我们得到了几乎正确的代码,同时感到有生产力。即时完成的多巴胺奖励掩盖了在我们身后积累的调试债务。
我不会告诉你停止使用 AI 工具。我经常使用它们。但我开始以不同的方式对待它们,与一年前不同。我过去接受建议然后继续。现在我读每一行代码,就像它是由一个非常自信但能力一般的初级开发者写的。因为本质上就是这样。
那 66% 的人不是在抱怨这些工具不好。他们是在抱怨这些工具好到足以造成危险。一把漏掉钉子的锤子很烦人。一把击中几乎正确位置的锤子是你最终得到歪斜房子的原因。
我没有解决方案。我不确定有人是否已经有了。这些工具会变得更好。上下文窗口会变长。模型会学会提出澄清问题而不是假设。也许吧。
在那之前,我会保持我的 print 语句在身边,我的测试覆盖率更近。有些技能不需要自动化。它们需要被磨砺。
有些评论可能只对已登录访问者可见。登录查看所有评论。
进一步操作,你可以考虑屏蔽此人和/或报告滥用。