不要害怕你不理解的事情
学习一些复杂的新事物开始时往往会感到困难 - 如果感觉很容易,那么它可能是你已经知道的东西,或者它可能不是真正考验你的知识(阅读如何解决一个物理问题并认为“它很合理”,比你自己用刚刚学会的工具解决一个问题要容易得多)。感觉吃力是个好现象 - 这意味着你真的在学习,集中精力一直坚持做下去,当你感觉变好的时候你的学习就会变得更容易。
我认为,一个新人在这方面甚至有一点优势:当你积累了一点经验后,只做你已经知道怎么做的事情,而不是学习新的东西,会让你感觉容易和舒适。这会导致你陷入一个停滞期,在那里你只是重复做你已经知道怎么做的事情,就像一个人只能用吉他弹一首歌,并且他总是弹同一首歌一样。对于一个新人来说,一切都很难,但这样做不应该是一个新人真正的选择。
第一次学习一些复杂的东西应该会感觉有点痛苦 - 你应该习惯这种感觉,因为这是件好事,意味着你在成长。不要因此觉得自己不够聪明而被吓跑了。因为有太多东西要学,有太多不同的途径要走(仅就计算机科学来说,就有很多东西,像计算机图形学、计算机安全、机器学习、算法、移动、网络、基础设施等等分支),所以有一个让自己成长并走出舒适区去学习新事物的心态是至关重要的。
学习编程 - 边做边学
仅仅通过阅读一本关于编程的书来学习编程,就像仅仅通过阅读一本关于跳伞的书来学习跳伞一样。你可能需要读一本书(而且在开始的时候你需要用它作为一个起点),但是除非你同时也在写一些小程序,否则你从中得到的有限。木匠通过建造东西来使技术变得更熟练,作家通过撰写文章来使文笔变得更优美,而程序员则通过编写代码来提高编码水平。这并不意味着你不应该读书,也不意味着一本好书不能给你带来价值。但是仅仅这样做会很容易让你陷入一个误区:你只是在那里读关于编程的书而不是自己做任何事情,会让你觉得读起来容易,做起来也容易。然而,当你真正开始编程的时候,你会发现凭空想象出来一些程序是很困难的。
我同意ESR的观点,Python是一种很好的作为编程起点的语言,而且有一个很好的学习网站,名为苦学Python,专门针对初学者,并在教学过程中使用一些练习。
一开始,你会觉得语法很难理解,当你开始学习的时候,很多时间都花在了语法上。因为每种编程语言都有不同的语法,它们看起来非常不同。当你开始掌握语法后,你更多的精力就会放在关于如何解决问题和使用什么数据结构的通用知识上。最终,你对于使用常见的数据结构已经相当娴熟,然后你的重点将会转向更高层次的抽象和更通用的设计或基础架构,这些设计或基础架构使得软件开发更易于在规模上管理或在将来更易于更改。
在掌握了一门编程语言的语法并且能够编写简单的程序之后,学习数据结构是最重要的下一步。Cracking the Coding Interview这本书对一些核心的数据结构有很详细的描述(并且还附带有一些示例问题)。令人困惑的是,不同的语言在实现相同的数据结构时往往有不同的名称(比如,Python称哈希表(hash table)为‘字典( dictionary)’),但大多数语言都会实现一些核心数据结构,即使它们都有一个不同的名称。
故障排除或调试也是一项核心编程技能 - 大多数编程时间实际上都是在调试,因此,如果你喜欢调试代码,这可能是一个好现象。当你不得不到处搜索以试图理解某件事情,或者当你正在阅读的文档不起作用,或者当你在环境中遇到一些意外错误时,不要气馁 ,记住这是正常的,而且这也不是你能力低下的反映。
大多数软件都不工作,而且经常有未记录的error、bug和一些难以纠正的琐碎问题。例如,Github上的大多数开源项目都有某种构建系统,用于处理将软件配置为运行的问题。这将执行诸如拉入依赖项(需要与之配合工作的其他代码)之类的操作,以及执行任何必要的命令来实际运行它。如果你要在Github上下载一个有趣的项目并尝试运行它,你可能会在这个过程中遇到很多意外的错误,而这些错误通常没有文档记录。
运行时遇到这些错误并且将问题解决是很正常的事情,经验丰富的程序员也必须处理这些问题(如果幸运的话,我们以前也见过这种类型的问题)。我见过有人遇到这样的错误,并且认为自己做错了什么,但实际上错不是你,而是编程就是这样的过程。围绕着构建系统并试图使其更好,有很多相互竞争的工具甚至行业(这可能会使初学者更加困惑,因为没有真正的标准化,并且配置软件使之运行的正确方法也因为编程环境和语言的不同而各不相同)。
计算机实际上是如何工作的?
我记得那时我很沮丧,因为我很难找到关于计算机实际工作方式的信息。我能找到的关于计算机的一切都是用毫无用处的过于简单的类比(比如,磁盘是“存放文件的柜子”),我找不到任何我可以阅读并且帮助我真正理解计算机是如何工作的,并且如果把我转移到过去,我就能真正解释如何构建出一个计算机的东西。这些是比软件更具体的电子或计算机工程,它们在帮助理解硬件方面仍然有很多价值(这很有趣!)。
我愿意推荐的最好的书是Charles Petzold撰写的《Code》。它引导你从电子位开始,一直到布尔逻辑和电路设计的历史,再到简单电路的实际图形,以及如何将位存储在内存中。这是知识依照发现的历史背景一步步地介绍给你,直到构建出一个真正的小CPU。Charles Petzold还学习了一些汇编和基本的计算机图形学。他是一个逻辑非常清楚的作家和老师,所以这本书的细节具备令人惊讶的可读性。
关于计算机的更多的历史背景,我推荐Mitchell Waldrop的《梦幻机器》和Steven Levy的《黑客》。书中的叙述性的故事使学习和记忆更容易,我认为这些发现的背景有助于学习事物的实际工作方式。
软件工具:代码编辑器,编程环境
工具是有趣的,了解你的工具是件好事,但是你可以永远定制一些东西,争论一些无关紧要的小细节。当你刚开始的时候,定制工具是一个有趣的学习方式,但是我看到人们花了大量的时间在这个上面,与实际编写解决问题的程序或者学习更多的通用编程技巧相比,它产生的价值相对较小(关于这点的一本很好的书是设计数据密集型应用程序)。过于专注于定制工具会束缚你前进的脚步。
不要太担心Vim或Emacs之类的工具,也不要太担心你正在使用何种操作系统 -你可以在任何地方学习这些核心技能(这是我与ESR原始文章的最大分歧)。也就是说,玩Linux对我来说是一个非常有价值的学习故障排除的方法 - 主要是因为我的Linux没有很好地工作,我不得不花上几个小时来尝试让无线互联网正常工作,让笔记本电脑成功挂起,甚至让用户界面出现(现在情况稍微好一点)。
我开始尝试安装Gentoo(实际上从未成功)。这种故障排除技巧对于我获得现在的工作非常有帮助,所以如果你喜欢玩不同的操作系统,我肯定会鼓励你,我只是不认为这是必要的。不过,在macOS或Linux上学习可能更容易,因为大多数现有的工具都是针对这些环境,而且大多数程序员都在使用这两种工具中的一种。
值得一提的另外一个特定工具是版本控制,特别是git。花点时间熟悉其基本知识是值得的,但它可能是在你编程一段时间之后才需要关注的东西。