数学知识从某个角度说,计算机科学是应用数学的一个 “发育过度” 的分支。尽管许多软件工程师试图 —— 并且在不同程度上成功做到 —— 忽视这一点,我们鼓励你用学习来拥抱数学。如若成功,比起那些没有掌握数学的人,你将获得巨大的竞争优势。对于计算机科学,数学中最相关的领域是 “离散数学”,其中的 “离散” 与 “连续” 相对立,大致上指的是应用数学中那些有趣的主题,而不是微积分之类的。由于定义比较含糊,试图掌握离散数学的全部内容是没有意义的。较为现实的学习目标是,了解逻辑、排列组合、概率论、集合论、图论以及密码学相关的一些数论知识。考虑到线性代数在计算机图形学和机器学习中的重要性,该领域同样值得学习。学习离散数学,我们建议从 László Lovász 的课程笔记开始。Lovász 教授成功地让这些内容浅显易懂且符合直觉,因此,比起正式的教材,这更适合初学者。对于更加高阶的学习,我们推荐 《计算机科学中的数学》,MIT 同名课程的课程笔记,篇幅与书籍相当(事实上,现已出版)。这门课程的视频同样可免费获得,是我们所推荐的学习视频。对于线性代数,我们建议从 Essence of linear algebra 系列视频开始,然后再去学习 Gilbert Strang 的《线性代数导论》和视频课程。
如果人们不相信数学是简单的,那么只能是因为他们没有意识到生活有多么复杂。— John von Neumann
操作系统《操作系统概念》 (“恐龙书”)和 《现代操作系统》 是操作系统领域的经典书籍。二者都因为写作风格和对学生不友好而招致了一些批评。《操作系统导论》(Operating Systems: Three Easy Pieces) 是一个不错的替代品,并且可在网上免费获得(英文版)。我们格外喜欢这本书的结构,并且认为这本书的习题很值得一做。在读完《操作系统导论》后,我们鼓励你探索特定操作系统的设计。可以借助 “{OS name} Internals” 风格的书籍,比如 Lion's commentary on Unix, The Design and Implementation of the FreeBSD Operating System,以及 Mac OS X Internals。对于 Linux ,我们推荐 Robert Love 的 《Linux 内核设计与实现》。为了巩固对操作系统的理解,阅读小型系统内核的代码并且为其增加特性是一个很不错的方法。比如,xv6,由 MIT 的一门课程所维护的从 Unix V6 到 ANSI C 和 x86 的移植,就是一个很棒的选择。《操作系统导论》有一个附录,记载了一些可能的 xv6 实验项目,其中充满了关于潜在项目的很棒想法。
数据库比起其他主题,自学数据库系统需要更多的付出。这是一个相对年轻的研究领域,并且出于很强的商业动机,研究者把想法藏在紧闭的门后。此外,许多原本有潜力写出优秀教材的作者反而选择了加入或创立公司。鉴于如上情况,我们鼓励自学者大体上抛弃教材,而是从 2015 年春季学期的 CS 186 课程(Joe Hellerstein 在 Berkeley 的数据库课程)开始,然后前往阅读论文。对于初学者,有一篇格外值得提及的论文:“Architecture of a Database System”。这篇论文提供了独特的对关系型数据库管理系统(RDBMS)如何工作的高层次观点,是后续学习的实用梗概。《Readings in Database Systems》,或者以数据库 “红书” 更为人知,是由 Peter Bailis,Joe Hellerstein 和 Michael Stonebraker 编纂的论文合集。对于那些想要在 CS 186 课程的水平更进一步的学习者,“红书” 应当是下一步。如果你坚持一定要一本导论教材,那我们推荐 Ramakrishnan 和 Gehrke 所著的 《数据库管理系统:原理与设计》。如需更深一步,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。
编程语言与编译器多数程序员学习编程语言的知识,而多数计算机科学家学习编程语言 相关 的知识。这使得计算机科学家比起程序员拥有显著的优势,即便在编程领域!因为他们的知识可以推而广之:相较只学习过特定编程语言的人,他们可以更深入更快速地理解新的编程语言。我们推荐的入门书是 Bob Nystrom 所著的优秀的 Crafting Interpreters,可在网上免费获取。这本书条理清晰,富有趣味性,非常适合那些想要更好地理解语言和语言工具的人。我们建议你花时间读完整本书,并尝试任何一个感兴趣的 “挑战”。另一本更为传统的推荐书籍是 《编译原理》,通常称为 “龙书”。不幸的是,这本书不是为自学者而设计的,而是供教师从中挑选一些主题用于 1-2 学期的教学。如果你选择使用龙书进行自学,你需要从中甄选主题,而且最好是在导师的帮助下。我们建议依据某个视频课程来设定学习的结构,然后按需从龙书中获取深入的内容。我们推荐的在线课程是 Alex Aiken 在 MOOC 平台 edX 所开设的。
分布式系统随着计算机在数量上的增加,计算机同样开始 分散。尽管商业公司过去愿意购买越来越大的大型机,现在的典型情况是,甚至很小的应用程序都同时在多台机器上运行。思考这样做的利弊权衡,即是分布式系统的研究所在,也是越来越重要的一项技能。我们推荐的自学参考书是 Martin Kleppmann 的 《数据密集型应用系统设计》。与传统的教科书相比,它是一本为实践者设计的具有很高的可读性的书,并且保持了深度和严谨性。对于那些偏爱传统教材,或者希望可以从网上免费获取的人,我们推荐的教材是 Maarten van Steen 和 Andrew Tanenbaum 所著的 《分布式系统原理与范型》(中文第二版,英文第三版)。对于喜欢视频课程的人,MIT 的 6.824 是一门很好的在线视频课程,由 Robert Morris 教授的研究生课程,在这里可以看到课程安排。不管选择怎样的教材或者其他辅助资料,学习分布式系统必然要求阅读论文。这里有一个不错的论文清单,而且我们强烈建议你出席你当地的 Papers We Love(仅限美国)。
常见问题解答
这份指引的目标受众是?我们面向自学的软件工程师、培训班学生、“早熟的” 高中生或者想要通过自学补充正式教育的大学生。关于何时开启这段自学旅程,完全取决于个人,不过多数人在有一定的职业经历后深入学习计算机科学理论会获益匪浅。比如,我们注意到,如果学生在工作中曾经使用过数据库,他们会 喜爱 学习数据库系统课程;如果学生从事过一两个 Web 项目,他们会 喜爱 学习计算机网络。人工智能 / 计算机图形学 / XX 主题怎么样?我们试图把计算机科学主题清单限制到那些我们认为 每一个软件工程师 都应该了解的内容,不限于专业或行业。拥有了这些基础,你将能更加轻松地挑选教材或论文,然而无需指引地学习核心概念。在这里,我们给出一些其他常见主题的自学起点:
人工智能:通过观看视频并完成 Pacman 项目来学习 Berkeley 的 AI 课程。至于教材,使用 Russell 和 Norvig 编写的 《人工智能:一种现代方法》。