我是如何学会编程的

说来惭愧,我学习编程的路径可谓艰辛,用了三四年才初窥门径。我不像很多程序员有天纵之才,也不像一些朋友很早就接触编程,无论是起步时间还是学习速度,我都落下很多,但这并不影响我最后掌握了这项技能。

所以这篇文章我想讲讲我——作为一个普通人——学习编程的经验,主要是三次“开窍”的心路历程。

如何定义学会

在我的理解中,编程是一项技能,和骑车游泳无差。学会编程,只意味着能用代码把想法变成现实,不是掌握什么高深的算法,也不是入职什么大型公司。比如有的会计朋友,学了点 VBA (opens in a new tab) 使自己在 Excel 中数据处理效率更高,我认为就算是学会编程了,再比如一些公众号作者学会用 AI 生成营销文,输入几个关键字就能自动生成一篇毫无营养但能卖钱的文章,也是算学会了。所以学不学会取决于你的目标,如果你是把将来从事程序员这个职业当作学会编程的目标,那么拿到任意技术 offer 就算学会了,不必妄自菲薄。

起步晚

我是直到大二才懵懵懂懂开始学习编程,不像我的一些朋友,小学就接触编程 (opens in a new tab)。尽管我家里有电脑比较早,但一直都沉迷游戏。高中时用 PhotoShop 和一些视频剪辑软件居多,却从未想过编程,因为我完全没有编程这个概念。就像你想学一个东西,却不知道从何搜起一样。“编程”这个关键字,是没有存在于我的脑海之中的,这就是我常说的“我不知道我不知道 (opens in a new tab)”的那部分知识。

高三填报志愿时,所有志愿的专业那栏我写的都是“计算机科学与技术”,当时虽然看了很多专业介绍,但实际上我是完全不知道这个专业是去学什么,可见我当时眼界之窄。连周边的家长们都说,这个专业没前(钱)途,“去了就是玩游戏”!

万万没想到一语中的......我本科大学的宿舍刚建好,根本没有接网线,再加上大一一整年没有专业课,所以虽然父母给我买了台联想 Y460,但只能玩玩单机游戏,或搞个局域网联机 Dota。直到大二,我们开设了一门《C语言教程》才算是真正开始了编程的学习。

说了这么多废话,我真正想说的是:如果你还处于这个阶段,应该尽可能提升眼界,接触那些“关键词”。在知识没触碰到自己之前,是没有学习动力的,更不会知道如何开始。

漫长的入门期

自学

大二,口播 PPT 是老师典型的教学方式,再加上严重的口音,对于完全没基础的我,真的很难跟上。我觉得这种课再上下去也意义不大,于是自己找了一些书学了起来。当时在图书馆反复比对,选中了大师 Kernighan (opens in a new tab)Ritchie (opens in a new tab) 的经典《C程序设计语言》 (opens in a new tab),当时的想法是,直接读 C 语言作者的书一定是深入浅出、化繁就简。没想到,书虽然好,但不适合新手。我是连开发环境都完全不会搭建的(就是说连在哪写代码都不知道),更别提按照书上的习题练习了,读了几章,不知所云。

这件事给我的启示是学习不一定要从经典开始,而是要从适合自己的开始。如果连怎么开始都不知道,就找一本大白话的“21天入门”之类的书,先对要学的东西有个笼统的认知再去学,这也是获取搜索关键字的最快方法。

这样断断续续又过了两三个月,学校里的课都快上完了,我还是没能运行一个简单的程序,非常废柴。不过这段时间我也没闲着,一直在研究学习方法,我发现视频对我来说是更友好的知识吸收方式,于是我搜索了一些视频教程,综合判断下来,我选择了郝斌C语言自学教程 (opens in a new tab),并开始了自学之路。我那个年代是没有 B 站的,我把所有视频都下载到电脑里,一集集看,反复地看。郝斌的北方口音让人亲切,他把视频按知识点切分而不是时长切分,每一集都用知识点的名字命名,这样非常方便回看复习。直到今天我都对郝斌老师心怀感激,尽管素未谋面,但把教学视频共享出来,并且教学方式从零出发、授人以渔,真的是做到了传道授业解惑。后来的数据结构 (opens in a new tab)我也是看郝斌老师的视频入门。

另外,当时的 CSDN (opens in a new tab) 还不像现在这么恶心,上面优质博主不少,我从各类博客中也收获颇丰,这段学习历程的总结我也是看我自己的知乎回答 (opens in a new tab)才回想起来。对我影响最大的应该就是程序员技术练级攻略 (opens in a new tab)刘未鹏的博客 (opens in a new tab),时至今日都不过时。

开窍

大三之后,我已经学习了 Java 和 C++ 等传统万能语言。因为课程里都有,所以我也就跨过了“究竟学 C++ 还是学 Java”的迷茫期。这段时间做了很多重复的事情——看书、做题、参加比赛,其实水平没有多高,很多题都不会做,很多书也看不懂,但一直在重复,没有停歇。

当时 Symbian (opens in a new tab) 青黄不接、Android 蓬勃发展,随着搜索能力和学习能力的提升,我接触到了开源社区与开源精神。偶尔徜徉在 GitHub 的海洋里,Jake Wharton (opens in a new tab) 成了我的偶像,因为无数的 Android APP 需要用到他的库。我的毕设做了一个 ToDo APP,基本上是从 GitHub 上东拼西凑的,里面的一些可视化图表,都是用 OpenGL 实现的。当时几乎一心扑在 Android 开发上,还大言不惭地去知乎回答了如何通过自学成为一名 Android 应用开发工程师? (opens in a new tab)

开窍”是我描述结束入门期的词,也基本上是一个量变到质变的过程。从小到大,为了开窍,我一直都是笨人笨办法。中学的我,化学成绩奇差无比,几个月都没有起色,于是我就盯着课本和辅导书看,一遍又一遍,很枯燥,但一直看,最后逐渐从懵懂到清晰。

我认为学习从来不是一个线性的进步过程,是某一天突然就开窍了。开窍之后,仿佛看什么都变的简单,我想这主要来自于信心,只有不惧怕自己不会,才能掌握它。

走出校园,转行 Web 前端

大学毕业后,我第一家公司还处在初创阶段,极其扁平化。本来是入职去做 Android 的,结果第一周还没完就被告知说“我们 Android 还有点遥远,要不先做做网页开发?”,当时觉得 Web 也是 UI,看起来很有趣,就直接答应了,没想到从此一头栽进了 Web 前端的深坑。

我入场 Web 的时候,jQuery (opens in a new tab) 仍在大行其道,完全不需要懂 JavaScript 就能开始。这时候不得不提到 J 哥了,当时 J 哥算是我的上司,让我一个人开发一个问答页面,样子有点类似知乎。对于还没有看完 jQuery 文档的我,完全不知从何下手。如果用 Android Studio (opens in a new tab) 的话,import export 以及各种 code snippet 都有现成的,Java 也有各种最佳实践,所以不用操心太多。但换到 JS 这种特别灵活的语言我就直接懵了。其次还会用到一些 jQuery Plugin,我也不知道如何组装。最后最关键的是,我不知道如何把现实中的 UI 操作和逻辑抽象映射到 Web 前端的代码上,这和学校里的做题思维是完全不一样的。

见我磨蹭了两三天都没憋出几行代码,J 哥直接说:“算了,我来带你做吧”,当时我觉得他背后溢出了佛光。那个下午,可能是我编程生涯成长最快的下午 (opens in a new tab),J 哥带着我一行一行敲代码,我站在旁边,他边写边解释:

而且整个过程是磕磕绊绊的,很多时候在推翻半小时前的自己:重写,重构,不断 debug,这也让我明白了,

从那之后,我好像又开窍了一次,写前端再也不费劲了。接下来我还读了一些入门书《JavaScript DOM编程艺术》 (opens in a new tab)《JavaScript高级程序设计》 (opens in a new tab),算是真的转型了前端。

快速掌握核心科技

后来随着学习的深入,自然开始接触当时势头正盛的 node.js (opens in a new tab)《Node.js开发指南》 (opens in a new tab)是我看的第一本 nodejs 的书,作者是 Byvoid (opens in a new tab),明明是同龄人,他在出书,而我在看他的书,不禁汗颜。看完的第一感觉是 node.js 真厉害,但我还是不知道怎么用和用在什么场景,可以看出我在初学一门技术时的体感是多么差。

后来 Howard (opens in a new tab)ruby-china 社区 (opens in a new tab)发帖搞远程教学,项目是自己实现一个 Express.js (opens in a new tab),于是果断报名。教学的形式就是阅读 Howard 写的教程,然后尝试自己实现,实现过程中遇到问题直接问他。教程短短几篇,知识从 JS 基础覆盖到 node.js 核心 event loop 机制。整个学下来,教学的形式已经不重要了,最关键的是我领悟到一个道理:

编程只是一个工具,学习一门技术的时候要快速掌握其最核心的部分,抛弃细枝末节,直接动手实现目标,中途遇到不会的再 Google 即可。这样才是高效快速的学习方式。

学会这个思维的好处是,我后来学什么都特别快,自我总结出一套学习方法 (opens in a new tab)。但坏处是知识点掌握的不牢靠,很多细节需要现学现卖,这在日常编程中好像没什么影响,随手 Google 随手写,但面试就很差了,毕竟面试是通过考察细碎的知识点来衡量你的知识面(我不苟同这个面试方式,但确实是现在最流行的)。

至此,我终于觉得我学会了编程。后来无论是做什么开发,都是预习一天直接动手。但在这之前,我经历了漫长的入门期。如果你仔细阅读就发现,当时我每次接触到新技术都非常慢热,尤其是第一阶段是最难熬过,看着晦涩难懂的术语抓耳挠腮。没办法,万事开头难,专业术语的发明是为了提升行内人沟通的效率,却无形给行外人增加了学习门槛。熬过这一阶段的方法无它,唯有重复。

学习历程是阶梯式的,学习效率是指数型的。

后来每每有人问我:这个语言是不是更容易些?学哪个最快?一两个月能不能学会它?我都觉得难以回答,这第一取决于你的目标,第二取决于你多快能跨越入门期。

掌握一项技能是需要时间和实践的,降低预期,慢即是快。

最后写完,有些感慨,在成长过程中有些人对你的影响总是比他自己想象的大。写博客的一个意义也在于此罢,跨越时空去帮助别人,哪怕是一点点也很奇妙。