计算机科学自学指南

monchickey

2021/03/03

作为自学计算转行或者从培训班出来直接工作的程序员,都存在计算机科学知识不足的问题,甚至连科班出身的人毕业后因为长时间工作而忽略了基础知识温习,也存在同样的问题。我们作为一名软件方面的工程师,不应只满足于高级语言、框架或工具的使用,这些都只能带来短期的效益而终究会变得无用,因此每个软件工程师都应该制定一份长期的自学计划,系统的学习计算机科学领域真正精华核心的部分,不仅是一遍,而且需要空闲时反复研究反复思考形成良性循环,一定会不断产生新的认识,因为越是基础的知识越具有通用性和可迁移性,而且几乎不会过时,学习基础会让我们看到计算机领域的前辈们是如何思考问题的,在这个巨人的肩膀之上再学习其他任何上层的东西都将会以底层的视角来看待,而且会变得非常容易,所以计算机科学的基础是工程师的内功,也是区分工程师是否优秀的根本,我们有了良好的基础知识掌握后,无论开发底层系统还是上层应用,都可以做到心中有底,每一步都是踏实的,才可以长期对自己从事的领域保持热情和信心,才更可能设计出更优秀的系统,因此每个工程师花时间学习计算机科学基础知识,就像一次长期价值投资,这种投入一定是值得的,并且在未来也一定会带来比自己预期还要高的收益!而这一切的山重水复、柳暗花明都需要自己经历过,知行合一才能真正的体会,是再多的语言也无法概括的。正所谓纸上得来终觉浅,绝知此事要躬行。那么,就让我们跟随先贤的脚步,让自己变得更智慧吧~

因为对于有一定经验的工程师来说,编程语言和工具使用本身已经没什么问题,至少c语言要会,而且应该都对计算机运行的原理有一定的了解,比如cpu、内存、网络等,但是每一项细节都比较模糊,因此大致的学习顺序是按照自底向上的顺序来学习的,大致来说是:计算机硬件—计算机架构和组成原理—操作系统—应用系统(数据库或网络等)—分布式系统,对于每一个层面上的学习顺序按照个人习惯即可,不影响总体的顺序,另外数据结构和算法、数学在整个学习中都会有贯穿,因此也应该尽早的有所了解。

1.计算机组成

《深入理解计算机系统》,大名鼎鼎的CSAPP,学完之后一定会对计算机实现架构有很深的理解,但是这个难度也非常大,但是是所有计算机工程应用的基础,豆瓣链接:https://book.douban.com/subject/26912767/,B站有配套的视频:https://www.bilibili.com/video/BV1iW411d7hd

如果感觉难度比较大,可以先从简单的学起,比如极客时间上面的《深入浅出计算机组成原理》链接:https://time.geekbang.org/column/intro/100026001,这个是付费的课程,也不算太贵值得一看,并且课程中不仅以简单易懂的方式讲解组成原理的知识,而且也会推荐其他比较好的学习资料和路线,同时还推荐一本书《计算机系统要素》,豆瓣:https://book.douban.com/subject/1998341/,这本书会给你讲清楚计算机是怎么一步一步构建出来的,能让你一览整个计算机的全貌,将整个运行的流程打通,看完之后一定会有全新的俯视感的认识,内容不深但是面足够,这本书和另外一本《编码:隐匿在计算机软硬件背后的语言》链接:https://book.douban.com/subject/4822685/很相似,只不过编码这本书算是科普书,各种概念解释上都浅一些,而计算机系统要素这本书更深一些,算是专业领域的入门书。

经过上面两门课程窥探计算机组成体系的原貌之后,可以进一步深入,可以阅读《计算机组成与设计:硬件/软件接口》,这本书可以作为计算机组成与设计的教科书了,非常经典,或者再回头去学《深入理解计算机系统》也是可以的,学习的同时可以配合北京大学Coursera Computer Organization这门课程一块学习,这门课在Coursera上也是免费的:https://www.coursera.org/learn/jisuanji-zucheng,B站也有相同的课程,链接:https://www.bilibili.com/video/BV1Xx411Q7Nz

2.数据结构与算法

数据结构与算法不仅可以提升我们程序设计的能力,还可以培养我们解决各个领域问题的通用能力,换句话说,数据结构和算法会让我们知道如何思考并解决问题。

推荐书籍方面《算法导论》就暂时跳过吧,因为实在太专业了,相对来说更推荐《算法设计手册》https://book.douban.com/subject/4048566/,这本书对读者比较友好,讲解很透彻,比较推荐先看这个,除了这个之外还有常见的《算法》第4版,《数据结构与算法分析》这个分为C语言描述、Java语言描述的不同版本,这两本也都很不错。另外仍然推荐极客时间上的课程《数据结构与算法之美》https://time.geekbang.org/column/intro/100017301,作者是之前Google的工程师王争,之所以推荐这个是因为作者抓住数据结构与算法的重点来讲解,核心的内容讲的很透彻,而不是上来就讲实现,所以这门课还是可以作为辅助学习的。

学数据结构与算法的过程也是提高编程能力最有效的过程,建议在学习过程中,使用自己擅长的编程语言将常用的数据结构、算法都实现并封装一遍,可以感受到在这个过程中编程能力的飞速提高,建议使用C语言来实现,因为C语言更贴近于底层,用C语言来练习可以提高自己对于C的内存管理、指针、数据底层的存储、程序设计范式等各个方面的认识,从此之后就再也不会惧怕C语言了,你一定会对代码和数据理解更深,感觉这些东西原来这么简单,所以学习数据结构与算法一定多思考,写代码。

借着编程能力不断提高这个机会,如果有时间也可以继续学习《计算机程序的构造和解释》https://book.douban.com/subject/1148282/,这本书会让你对程序抽象设计本身有更深的认识,对代码表示的思想认知会有很大的提高,从而不会再迷失在代码中了。

最后,如果觉得上面都太容易,那就去看《算法导论》吧

3.操作系统

操作系统这方面经典的书籍比较多,这里主要推荐《操作系统导论》https://book.douban.com/subject/33463930/,这本“导论”要比楼上的“导论”更适合入门哈哈,可以作为麻省理工MIT 6.828操作系统课程的参考书,这里推荐两个课程,分别是MIT 6.828 https://www.bilibili.com/video/BV1px411E7ST以及HMC CS 134 https://www.bilibili.com/video/av47977122,遗憾的是这两门课程都是英文字幕,所以英文不好的难度有点大,不过看《操作系统导论》也是极好的。

其次就是推荐《操作系统:精髓与设计原理》https://book.douban.com/subject/5064311/,这本书写的也很不错,比如清华大学操作系统的课程就是按照这个书的内容讲的,B站链接:https://www.bilibili.com/video/BV1uW411f72n,这个课程讲解比较通俗,涉及细节不是太多,相对于上面的国外课程简单很多,可以作为入门学习,同时以《操作系统:精髓与设计原理》作为教材,然后就是推荐哈工大李治军老师的操作系统课https://www.bilibili.com/video/BV1d4411v7u7,这个内容就深入很多,可以作为进阶,啃完之后操作系统的基础肯定是没问题的。

另外还有本《现代操作系统》https://book.douban.com/subject/27096665/,这本书由于风格问题争议比较大,说好的不好的都有,如果有时间也可以看一下,看看自己是什么体会。

上面主要是通用的操作系统原理性的学习,基础掌握之后我们可以主动探索某一个具体的操作系统设计,对于工程师来说当然就是Linux了!推荐《Linux内核设计与实现》https://book.douban.com/subject/6097773/,短短300页将内核将的比较清楚,读者会有整体的感觉,即使是书中基于过时已久的Linux 2.6内核也绝不失指导意义,对Linux内核有一定了解认识之后,你应该就自然会知道自己想学习的方向以及主动寻找适合自己的资料。

4.计算机网络

计算机网络部分最适合学习的书籍当然是《计算机网络:自顶向下的方法》https://book.douban.com/subject/30280001/,这本书有自己独有的特色来讲解整个计算机网络的演化,读起来体验也非常流畅,同时推荐B站的计算机网络微课堂,作为辅助学习https://www.bilibili.com/video/BV1c4411d7jb

另外如果有时间还可以看一下日系图解系列的书,比如《图解HTTP》和《图解TCP/IP》、还有偏向科普的《网络是怎样连接的》,还有韩系的《TCP/IP网络编程》,这几本书读起来都是非常轻松有趣的,有时间读一下一定会有新的灵感。

最后如果还想更上一层楼,就可以看重磅书籍《TCP/IP详解》,这一系列一共分为3卷,分别是:协议、实现和TCP事务协议、HTTP、NNTP和UNIX域协议,其中每卷都是非常厚,不适合入门学习,所以最推荐的仍然是上面的《计算机网络:自顶向下的方法》,如果有精力再来了解详解也是可以的。

5.数据库系统

数据库是和工程师日常最贴近的软件系统了,可以说大部分时间我们都是在和数据库打交道,因此学习数据库系统技术可以非常明显的提升自己的能力,无论是软件研发、性能调优、故障排查都有层次性的提高,因此学习数据库之后,就不再是简单地CRUD,而是深知这背后的逻辑,写出更稳定可靠的程序,这里推荐书籍《数据库系统概念》第6版链接:https://book.douban.com/subject/10548379/,内容非常详尽,可以掌握扎实的数据库基础,然后再学习各类开源的数据库系统就非常简单了

6.分布式系统

分布式对于从事大数据或者架构工作的工程师来说是必不可少的,当前所有的主流存储、计算框架都是基于分布式系统的基础构建起来的,和数据库一样,掌握分布式系统的关键技术也可以快速提高开发以及架构设计的能力,分布式技术学习推荐《数据密集型应用系统设计》https://book.douban.com/subject/30329536/,这本书强烈坚持看完并吸收,知识面非常广,学习之后会对系统有更深的认识,然后再来阅读具体框架的英文文档,这样会发现很多基础都是相通的,所以这本书学习的意义甚至超过操作系统。

7.编译原理

之所以把编译原理放到最后是因为这门课的难度非常大,不如前面有趣,看起来好像和我们做软件开发没有什么关系,但是我们却每天都会用到,只是编译器帮我们做了太多的东西,如果能真正理解编译器是如何工作的,那么不仅会帮助我们写出更优的代码,而且有可能为其他人创造更多工具,另外意义上来说,这就是使用者和创造者的差距,即使我们不去开发改变世界的工具或者系统,但是我们也一定对程序设计本身有质的改变,这样在面对大型复杂的系统时,我们一定会比普通工程师具有更明显的优势,是非常有可能创造性解决问题的,对于编译原理的学习,当然推荐《编译原理》这本“龙书”,https://book.douban.com/subject/3296317/,当然如果更追求趣味性可以阅读国外的Crafting Interpreters网站,首页为https://craftinginterpreters.com/,具体内容页面:https://craftinginterpreters.com/contents.html,当然这个网站上写的条理非常清晰,随时可以在线阅读,看完之后你可能会发现编译原理也是非常有趣的。

同时可以结合B站的斯坦福编译原理 CS 143来辅助学习,链接有好几个,可以选择学习:

1.https://www.bilibili.com/video/BV1cE411f78c

2.https://www.bilibili.com/video/BV17K4y147Bz

3.https://www.bilibili.com/video/BV1NE411376V

8.数学(可选)

虽然作为软件工程师可以不用太多的数学知识,但是毫无疑问,数学学习好的人学习计算机科学一定是更有优势,并且所有优秀的计算机科学家都是数学家,其实计算机科学本身就是数学的一个分支,只是在计算机工程方面,表面上看数学弱化了,其实每一个领域都具有大量的数学,所以学好数学不仅有助于学习计算机方面的技术,更重要的是我们掌握了可以迁移到任何领域的基本能力,这样我们在面对任何问题时都会系统性思考,更有逻辑的解决,同时也会更有信心,数学和上面的数据结构和算法一样,都是工程师的内功心法,具体的数学知识在机器学习部分已经介绍过一部分了,其实高中和大学课程我们掌握的差不多就基本上够用了,唯一缺少的方面其实就是离散数学了,所以这里推荐一本《离散数学及其应用》第5版链接:https://book.douban.com/subject/2130743/,这本书功力非常深厚,目前已经出版到第8版了,看完离散数学后,你可能会真正发现计算机中所有的问题、算法思路、软件底层的实现原理在这里面基本上都能找到答案,同时推荐中国大学MOOC上的离散数学课程来学习https://www.icourse163.org/course/UESTC-1002268006,这个课程质量还是比较好的,最后还是万能的B站https://www.bilibili.com/video/BV1cs411H7sz,这个是电子科技大学的离散数学课程,也非常优秀,其实对于工程师来说数学需要经常复习,保持这种思维或者思考方式来解决问题就可以了。

上面的可以看做比较严谨的专业数学课程,也可以看一些比较轻松的,比如:《计算机科学中的数学》、《程序员的数学》、《数学之美》这些,虽然不能系统完整的学习数学,也可以学到很多有趣的知识,如果感兴趣每个点都可以深入,这些书可以作为科普闲暇时间阅读还是不错的。



目前对于计算机科学系列的自学计划大致就是上面这些内容,每一门课程不仅有深度而且涵盖面也比较广,整个体系还是非常丰富的,另外对于学习我们一定要学习精华的东西,甚至宁缺毋滥,学习真正有用的知识,而不是为网上各类资源所束缚,什么都想学上一下,什么都想看一眼,那得多累呀~,要学习先要懂得舍弃,无需太多准备,只要路径大致正确,其他的学起来就可以了,一定不要忽视长期坚持的价值!那么对于工作和学习该如何协调呢?我的看法是要并行,工作一定要做好,同时遇到问题去实际解决并及时整理总结,提高自己的工程能力,属于零散的积累,然后业余时间要长期坚持系统性的学习,一定会不断发现原来工作中的困惑都变得很透彻了,自己理论的提升也会促使工作更加出色,总结来说工作的根源在于理论的认知,而理论的充实可以让自己工作的更优秀,如此形成良性循环,自己的知识体系会不断补充完善,而这绝不是短期的速成,一定是背后长期坚持不懈的学习提升,以及日拱一卒的累积!另外上面这些所有的课程如果有能力,尽量看英文原版的,学起来会更透彻,像我这种英文渣渣只能看翻译的了。

这个课程体系也是参考网上比较火的TeachYourselfCS以及其他大佬的推荐,加上自己学习的思考整理出来的,不一定适合每个人,但相对于大学的课程,肯定还是及格的哈哈,如果有任何问题,欢迎指出来,感谢!

reference:

Teach Yourself Computer Science:https://teachyourselfcs.com/

TeachYourselfCS中文翻译:https://github.com/keithnull/TeachYourselfCS-CN

硬核计算机科学自学计划:https://github.com/spring2go/cs_study_plan