POST://debugging-systematic-method
带点橘子味的馒头的头像
带点橘子味的馒头

FRONTEND / DESKTOP DEV

返回文章列表

调试不是玄学:我排障时的固定四步法

1 分钟· 988 1 次阅读

带团队时我常被问:"你是怎么这么快定位到问题的?"其实没什么天赋,只是我不靠"感觉",而靠一套固定流程。调试最贵的从来不是时间,是被假线索带偏的方向

第一步:稳定复现,先别急着改

不能复现的 bug,等于没修。先回答三个问题:

  • 在什么操作序列下必现?是"点一下就崩"还是"点十几下才崩"?
  • 环境是否相关?浏览器版本、是否登录、数据是否为空?
  • 能不能写一个最小复现(minimal repro)?

我踩过最大的坑之一:凭记忆"大概是这样操作就出错了",结果花两小时改了一通,发现复现路径根本记错了。先拿到一条能反复跑通的复现路径,再动手。

第二步:二分定位,把范围砍到最小

别从头读代码。用二分法快速锁定"坏掉的那一层":

  • 前后端之间:先用 curl / 浏览器网络面板看接口返回对不对,确定是前端渲染错还是后端数据错;
  • 函数之间:在关键节点打日志或断点,看数据在哪一步"变形";
  • UI 问题:把样式一层层剥掉(或逐层加),定位是哪条规则在作妖。

一句话:让证据说话,而不是让猜测主导。

第三步:建假设,再验证

定位到范围后,写下你的假设——"我怀疑是 X 导致的",然后设计一个能证伪它的实验

假设:列表错位是因为 flex 容器宽度被某个子项撑开
实验:给该子项加 max-width: 0,看错位是否消失
结果:消失 → 假设成立;没消失 → 推翻,换下一个假设

关键是一次只改一个变量。同时改三处然后"好像好了",你永远不知道是哪处生效,下次还会踩。

第四步:验证 + 防回归

修完别急着关。做两件事:

  1. 确认复现路径已不通,且在相邻场景(边界值、空数据)下也不崩;
  2. 留一个防回归的东西:一条单测、一段断言、或一个能一眼看出问题的日志。否则三个月后同样的坑还会再来。

那些年踩过的"假线索"

假线索 真相
报错栈指向的第三方程序库 实际是自己传了 undefined 进去
"只在我机器上崩" 其实是环境变量 / 缓存 / 依赖版本不一致
改了 A 就好了 其实 A 根本没生效,是 HMR 偷偷重载了 B
日志没打印 → 没走到 可能是日志级别被过滤,而不是代码没执行

最阴险的是最后一条:我曾有次坚信"函数没被调用",反复查调用链,最后发现是日志级别设成了 warn,debug 全被吞了。证据不足时,先怀疑你的观测手段,再怀疑代码。

一个真实案例

有次一个 LAN 聊天界面偶发卡死。直觉告诉我"WebSocket 断了没重连",但复现后看网络面板——连接好好的。二分后发现是前端一个 setInterval 在收到高频消息时不断 setState,攒出成千上万个待渲染节点。

假设从"网络层"转向"渲染层",关掉那个定时刷新、改成消息到达时增量更新,卡顿消失。如果当初顺着直觉去改重连逻辑,只会越改越乱。

小结

我的调试四步法就四句话:

  1. 先稳定复现,拿不准就先别改;
  2. 二分定位,让证据说话;
  3. 建假设再验证,一次只动一个变量;
  4. 验证 + 留防回归,别让同一个坑来第二次。

技术栈会变,但这套"先证伪、再动手"的节奏不会过时。调试不是玄学,是把不确定性一个个关进盒子里。

相关文章