狙击手修正弹道看三个变量:距离、风速、温度。差一点,落点就偏很远。

写代码出问题其实是同一件事:现象摆在那儿,原因藏在几个变量里。区别是风会变,Bug 不会——它每次都按同样的规律错。

我的三步

一、先复现,别急着改

不能稳定复现的问题,先别动代码,先让它稳定出现。加日志、加时间戳、把随机输入换成固定输入。

我见过最浪费时间的一幕:有人对着"偶发"的 Bug 改了三小时,然后宣布"应该好了"。"应该"这两个字的含金量,约等于零。

二、二分法,缩小范围

一半一半地排除:注释掉一半、关掉一半、只留一半。前端还是后端?接口还是渲染?配置还是代码?每排一次,范围减半,二十次之后剩下的东西藏都藏不住。

Git 里有个 git bisect,干的就是这件事——在一堆提交里对半砍,找出把问题带进来的那一次。我用它抓过一个"三周前就埋下"的坑,全程不到二十分钟。

三、一次只改一处

改完马上验证。同时改两处,你不知道是哪一处起的作用——下次再出问题,连自己动过什么都得翻记录。

一次真实事故

站刚上线那阵,页面突然全变 502。我按顺序查:

  1. 容器活着吗?docker ps —— 活着

  2. 反代指向的端口,跟容器映射的端口一致吗?—— 不一致

  3. 为什么变了?一次例行重装,配置回滚到默认端口

  4. 日志里有更早的线索吗?有。前一天就开始零星报错,我以为是一次网络抖动

真正的问题不是端口,是我把"零星报错"当成了正常。

三条经验

  1. 日志不是给"以后出问题"准备的,是给"现在就能看懂"准备的。

  2. 假设要能被推翻。说不清怎么验证的,那不叫假设,叫猜。

  3. 修完写下来。不写,三周后你还得重新想一遍,顺便骂自己记性差。

给维修工的备注:改代码之前先 git commit。不信的话,问问我那块焊废的主板。

—— 音葵

修完那天是凌晨两点。这篇的草稿就是在值班室开的头,写了三天才写完。