今天分享一下自己这些年来学习编程的一些体会,来阐述一个朴素的道理和原则。而好多初学者并不太明白这个道理,所以在学习过程中会有迷茫感。
我是 2004 年上的大学,当时读的是信息安全专业。在上大学之前我没怎么用过计算机,可以说是完全的小白,而且我觉得自己的数学一般,算是一个资质平平的小白。
当年我们学校还规定大一新生不准自己带电脑进宿舍,所以大学第一年我也没怎么写过代码。我记得当时我们上 C 语言的课,每周大概有一两次去学校机房敲代码,机房里装的是 Turbo C,至今印象深刻。
因为我完全是小白,键盘都不太熟悉,所以我是完全照着书上面的例子敲的。
而后的三四年里,我买了自己的台式机,平时也写了一些简单程序,但我花费了更多的时间去折腾 Linux 系统。那时候 Linux 发行版本 ubuntu 会免费给学生邮寄光盘,我每年都申请一个新版本,所以毕业时一袋子 Linux 系统光盘。
我本科期间因为各种原因蹉跎了很多时间,可以说编程并未入门。那是什么感觉呢?就是看起来都好像懂点,自己写起程序来就没底。比如数据结构和算法,我虽然知道很重要,但就是没太学懂,考试过了却不知道实际应用。看相关的书籍,如果没有现成的代码我就总感觉少了点什么,有些困难。
后来我就考研了,当时我也没太想明白为什么要读研,算是还没准备好参加工作,还想在学校待两年。读研期间我在实验室跟着做一些科研项目,编程做得也不算多。
2009 年一次偶然的事情改变了我。那天我大概是看到了一个介绍 PKU JudgeOnline - POJ 的网页,然后想起自己 2006 年注册过账号,我就重新登录了进去,没想到从此的一年多时间里,我基本天天泡在上面写程序。
我不是为了参加比赛,而只是偶然陷入了进去,然后就变得沉迷。我基本从早上九点到实验室,到晚上十一点左右离开实验室。我从一些简单的算法开始写,有时候是按照某些分类去做,实在想不出来就去评论区和别人的博客看解题报告。
现在回想起来那一年算是自己最专注的学习编程的一段时间,我记得有一次神奇的体验,有次我一直在想一个算法问题,然后在梦里还在做,第二天醒来后居然能回忆起梦里的方法,最后实现出来居然是对的。
这种忘我的、愉悦的心流体验非常难得,以至于在十年之后,当我遭遇焦虑时仍用这种办法来解决。
在这一年多的时间里,我基本刷完了 500 道题目。其实每个程序通常都比较短,算 100 行每道题的话我也就写了 5 万行代码。
就是这 5 万行代码彻底提高了我的编程能力,感觉就好像就是突然上道了。我对算法和数据结构没有了恐惧感,变得更有耐心,我看其他技术书籍也没任何困难,学习编程语言,框架类的东西快多了。
在 POJ 上做编程题和自己学习数据结构、算法有什么区别呢?后来我明白,其实我经过了一年多刻意的有效练习,这种在线编程的练习有几个好处:
- 可以获得即时反馈,一个程序是否通过都是确定的,到底是 Wrong Answer、Memory Limit Exceeded、还是 Time Limit Exceeded
- 可以跟踪和量化,我学会了哪些,比如 DFS、BFS、DP、Tree、Graph 等都是可以追踪和量化的
- 可以和其他人交流
在这种练习中,我通过写获得了编程的“语感”,也提高了阅读源码的能力。写代码和写作差不多,编程无非是通过代码来表述自己的想法,需要不断地练习。
关于这一点我后来看到硅谷王川的表述非常好:
所有的我们以为的质量问题,大多本质是数量问题。因为数量不够,差几个数量级而已。
数量就是最重要的质量。大部分质量问题,在微观上看,就是某个地方的数量不够。
最大的误区是,明明是数量不够的问题,因为错误地以为瓶颈在于质量,幻想在不增加数量的前提下,用某种奇技淫巧,偷工减料达到目的。这时候玄学,迷信和各种无病呻吟就出现了。数量不够,底子不够厚时,很多事情时做不到的。即使有时看似有捷径,欠的账迟早是要还的。
有的初学者在量没达到的情况下,怀疑自己的学习方法有问题,然后再怀疑是不是编程语言没选对,试其他的办法又没法长久坚持,最终导致自己好像一直没上道。如果没有写到足够的量,任何方法都是无法阶段性提高自己。
这个量就像是一个门槛。
任何复杂技艺的学习都是有门槛的,通过这个门意味着构建了做这行的韧性和耐心,也可以说是找到了里面的乐趣和成就感,这些是深入下去的基础。
在纪录片寿司之神中有一个片段:
在小野二郎的店里做学徒,先要学会的是拧毛巾。毛巾是刚从开水中蒸出来的,温度骇人,食客使用都需要晾凉。而在这之前,学徒要将其捞出,并拧至全干。
这种训练非常辛苦,但如果学不会的话,就不能去碰鱼。接着,学徒要学会用刀料理鱼,10 年后才会被允许去煎蛋。
资深学徒苦修 4 个多月,失败 200 多次,终于做出了人生第一个“合格”的玉子烧。
训练和衡量一个飞行员,我们说他累计飞行时间多长;训练长跑运动员,衡量标准是每天跑多少公里;那衡量一个编程初学者,有效编程行数就是一个很好的指标。
编程中的有效练习不是拷贝粘贴代码,也不只是读代码,而是自己从头到尾去思考,去写出来,然后出了问题自己去调试。
在 LeetCode 上写也很不错,你可能对算法不感兴趣,那可以去做游戏、Web 应用开发、后台开发等等项目,找到自己感兴趣的方向作为突破口,然后持续积累到一定程度的代码量,比如三万行代码,那编程自然就入门了。
就编程来说,三万行代码这么明确的一个指标,实际上大部分人做不到。以大多数人的努力程度之低,根本轮不到拼天赋。不信你可以问问,即使是大学计算机专业的学生,很多人毕业的时候并未完成过 3 万行有效编程的这个量。
有了这种体验,我培养出了作为普通人学习掌握技能的耐心。类似编程,那些难以获得、需要不断锤炼的技能,例如写作、英语、钢琴、绘画等,前期都需要一定量的积累,我们要做的是找到有效练习的方式,持续投入再阶段性回顾。
这个月我在锻炼写作能力,因此我一个月写了接近 15 篇文章,自我感觉确实有提高了不少,而且在这段时间里我克服了心理问题,解决了写作的流程、和工具的问题,所以我也不感觉到迷茫。
总而言之,编程初学者不要想着捷径。每个人的方法都可能会有所差别,他人的路径不一定适合你。唯一的共同点是得有量的积累,先在键盘前敲起来,敲几万行代码后你就没有入门学习这类的疑问了,下一阶段是如何写得更好,如何用编程解决现实问题了。