为什么你debug总比别人慢?
为什么你debug总比别人慢?
你遇到一个bug,第一反应是什么?
“改改试试呗。” 于是你改了20个地方,重启了5次服务,清了3次缓存,删了node_modules重新装了一遍。4个小时后,bug消失了。你长舒一口气,提交代码,写上commit message:”fix bug”。
但你心里清楚——你根本不知道到底是哪个改动修好的。
而你旁边工位的senior呢?他遇到同样的bug,打开日志看了两分钟,在代码中间加了一行console.log,跑了一次,锁定了出问题的函数,改了一行代码,30分钟收工。
同样一个bug,你用了4小时,他用了30分钟。差距在哪?不是他比你聪明,不是他写代码比你多,而是他脑子里装着一套你没有的东西——排除法思维。

你以为debug靠经验,其实靠的是方法
很多初级开发者有一个误解:senior debug快,是因为他们”见过的bug多”。好像debug这件事,就是一个大型的”连连看”——见过的bug越多,匹配得越快。
这个想法有道理,但只对了一小半。
真实情况是:senior遇到一个从没见过的bug,照样能比你快5倍定位出来。因为他依靠的不是”我见过这个”,而是一套系统的排除流程。每一步操作都在缩小范围,而不是在碰运气。
你debug的方式像什么呢?像在一个黑屋子里找钥匙,你闭着眼在地上乱摸。运气好,摸到了。运气不好,摸了四个小时。
senior的方式是:先开灯。
他会先搞清楚钥匙大概在哪个区域,然后把这个区域再切一半,再切一半——三四次之后,钥匙就在手里了。
那”开灯”具体意味着什么?意味着你把时间花在了正确的地方。
70%定位,30%修复——你搞反了
程序员圈子里流传一个观察:优秀工程师处理bug时,70%的时间花在”定位问题在哪”,只有30%的时间花在”修复”上。
初级工程师恰好相反——30%的时间在定位,70%的时间在瞎改。
想想也合理。一个bug修好可能就是改一行代码的事,但找到该改哪一行,才是真正考验你的地方。就像医生看病,开药可能就一分钟的事,但诊断才是核心能力。
修bug不需要技术,找bug才需要思维。
你改了4个小时,其实3个半小时都在做无用功——因为你在改错误的地方。如果你花30分钟先定位准确,后面只需要5分钟就能修好。
这不是数学游戏,这是真实的效率差距。

好医生不会上来就开药——debug也是
你肚子疼去看医生。碰上庸医,听你说”肚子疼”,直接开了胃药、止痛片、消炎药。吃了三天没好,换了个药又吃三天。折腾一周,自愈了——他还跟你说”看,我的药管用了吧”。
好医生怎么做?先问你:什么时候开始疼的?吃了什么?疼在哪个位置?然后做检查排除可能性,定位原因,对症下药,两天搞定。
debug的逻辑一模一样。你不需要”见过所有的bug”,你需要一套排除流程。我把它提炼成四步,下次遇到bug直接用。
第一步:复现——先把bug拴住。
很多人遇到bug第一反应就是改代码。等等,你连bug都不能稳定复现,你改什么?
你可能也经历过类似的场景:花了整整两天追一个”偶尔出现”的bug,最后发现它只在用户头像URL包含中文时触发。如果一开始就花20分钟找到复现条件,后面根本不用折腾那么久。
能稳定复现的bug就是被拴住的狗,跑不掉的。不能复现的bug是野鬼,你追它它就消失了。所以第一优先级永远是:找到稳定复现的步骤。
第二步:二分法——每一刀砍掉一半嫌疑犯。
这是整个方法的灵魂,也是senior和junior最大的分水岭。
原理简单到有点无聊:在代码执行路径的中间加一行日志,看数据到这里是对是错。对的话,问题在下半段;错的话,在上半段。然后对出问题的那一半再切一刀。
一个涉及1000行代码的bug,用二分法最多10次就能定位到具体那一行。而”改改试试”的方法?理论上你可能需要试1000次。
这就是算法思维和人肉穷举的差距。
第三步:最小复现——给bug做一次”裸奔测试”。
定位到大概区域后,做一件反直觉的事:开始删代码。删掉所有无关的配置、依赖、业务逻辑,只留能触发bug的最少代码。
这一步经常让人拍大腿——”我靠,这行删掉bug就没了!”
最小复现是debug的照妖镜。代码越少,bug越无处藏身。很多时候你还没删完,答案就自己蹦出来了。
第四步:修完之后,问自己一个灵魂问题。
别急着关编辑器去摸鱼。问自己:我能解释为什么它之前不工作吗?
“因为这个变量在并发场景下会是null,而代码没有处理null的情况”——这叫修好了。
“我也不知道为啥,反正改了就跑通了”——这不叫修复,这叫掩埋。被掩埋的bug不会消失,它只是在等一个更尴尬的时机回来找你——比如你老板在演示的时候。

这不只是debug,这是你最该练的思维肌肉
回到开头那个场景。你改了4个小时,本质上是在用”人肉穷举法”——把能改的都改一遍,看哪个能碰上。bug简单时这招确实管用,但遇到稍微复杂的问题,你就掉泥潭里了。
而二分排除+假设验证,是一种逻辑推理。它不要求你见过这个bug,不要求十年经验,只要求你在动手之前冷静三秒钟,问自己一个问题:“我怎么用最少的操作排除最多的可能性?”
有意思的是,这套方法不只在写代码时管用。服务器挂了排查原因——用它。家里WiFi突然断了——也是先看路由器灯,再看是单个设备还是全挂,一层层缩小范围。甚至你找不到钥匙的时候——先确认是出门前还是回来后丢的,瞬间排除一半地点。
所有”找原因”的场景,都是排除法的主场。
所以下次遇到bug,忍住。别急着改代码。花5分钟想清楚:我要怎么缩小范围?
这5分钟省下来的,不只是4个小时——是你头发的数量。