计算机科学自学指南

如果你是一名自学工程师或者是一名软件集训课程毕业的学生,有些计算机科学基础课程是你必须要补齐的。幸好,你通过互联网就能获得世界顶级的CS(计算机科学)课程。

其实网上有很多学习资源但它们良莠不齐,你需要不是什么“200+免费在线课程”列表而是如下问题的答案:

你应该学习哪门课程?为什么?

每门课程最好的书籍或者视频,讲座是什么?

我写这篇文章的目的就是尝试对于这些问题给出的明确答案:

使用建议的书籍或者视频讲座来学习以下的九门科目,最好是书籍和讲座都仔细的研究一下,可以不严格按照列出的顺序来。每一门科目都需要花上100-200小时来研读,然后在你的职业生涯中对于最热爱的方向进行反复重温。

主题 为什么学习它 推荐书籍 推荐视频
编程 别做那些连“递归”是什么都搞不懂的程序员 Programs Brian Harvey’s Berkeley CS 61A
计算机体系结构 如果你基础薄弱,不知道计算机是如何运行的,那些你学会的所谓“高层”技能不过是空中楼阁 计算机组成与设计硬件/软件接口 Berkeley CS 61C
算法和数据结构 如果你不能很好的使用随处可见的数据结构(例如栈、队列、树和图),你是无法解决复杂问题的 Steven Skiena’s lectures
计算机数学 计算机科学实际上是应用数学的一个分支,学好数学让你更具竞争力 《Mathematics for Computer Science》 Tom Leighton’s MIT 6.042J
操作系统 你编写的大部分代码是通过操作系统运行的,所以你需要知道它们是如何交互的 Operating Systems: Three Easy Pieces Berkeley CS 162
计算机网络 互联网是个了不起的发明,只有理解它的原理,才能发挥它的威力
计算机网络(第4版)
Stanford CS 144
数据库 对于很多程序来说,数据是其核心,但是很少有人真正理解数据库系统是如何运行的 Readings in Database Systems Joe Hellerstein’s Berkeley CS 186
编程语言和编译器 如果你理解语言和编译器是如何运行的,你就能编写更好的代码并轻松学会新的语言 编译原理 技术与工具 Alex Aiken’s course on Lagunita
分布式系统 近年来,大部分系统已经发展成为分布式系统 Distributed Systems

为什么要学习计算机科学

有两种软件工程师:一种人对于电脑科学有很好的理解从而去从事挑战性的、富有创造力的工作。另外一种人仅仅熟悉一些高级工具,对其原理持得过且过的态度。

两者都叫做软件工程师,而且两者在早期的职业生涯中可能领着同样的薪水。但是第一种工程师,不管他从事的是商业工作,还是突破性的开源工程,都会由于他的技术领导力或者杰出的个人贡献一点一点成长成一名对于编程更加痴迷而且待遇更高的工程师。

第一种工程师可以通过常规手段或者在职业生涯中不断学习来加深对于计算机科学的理解深度。第二种工程师通常停留在表面,学习具体的工具或者技巧而不是其中的基础,当前流行什么技术,他们就仅仅捡起新的技能学习一下。

近些年来,越来越多的人进入软件领域工作,但是本质上计算机科学的毕业生数量是没有改变的。第二种工程师的供应过量开始导致他们的就业机会变少而且导致他们离企业中令人感觉充实的工作更远。不管你是努力要成为第一种工程师或者仅仅是保险起见地想找到更多的工作,学习计算机科学是唯一一种可靠的途径。

课程指南

编程

大多数大学的计算机编程课程通常以“入门类”计算机的课程开始。这些课程最好是不仅仅针对于初学者,而且对于第一次学习编程,基本概念和编程模型不是很熟悉的人也有所启发的。

对于这种介绍的内容的我们给出的标准建议是经典的计算机程序的结构与解释,在网络上能找到很多这样的资料,它们可能是电子书或者是MIT的一系列讲座视频。这些讲座都很不错,但是我们的视频推荐的实际上是伯克利的一门课程:Brian Harvey 的 SICP 讲座 ,这个系列的课程比起MIT的讲座更精炼而且对于入门者更具有针对性。

我们推荐观看完至少前三章节的SICP(《计算机程序的构造和解释 》)并且做完相应训练。额外地,可以在 exercism 进行一些编程训练。

image

如果你觉得SICP太难,我们推荐《程序设计方法(中文版)| How to Design Programs》这本书。如果你觉得它太简单,我们推荐《Concepts, Techniques, and Models of Computer Programming 这本书。

计算机体系结构

硬件是平台 – Mike Acton(Insomniac Games的工程总监) (收看他在 CPP 大会上的演讲)

计算机结构–有的时候被称为“计算机系统”或者“计算机组织”–是了解程序外表下计算机运行的第一步。根据我们的经验,这是自学软件工程师最容易忽略的地方。

《计算机系统要素》The Elements of Computing Systems,也被称为“从与非门到俄罗斯方块”。这是一本让你对于计算机中的每一个零件是怎么工作的有一个整体的理解的雄心勃勃的书。每个章节涉及到建立整体系统中一个小的部分,从写基本的逻辑门到HDL,到CPU和汇编语言,一直到完成一个俄罗斯方块应用程序。

elements-computing-systems

我们推荐阅读书的前六章节并且完成相关的工程。这会提高你对于计算机结构和运行的软件之间关系的理解。

这本书的前半部分(和它的全部工程)在 Nand2Tetris 网站上可以免费获得。在 Coursera 课程网站上你也可以找到它们。

为了保证课程简单并吸引人,Nand2Tetris 舍弃了深度。特别是现代计算机结构中两个很重要的概念:流水线(pipelining)和内存层级(memory hierarchy),在书中都没有提及。

当你觉得看Nand2Tetris已经很简单了,我们下一个建议是Patterson和Hennessy合著的《计算机组成与设计硬件/软件接口》Computer Organization and Design——一本杰出的现代经典书籍。不是书中所有的部分都很重要;我们建议跟随Berkeley的CS61C 课程——(Great Ideas in Computer Architecture),作为特殊读物。讲座的笔记和实验环境都是在线的,而且可以在在这个归档链接回看讲座。

算法和数据结构

只有一个方法是我一直以来广泛推荐的—编码前首先要思考 — Richard Hamming

我们根据几十年的通识来看,熟悉通用的算法和数据结构是计算机科学教育中最重要的方面之一。这是一个训练一个人解决问题的通用能力的方式,而且这种能力还可以迁移到其他领域的学习。

这个领域有很多优秀的书籍,但是我们最喜欢的是Steven Skiena的《算法设计手册》The Algorithm Design Manual 。他显然喜欢这东西而且也迫不及待地想帮助你学习数据结构和算法。这是令人耳目一新的变化,我们认为这本书相对于被更多人所推荐的Cormen, Leiserson, Rivest & Stein 或者 Sedgewick 的书来说更好。后两本书有些太过于引经据典,对于想通过阅读来解决问题的人来说并不是一个好的选择。

skiena

对于那些更喜欢讲座视频的人来说,我们推荐Skiena的讲座. 我们也喜欢Tim Roughgarden的课程,在斯坦福的MOOC平台或者Coursera上面可以获得。你喜欢 Skiena 还是 Roughgarden 的讲课风格就是你的个人喜好问题了。

说到练习,我们倾向于让学生在Leetcode上面解决问题。LeetCode上面的问题都比较有趣而且有答案和讨论。这上面还可以通过解决各大软件公司广泛应用的技术问题来帮助你测试你的进步。我们建议解决你学习的时候解决大约随机100道LeetCode上面的问题。

最后,我们强烈推荐《怎样解题》这本书,它针对如何解题进行了精彩绝伦和独特的讲解,既适用于数学也适用于电脑科学。

polya

计算机科学领域的数学

如果人们不认为数学是简单的,那么他们一定没有体会过人生的艰难 — John von Neumann

在某些方面,计算机科学是应用数学的一个扩展。虽然许多软件工程师忽略了这一点,我们建议你去学习它。好好学习数学会给你比那些不学习它们的人巨大的竞争优势。

和CS最相关的数学领域是“离散数学”,离散是连续对立面。是微积分之外的一系列的有趣的应用数学的主题。从大体上说,尝试学会全部范围的“离散数学”是没有意义的。更现实一点的做法是对于逻辑学,组合学和概率学,集合论,图论和一些数论告知密码学有一个了解。对于计算机图像学和机器学习来说,线性代数也是一门值得学习的课程。

我们建议从László Lovász的讲座学起. 这一系列开始学习离散数学。Lovász 教授让学习的内容变得直观生动,比起拘谨的文字,这更利于你学习。

接下来,我们推荐《Mathematics for Computer Science》, 它是MIT同名课程的讲义。讲座课程的视频也是免费的,而且是我们推荐的离散数学的视频课程。

线性代数,我们建议从 Essence of linear algebra 系列开始学习,接着是Gilbert Strang的书籍视频

操作系统

《操作系统概念》Operating System Concepts)(恐龙书)和《现代操作系统》Modern Operating Systems )是经典的操作系统的书籍。这两本书的写作方式都饱受争议,而且为了鼓励你去购买新版,这些长达1000页的书每几年就会添加一些内容。

Operating Systems: Three Easy Pieces》这本书是一本比较好的可供选择的线上免费读物。我们特别喜欢书的结构和它经典的练习题。

ostep

读完这本书,我们推荐你去探索一种特定的操作系统的设计方式,比如那些书名中有系统名字的书籍,比如 《Lion‘s commentary on Unix》、《The Design and Implementation of the FreeBSD Operating System》,还有 Mac OS X Internals.

巩固你对于操作系统的理解很好的方式是去读一个小的内核并且添加功能。xv6 是一个不错的选择,它是 Unix V6 和 ANSI C 和 X86 的接口,MIT专门有一门课程就是讲这个的。OSTEP(之前提到的)这本书有一个 XV6 的实验附录,里面都是充满潜力项目的好点子。

计算机网络

你不能够通过凝视水晶球来预见未来。因特网未来会变成什么样,取决于如今人类如何去塑造它 — Bob Kahn

考虑到很多软件项目都是基于web服务器和客户端的,计算机网络变成计算机科学中一门有实用价值的学科。系统学习过该课程的自学学生发现他们终于理解了围绕了伴随它们很多年的术语,概念,协议等等。

关于这个主题我们最推荐的书是:《计算机网络》Computer Networking: A Top-Down Approach)。书中的小工程和实验都很好,值得一做。我们非常喜欢它们提供的 Wireshark labs

对于那些喜欢视频课程的人,我们推荐斯坦福MOOC平台上的《Introduction to Computer Networking course》。

学习网络的好处不仅仅在于做小的实验而且对于工程来说也有很大的好处。可能涉及到的有:一个HTTP的服务器,一个UDP协议的聊天软件,一个迷你的 TCP 协议栈,一个代理或者负载平衡器,还有分布式的哈希表等等。

数据库

对于自学者来说,学习数据库系统会比学习其他花费更多的时间。这是一个相对较新的(即1970年代后期)的研究领域。比起写书,许多潜在的杰出教科书作者更愿意去加入或者创办一家公司。

在这种情况下,我们建议自学者放弃教科书而去学习伯克利的Joe Hellerstein的数据库课程,看完课程再去阅读论文。

对于初学者有一篇论文比较推荐的是:《Architecture of a Database System》,它高屋建瓴地讲解了关系数据库管理系统是如果工作的这一问题。它会为你未来的学习提供一个有用的纲要。

Readings in Database Systems这本书,又被称为数据库红皮书、是一本Peter Bailis、Joe Hellerstein和Michael Stonebraker编辑地论文集。对于那些理解了CS 186内容的人来说,红皮书是你的不二之选。

如果你坚持要使用一本引导性的教科书,我们推荐Ramakrishnan 和Gehrke的《数据库管理系统》Database Management Systems,对于更优秀的学生,Jim Gray的传统课程《Transaction Processing: Concepts and Techniques值得一看,但是我们不建议把它当成入门书。

不编大量的代码是不能很好的巩固数据库的理论的,CS 186的学生往Spark中添加功能,这是一个很有意义的工程。但是我们建议仅仅是从头写一个简单的关系数据库管理系统。功能可能不是很丰富,但是即使每一个部分都涉及到一些基本功能也很有启发性。

最后,数据模型是一个数据库使用中被忽略和没有被重点学习的方面。我们对于这个课题建议的书籍是:《Data and Reality: A Timeless Perspective on Perceiving and Managing Information in Our Imprecise World

语言和编译器

Don’t be a boilerplate programmer. Instead, build tools for users and other programmers. Take historical note of textile and steel industries: do you want to build machines and tools, or do you want to operate those machines? — Ras Bodik at the start of his compilers course

大部分程序员学习如何使用一门编程语言,然而大部分的计算机科学家则学习这门语言本身。这给了计算机科学家比起程序员很明显的优势。他们的知识能够更好的泛化,他们能比简简单单地掌握一门语言的更加深入和快速的理解一门新语言的操作。

经典的教科书《编译原理 技术与工具》( Compilers: Principles, Techniques & Tools)通常又被称为“龙书”。不幸的是,这本书并不适合自学者,它比较适合教师从中选出1-2个章节并在课堂上讲授。这本书是有必要看的,你可以挑选里面的主题,最好再有个师傅指导你。

如果你选择在自学中使用龙书,我们推荐你一系列门视频讲座,然后再沉浸在对于龙书的研究中。我们推荐的在线课程是:Alex Aiken 的讲座,你可以在斯坦福大学的幕课平台上观看。

也有可以替代龙书的教材:Terence Parr写的《编程语言实现模式》Language Implementation Patterns,它更适合那些工作中使用类似特定领域语言的小众语言的有经验的编程者,它显得更加实用。当然,为了达到这个目的它也删去了一些有价值的理论。

对于工程实践,我们推荐你写一个编译器,你可以选择像COOL这种简单的教学语言或者你感兴趣的一门语言。如果你觉得太难,你可以参考Make a Lisp,你可以参考它作为开始。

分布式系统

计算机的数量增长了,它们的分布也更广了。企业之前会购买越来越大型的主机,但是现在大家更倾向于在很多机器上分布式的运行多个小型的应用程序。分布式系统研究的就是这样的技术,这一技术变得越来越重要了。

我们建议的自学教科书是 Maarten van Steen 和 Andrew Tanenbaum 的《Distributed Systems, 3rd Edition》。 针对于之前的版本做了很大的改进,而且作者慷慨地把书放在了网上共享。由于分布式计算是一门变化很快的领域,所以没有教科书可以很好的涵盖所有的内容。但是Maarten van Steen的书是我们读过的所有书中最好的书。

研究生在线课程 MIT’s 6.824 也是一个不错的选择,但可惜视频中的音质不太好,而且不清楚这些视频是不是都被授权过。

尽管有参考书或者其它的资源,但学习分布式系统是绝对要读论文的。链接中有一个很好的清单,而且我们十分推荐你从Papers We Love 上面下载论文到本地学习。

 

译注:本文提到的大部分书籍,中英文版已归档至该豆列

1 13 收藏 评论

关于作者:pumpkin0227

简介还没来得及写 :) 个人主页 · 我的文章

可能感兴趣的话题



直接登录
跳到底部
返回顶部