注:本指南在2020年5月进行了广泛更新。有关以前的版本,请参见此处。
如果你是一名自学成才的工程师或训练营毕业生,你应该学习计算机科学。谢天谢地,你可以给自己一个世界级的CS教育,而不需要在学位课程💸上投资几年和一小笔钱。
外面有很多资源,但有些比另一些更好。你不需要再来一篇“200+免费在线课程”的演讲了。您需要以下问题的答案:
感谢吴正科翻译的中文:中文翻译见此和克莱门斯·施拉格的葡萄牙语翻译:Tradução em Português。
学习下面的所有九个主题,大致按照呈现的顺序,使用建议的教科书或视频系列讲座,但最好是两者兼而有之。为每个主题设定100-200个小时的学习时间,然后在你的职业生涯🚀中重温你最喜欢的话题。
不要成为那种“从未完全理解”递归之类的东西的人。
如果你没有一个坚实的计算机实际工作方式的心理模型,那么你的所有更高层次的抽象都将脆弱不堪。
如果您不知道如何使用堆栈、队列、树和图形等无处不在的数据结构,您将无法解决具有挑战性的问题。
CS基本上是应用数学的一个失控分支,所以学习数学会给你带来竞争优势。
您编写的大部分代码都是由操作系统运行的,因此您应该知道它们是如何交互的。
事实证明,互联网是一件大事:了解它是如何发挥其全部潜力的。
数据是大多数重要程序的核心,但很少有人了解数据库系统实际是如何工作的。
如果您了解语言和编译器的实际工作方式,您就可以更轻松地编写更好的代码和学习新语言。
如果多年自学9个主题的想法让人感觉不堪重负,我们建议你只读两本书:“计算机系统:程序员的视角”和“设计数据密集型应用程序”。根据我们的经验,这两本书在投资时间上提供了令人难以置信的高回报,特别是对于自学成才的工程师和从事网络应用程序工作的训练营毕业生来说。它们也可以作为上面列出的其他主题和资源的入门药物。
有两种类型的软件工程师:一种是对计算机科学的了解足够好,可以从事富有挑战性的创新工作,另一种是因为熟悉一些高级工具而勉强过活的人。
两人都自称是软件工程师,而且在早期职业生涯中,两人的薪水都差不多。但随着时间的推移,第一类工程师会朝着更有成就感、报酬更高的工作方向发展,无论是有价值的商业工作还是突破性的开源项目、技术领导或高质量的个人贡献。
全球短信系统每天处理约200亿条短信。WhatsApp目前的业务规模为420亿美元。有57名工程师。pic.twitter.com/zZrtSIzhlR。
--本尼迪克特·埃文斯(@BenedictEvans)2016年2月2日。
第一类工程师找到了深入学习计算机科学的方法,无论是通过传统的方法,还是通过在他们的职业生涯中坚持不懈地学习。第二类工程师通常停留在表面,学习特定的工具和技术,而不是他们的基础,只有在技术时尚的风向改变时才会学习新技能。
目前,进入该行业的人数正在迅速增加,而CS毕业生的数量相对稳定。II型工程师的供过于求正开始减少他们的就业机会,并使他们无法从事该行业更有成就感的工作。无论你是在努力成为一名一级工程师,还是只是在寻找更有保障的工作,学习计算机科学都是唯一可靠的途径。
大多数本科生的计算机科学课程都是从计算机编程的“入门”开始的。这些课程的最好版本不仅迎合新手,而且也迎合那些在刚开始学习编程时错过了有益概念和编程模型的人。
我们对这一内容的标准推荐是计算机程序的经典结构和解释,它可以作为一本书和一套麻省理工学院视频讲座在网上免费获得。虽然这些讲座很棒,但我们的视频建议实际上是布莱恩·哈维(Brian Harvey)的SiCp讲座(针对伯克利的61A课程)。与麻省理工学院的讲座相比,这些课程更精致,更有针对性。
我们建议至少通读SICP的前三章,并做练习。对于额外的练习,可以解决一组小的编程问题,比如练习中的问题。
自本指南于2016年首次出版以来,最常被问及的问题之一是,我们现在是否会推荐约翰·德尼罗(John DeNero)教授的更新版本的61A的录音,和/或相应的书籍作曲程序(Composing Programs),这本书“沿袭了SiCp的传统”,但使用了Python。我们认为DeNero的资源也很棒,一些学生可能最终会更喜欢它们,但我们仍然建议将SICP、Scheme和Brian Harvey的讲座作为第一套尝试的资源。
为什么?因为SICP的能力是独一无二的--至少是潜在的--能够改变你对计算机和编程的基本信念。不是每个人都会经历这种情况。有些人会讨厌这本书,有些人读不过前几页。但潜在的回报使它值得一试。
如果你不喜欢SICP,可以试着编写程序。如果这仍然不合适,那就试试“如何设计程序”(How To Design Programs)吧。如果这些似乎都没有回报您的努力,也许这是一个信号,表明您应该在一段时间内专注于其他主题,并在一到两年内重新审视编程纪律。
最后,需要澄清的一点是:本指南并不是为那些对编程完全陌生的人设计的。我们假设您是一名有能力的程序员,没有计算机科学背景,希望填补一些知识空白。事实上,我们已经包括了一个关于编程的部分,这只是一个提醒,可能还有更多的东西需要学习。对于那些以前从未编写过代码,但想要编写代码的人,您可能更喜欢这样的指南。
计算机体系结构-有时被称为“计算机系统”或“计算机组织”-是对软件表面下的计算的重要的第一次审视。在我们的经验中,这是自学成才的软件工程师中最被忽视的领域。
我们最喜欢的入门书是“计算机系统:程序员视角”,使用这本书的典型计算机体系结构入门课程将涵盖第1-6章的大部分内容。
我们喜欢CS:App实用的、面向程序员的方法。虽然关于计算机体系结构的内容比本书涵盖的内容要多得多,但对于那些主要为了编写更快、更高效和更可靠的软件而希望了解计算机系统的人来说,它是一个很好的起点。
对于那些想要更温和地介绍这一主题并平衡硬件和软件问题的人,我们推荐计算系统的元素,也被称为“Nand2Tetris”。这是一本雄心勃勃的书,试图让你对计算机中的一切如何工作有一个连贯的理解。每一章都涉及构建整个系统的一小部分,从用HDL编写初级逻辑门,到CPU和汇编器,一直到俄罗斯方块游戏大小的应用程序。
我们建议您通读本书的前六章,并完成相关的项目。这将加深您对计算机体系结构和在其上运行的软件之间关系的理解。
这本书的前半部分(以及它的所有项目)可以从Nand2Tetris网站免费获得。它还可以作为Coursera课程提供,并附带视频。
在追求简洁性和凝聚力的过程中,Nand2Tetris牺牲了深度。特别是,现代计算机体系结构中的两个非常重要的概念是流水线和内存层次结构,但这两个概念大多没有出现在正文中。
一旦您对Nand2Tetris的内容感到满意,我们建议您要么返回CS:App,要么考虑Patterson和Hennessy的“计算机组织与设计”,这是一本优秀的、现已成为经典的文本。并不是书中的每一节都是必不可少的;我们建议您按照Berkeley的CS61C课程“计算机体系结构中的伟大想法”阅读特定的读物。课堂讲稿和实验可以在网上找到,过去的课程可以在互联网档案馆找到。
我们同意几十年来的共同智慧,即熟悉常见的算法和数据结构是计算机科学教育最有力的方面之一。这也是训练一个人一般解决问题能力的好地方,这将在其他所有学习领域都会有所回报。
有数百本书可供选择,但我们最喜欢的是Steven Skiena的“算法设计手册”。他显然热爱算法问题的解决,在学生和读者中培养了类似的热情,这是他典型的成功之举。在我们看来,对于那些学习材料主要是为了帮助解决实际问题的人来说,两个更常见的建议文本(CLRS和Sedgewick)倾向于有点过于举证繁重。
对于那些喜欢视频讲座的人,Skiena慷慨地提供了他的在线课程。我们也非常喜欢Tim RoughGarden的课程,可以在Coursera和其他地方找到。您更喜欢Skiena的演讲风格还是RoughGarden的演讲风格,这取决于您个人的喜好。事实上,有几十种好的选择,所以如果你碰巧找到了你喜欢的另一种,我们鼓励你坚持下去!
对于实践,我们首选的方法是让学生解决Leetcode上的问题。这些往往是有趣的问题,伴随着体面的解决方案和讨论。它们还可以帮助您针对在更具竞争力的软件公司的技术面试中常用的问题来测试进度。作为研究的一部分,我们建议解决大约100个随机的leetcode问题。
最后,我们强烈推荐如何解决它,将其作为解决一般问题的优秀而独特的指南;它既适用于数学,也适用于计算机科学。
我只有一种广泛推荐的方法--那就是“三思而后行”。
--理查德·汉明。
在某些方面,计算机科学是应用数学的一个杂乱无章的分支。虽然许多软件工程师试图忽略这一点,并在不同程度上取得了成功,但我们鼓励您通过直接学习来接受这一点。成功做到这一点将给你带来巨大的竞争优势,而不是那些没有做到这一点的人。
与CS最相关的数学领域被广泛地称为“离散数学”,其中“离散”是“连续”的反义词,它是微积分之外有趣的应用数学主题的松散集合。考虑到模糊的定义,试图涵盖整个“离散数学”是没有意义的。一个更现实的目标是建立对逻辑学、组合学和概率论、集合论、图论的工作理解,以及一些数论知识来指导密码学。鉴于线性代数在计算机图形学和机器学习中的重要性,它是另一个值得研究的领域。
我们建议的离散数学起点是LászlóLovász的一套课堂讲稿。Lovász教授在使内容平易近人和直观方面做得很好,所以这是一个比更正式的文本更好的起点。
对于更高级的治疗,我们建议使用计算机科学的数学,即麻省理工学院同名课程的全书长的课堂讲稿。该课程的视频讲座也是免费的,是我们推荐的离散数学视频讲座。
对于线性代数,我们建议从线性代数的本质视频系列开始,然后是Gilbert Strang的书和视频讲座。
如果人们不相信数学是简单的,那仅仅是因为他们没有意识到生活有多么复杂。
-约翰·冯·诺伊曼(John Von Neumann)。
“操作系统概念”(“恐龙书”)和“现代操作系统”是关于操作系统的“经典”书籍。这两所学校都因缺乏清晰度和普遍的学生不友好而招致批评。
操作系统:三个简单的部件是一个很好的选择,可以在网上免费获得。我们特别喜欢这本书的结构和可读性,觉得这些练习是值得的。
在Ostep之后,我们鼓励您通过“{OS name}内部结构”风格的书籍来探索特定操作系统的设计决策,例如Lion对Unix的评论、FreeBSD操作系统的设计和实现以及Mac OS X内部结构。对于Linux,我们推荐Robert Love的奇妙的Linux内核开发。
要巩固您对操作系统的理解,一个很好的方法就是阅读小内核的代码并添加特性。一种选择是xv6,它是Unix v6到ANSI C和x86的一个端口,在麻省理工学院的一个课程中进行维护。Ostep有一个附录,列出了潜在的xv6实验室,里面充满了关于潜在项目的伟大想法。
鉴于如此多的软件工程都是在Web服务器和客户端上进行的,计算机科学中最有价值的领域之一就是计算机网络。我们的自学成才的学生有条不紊地学习网络,发现他们终于理解了他们多年来一直被包围的术语、概念和协议。
关于这个主题,我们最喜欢的书是“计算机网络:自上而下的方法”。书中的小项目和练习非常值得做,我们特别喜欢他们在网上慷慨提供的“Wireshark实验室”。
对于那些喜欢视频授课的人,我们推荐斯坦福大学的计算机网络入门课程,这门课程以前可以通过斯坦福大学的MOOC平台Lagunita获得,但遗憾的是,现在只能在YouTube上以非官方播放列表的形式提供。
你不可能在凝视水晶球的同时看到未来。未来的互联网是由社会决定的。
与大多数其他主题相比,自学数据库系统需要更多的工作。这是一个相对较新(即70后)的研究领域,对闭门造车的想法有很强的商业诱因。此外,许多潜在的优秀教科书作者更愿意加入或创办公司。
考虑到这种情况,我们鼓励自学者一般避免使用教科书,从录制Cs186开始,这是乔·赫勒斯坦在伯克利的数据库课程,然后继续阅读论文。
对于新生来说,有一篇文章特别值得一提,那就是“数据库系统的体系结构”,它提供了关系数据库管理系统(RDBMS)如何工作的高级视图。这将作为进一步研究的有用框架。
“数据库阅读”,也就是大家熟知的数据库“红皮书”,是由Peter Bailis、Joe Hellerstein和Michael Stonebraker编辑的论文集。对于那些已经超过CS186内容水平的人来说,红皮书应该是你的下一站。
如果您坚持使用入门教科书,我们建议您使用Ramakrishnan和Gehrke的“数据库管理系统”。对于更高级的学生来说,Jim Gray的经典的事务处理:概念和技术是值得的,但我们不鼓励将其作为第一资源。
最后,在使用数据库时,数据建模是一个被忽视且教得很少的方面。关于这个主题,我们推荐的书是“数据与现实:在我们不精确的世界中感知和管理信息的永恒视角”。
大多数程序员学习语言,而大多数计算机科学家学习语言。这使计算机科学家比程序员有明显的优势,甚至在编程领域也是如此!他们的知识是概括性的;他们能够比那些仅仅学习过特定语言的人更深入、更快速地理解一门新语言的操作。
我们建议的介绍性文本是Bob Nystrom的优秀手工艺翻译器,可以在线免费获得。它组织良好,极具娱乐性,非常适合那些主要目标只是为了更好地理解他们的语言和语言工具的人。我们建议花时间把整件事做完,尝试任何一项挑战来保持你的兴趣。
一个更传统的推荐是编译器:原则、技术和工具,通常被称为“龙书”。不幸的是,它不是为自学而设计的,而是供教师为他们的课程挑选1-2个学期的主题。
如果你选择使用“龙书”,那么精挑细选主题几乎是必不可少的,最好是在导师的帮助下。事实上,如果您愿意的话,我们建议使用“龙书”的方式是作为系列视频讲座的补充参考。我们推荐的是Alex Aiken的,在edX上。
不要做一个例行公事的程序员。相反,应该为用户和其他程序员构建工具。回顾一下纺织和钢铁行业的历史:你是想制造机器和工具,还是想操作这些机器?
随着计算机数量的增加,它们也在普及。虽然以前企业会购买越来越大的大型机,但现在典型的情况是,即使是非常小的应用程序也可以跨多台机器运行。分布式系统是研究如何对在此过程中涉及的权衡进行推理的学科。
我们推荐的自学书籍是马丁·克莱普曼(Martin Kleppmann)的“设计数据密集型应用程序”。DDIA比传统的教科书要好得多,它是一本专为从业者设计的可读性很高的书,不知何故避免了牺牲深度或严谨性。
对于那些寻求更传统的文本,或者更喜欢在线免费的文本的人,我们推荐Maarten van Steen和Andrew Tanenbaum的分布式系统,第三版