关于学习编程的一箩筐问题

less than 1 minute read

两个月前和 16 岁 JK 美少女 @-顾兮- 一起吃饭的时候聊到了计算机教育入门的话题。之前虽然我写过一些批判培训班的文章,但是所谓只破不立,至于到底怎么学习是对的,很难有个界定标准。想到今天睡不着觉,于是想到以后如果再有微博私信问计算机教育空洞而广泛的问题的话,这篇文章将是我想说的全部答案。

为什么需要编程?

以前我喜欢把这个问题表达成「为什么要学习编程?」在收到了不少「为了钱」这样的答案之后,我决定换个方式来问这个问题。「为什么需要编程?」如果你提供编程的服务,而别人为此付钱。别人为什么付钱?别人为什么要从你这里购买服务?这个答案最宽泛的回答就是「我们用编程来解决问题。」

人们的日常工作生活有大量的问题,比如低下的沟通效率、低下的执行效率等等。而我们使用编程的技术,来帮助人类解决这其中的 一部分 问题。而这,是编程的根本意义。

学习编程的前置条件

显然地,编程不是魔法。要想写代码,事实上随便学习一下,几个月能写出一些东西我想是没有问题的。这也是为什么那么多培训班能存活下来的原因。但要想写好代码,两个必不可少的因素是对数学的敏感和放洋屁的能力。这两点既需要人的一些天赋,亦需要长时间的训练才能达到。

对于数学的敏感性不是指对算术的敏感性。中国人扎实的基础教育让大家对算术都很敏感,去买个菜从来不会算错找零钱。但事实上,在编程中,算术问题是极易通过计算机来解决的。人所要做的,是如何让计算机解决问题。要想做到这一点,要有能很好地将现实中的问题转换成清晰、直观的数学模型的能力。

而放洋屁的能力关键落在编程的社会性上。我知道不少因为英语问题而被严重困扰的码农们的日常。虽然大多数东西都能找到「中文文档」,但在大多数情况下,中文文档往往不是一手资料,甚至有可能是过时资料。英文是假设每个不在使用易语言的程序员都应该掌握的能力。当你使用的库遇到了 bug,跑到 GitHub 上狂开一通中文,且不说礼貌问题,对于解决问题本身亦会造成极大的困难。

这两点对于很多人来说可能是灾难性的。大学 CS101 写个求水仙花数的题目,对于一些人来说,就像是说话一样在描述问题,而对另一些人完全找不到下手的地方。还有我非常喜欢讨论的 FizzBuzz 问题,亦是考察描述模型时考虑是否周全的好例子。而另一些人看到英文字母就头晕,完全没有读下去的能力。对于这些人来说,我的建议是我不太推荐你来学习编程。这不是说你不能通过学习来通过编程谋生,而是你的职业道路会非常坎坷,你会因为基础的不牢固而还债。

计算机科学

今天看到一个知乎上的问题:

「既然终究要成为码农,那么大学计算机系的意义何在?」

此问题,源于 Hacker News 上的一个帖子:Are you working on interesting technical problems?

题主对此也是很有感触,今年刚换了工作,令我惊讶的是身边的同事有一批二本毕业的(没有歧视,就事论事),有几个比我还小,题主的大学虽然只是普通 211 但是我一直在努力地学习技术,毕业两年下班之后几乎没有过多的娱乐时间,都在看内核相关的东西,可是结果却是两年过后我依然和他们在同一个水平线上。四年的大学生涯并没有为自己增加多少能力,所谓的离散数学,所谓的算法,所谓的计算机原理,到现在为止都没有用上,至于那些 Linux 操作之类的完全没必要早接触,还不如那些在工作中临时学的人节省时间。工作中的用到的大部分知识基本都可以在工作中逐渐学会,大学努力所学的一切,所花费的精力都在一瞬间成为了泡影。感觉自己正在失去信念,越来越觉得大学计算机系和培训机构没什么太大区别,学出来都是做码农的,知乎上大神们谈论的高深的计算机科学到底在哪里,为什么这么难以见到?

事实上这个问题的前提「既然终究要成为码农」就有一些问题,显然不是所有人都会成为码农。我现在的工作,和 Linux 底层、算法就强相关。写代码,可以做业务强相关的码农。但计算机科学,有很多与业务相对无关,非常重视底层技术的工作需要做,而且这些工作还很难找到适任的人。

「都在看内核相关的东西,可是结果却是两年过后我依然和他们在同一个水平线上。」这一点我是相当怀疑的,所谓看内核的东西,究竟是看看博客当小说,还是带着问题,特别去深究一些功能究竟在干什么,要解决什么问题。这些信息往往在解决特定问题的时候会变得非常实用。

高德纳说过:「在大概 97% 的时间里,我们应该忘记微小的性能提升。过早优化是万恶之源。」

很多人把这句话视为教条,但这句话的后半句紧跟着就是「我们不能放弃剩下的 3%。」怎么发现 3%,发现 3% 后怎么解决?而这 3% 的关键问题往往是决定你产品快和慢、好用还是不好用甚至是能用还是不能用的关键。如果你已经甘心成为一名码农放弃了这 3%,那么你自然不会觉得这些东西有用。

读大学的时候时间非常充沛,要想边工作边阅读 Linux 内核实现、gcc 的实现恐怕已经变得越来越难了。大学时的算法、数据结构、编译原理、离散数学、计算机组成原理这些经典基础课程存在是你来解决这些问题的基础。然而一个非常值得诟病的一点是,事实上,我们今天的大学计算机科学教育在科学上教得太浅在工程上也教得不深。如果学生本身没有兴趣,没有深入自学这些内容,这甚至使得大学毕业的同学无论是当一名码农还是当一名计算机科学家都不适任,大学毕业后在一批转岗后,最后又回到了师傅带徒弟的技工模式。

初学者该学哪门语言?

这个问题大概是我被问到次数最多,也是最让我无语的问题。就我个人认为,除了某些学习要求特别高的语言比如什么 Haskell、Idris 之类的,大多数我们常听到的语言都可以作为初学语言,比如 Python、Java、Swift、Ruby、PHP、C#、C、C++ 甚至是 Scheme。我不认为学习某一种语言本身是一种障碍,虽然每一门语言各有特色和优劣,但因为编程的逻辑大体上基本是相通的,学习编程从来不是学习某一门特定语言。

然而后来我发现,大多数问这个问题的其实问的是另外一个意思,是「初学者学习哪一门语言有前(钱)途?」这个问题完全没有意思,如果你只想学一门语言,混吃等死,那么就永远没有前途。

P.S. 翻了下平均薪资,好像写 F# 最有前途(逃

如何规划学习路径?需要报班吗?

这也是一个常被问到的问题,特别是已经入门学习了一点编程知识的人。我觉得既然编程的本质是来帮助人类解决问题,那么问题就是关键。既然我们在为这个互联网世界服务,那么我们也可以利用互联网来为我们自己服务。简单来讲就是「从兴趣出发,从问题出发」。

之前有收到一封私信,内容如下:

博主您好,我是一名非计算机专业在校生,刚刚自学计算机课程已学的有 C 语言、组成原理、数据结构、操作系统四门,但发现您和很多技术博主包括论坛上的大部分内容我还是看不懂,尤其是其中的很多英文简称。请问您是否可以告诉我如何开始学习那些知识?

无论是 C 语言、计算机组成原理、数据结构、操作系统都是非常基础的课程,他们是构成软件构成非常底层的内容。当我们谈论某一些具体的技术的时候,通常很碎片,并不会直接讨论这些东西。举例来说,如果我们要讨论非阻塞 I/O,那么我们会举例一些实际的技术,比如 Linux 上的 epoll。至于需要弄清 epoll 的实现,了解 epoll 为什么快,就可以通过比较 epoll 和比如 Windows 上的 IOCP。而比较过程就需要对操作系统、算法有比较好的理解。而这些在你单独上这几门课的时候都不会讲得非常具体。

那么怎么学习这些东西呢?用 Google 搜索,查 Wikipedia,找 Stack Overflow。当你知道一个你不知道的关键词的时候,就去搜索它,然后会出来更多你不知道的概念,直到你了解的概念为止。你就能搞清楚这个技术具体是什么,以及解决了什么具体的问题。然后要自己具体去实践,写一些相关的代码,尝试做一些与之有关的 Hobby Project。就会让你对这东西有比较好的了解,也能从碎片中掌握一门新的技术了。

至于需不需要报班,在这个过程中我想已经有答案了。因为你从班上能学习到的知识,明明点点鼠标就已经可以知道了。而如果你需要一个班来给你填鸭式地教学,那么出了这个班,你依然没有学习的能力。

女孩子可以学习编程吗?

讲道理,我也认为这是一个非常鬼扯的问题,但是确实就是有很多人问。

你能举出男性在学习编程的过程中和女性又任何差别吗?女性有任何生理上的不同限制了她不能学习编程吗?

或者换个说法:

既然一个男孩子可以编程,那么一个女装子可以编程吗?

那么一个做了变性手术的男孩子可以编程吗?

如果一个男孩子,看起来像女孩子,游泳像女孩子,叫声像女孩子,那么他可以……编程吗?

有一个很有趣的说法叫「Everything is a Remix」,类似于中文里的「天下作文一大抄」的感觉。天下所有歌曲都是 Remix,音符、和弦、调式、编曲模式都不是你发明的,但你把他们组合起来让它听起来好听。今天程序也是一个 Remix,我们将现有的技术组合起来解决现实问题,甚至组合起来发明更新的技术。程序,在一些人眼里也许非常魔法,但事实上了解一下它,并没有什么魔法的。

但讲真的,考虑几个月学还是不学,随便找个书、找个交互式编程网站之类的只需要几个小时就可以学起来嘛。到时候究竟自己是适合学习,还是不适合学习,不是几个小时后就能知道?

Tags:

Updated: