计算思维不是算数能力,那它到底是个啥?聊聊我修bug时悟出的东西

🔑 关键词:计算思维,编程教育,算法思维,调试,逻辑思维

📖 摘要:从一个调bug到凌晨三点半的真实经历出发,重新定义计算思维的核心不是正确而快捷地解题,而是愿意接受错误、缩小错误范围的能力。本文也提供了几个不用写代码也能培养这种思维的土办法。

我到现在都记得那次调bug的夜里。2019年11月30号凌晨4点,我手里的一个数据处理脚本崩溃了,后台提示task failed,但没有日志。30万条用户数据,重跑一遍要两小时,可早上客户就要报告。我第一反应是重启服务器、检查内存,全都没用。最后我把脚本拆成十段,每段末尾塞一句print输出,顺着最后一次正常打印往回找。其实这就是二分法查找。折腾到上午十点,终于定位到一行时区换算的代码:数据库存的是UTC,我直接偏移了八小时,可当天服务器正好在某个时区切换日,多翻了一小时。这个bug在历史上只出现一次,却让我想通一件事——计算思维真正考验的不是你会不会又快又准地解题,而是你肯不肯承认自己猜错了,然后一条条排除掉错误答案。

图片

学校教的计算思维四件套:分解、模式识别、抽象、算法。这些没错,但更像是事后整理出来的方法论,像验尸报告。真实世界里的计算思维,是在panic之后还能不能保持对错误的兴趣。我见过不少编程新手,他们不是不会写循环,而是终端一报错就慌了,立刻把代码删了重写。老手反而会读一下报错信息,把问题切开,甚至故意造一个错误去看系统怎么反应。程序员本质上是职业怀疑论者。人和机器最大的差别是:电脑面对同一个bug每次都会给出相同结果,人却经常带着情绪和偏见去处理同一个问题。所以我渐渐觉得,这种容错思维是可以迁移的——比如你被同事甩锅的时候,别急着辩解,先把事实、假设、情绪分成三份。这就是一次栈溢出的排查思路,跟代码没有关系。

图片

另外还有一个更野的观点,我一直想说:计算思维本质上是一套「认知卸载」的秩序。人脑的短期记忆容量大概只有4±1个单元,遇到一团糟的事情基本转不动。而电脑可以把成千上万个状态存在硬盘里,不高兴了随时重新算。所以写代码的人最常做的事其实不是坐在那儿瞎想,而是把自己的想法变成流程图、状态机、变量表,然后扔给机器去跑一遍,用结果反推思路哪里不对。我以前觉得用数学建模分析迟到很蠢,但后来我真的把闹钟、地铁限流、开会时间画成了状态转移图,才发现自己每天迟到根本不全是懒,而是状态机里缺了一个「出门前查地铁延误」的动作。这个发现比看什么时间管理鸡汤都好使。再拿栈来说,你正在写方案,突然微信弹了个消息,你切过去回一句,再切回来——这就是一次压栈和弹栈。一天切几十次,栈不溢出才怪。程序员都知道乱用并发会死锁,那我们安排自己的日程时,是不是也该考虑给自己加把锁?

图片

所以你要问我怎么培养计算思维,我反而会劝你别一上来就学Python、刷LeetCode。那些东西太消磨人了,对新手特别不友好。我自己的土办法是:先挑一个真实让你烦躁的小问题,比如“为什么我又找不到钥匙”。把它画成一条流程线——从进门开始,你的手放在哪,包放在哪,钥匙落在哪,每个容易出错的环节全标出来。然后人为改变其中一个条件,比如逼自己钥匙永远只扔鞋柜上的碗里,试两周,看会不会好一点。这其实就是设计实验和单变量控制。等这个玩腻了,再把你每周的遗憾做成一个错误清单,每一条错误配一个假设,失败了就在假设上打横线。我坚持过八周,每周只花一个小时,最后我发现自己对“不确定”这件事没那么害怕了。没有炫技的高深算法,但这个练习会逼着你像编译器一样从头到尾检查自己的思维路径。

图片

所以算下来,我理解的这种思维智商门槛不高。它更像一种态度:允许自己出错,然后把错误当成信号灯,而不是耻辱柱。就算你不写代码,做菜烧糊了、约会迟到、月底对不上账,都当成一个系统输出不符合预期,然后一步步去缩小出错模块。那次修完bug后,我每遇到糟心事都会下意识做一件事:先把抽象情绪降成具体问题,再判断是假设错了,还是环境变了。可惜我不是第一次调bug就懂得这个道理,而是在排查了三十万条数据里的那一条时才记住。别把计算思维抬得太高,它不过是帮你在混乱里拆出一个最小可验证的单元,再鼓起勇气对周围人说:我错了,但错误范围已经小多了。

图片