如何成为一个计算机知识体系完整的毕业生
# 如何成为一个计算机知识体系完整的毕业生
作者:冯昱尧(知乎) (opens new window)
一般来说我喜欢把计算机或者直白一点讲“写代码”的知识分为三大类别:基础知识、领域知识和碎片知识。
基础知识指的是你要吃写代码这碗饭必须掌握的通识性质的内容。即数学+计算机五大件。
领域知识指的是你要精研某个方向时所要掌握的知识。写代码不同的方向之间差别还是很大的,很难多方面兼顾。
碎片知识指的是一些实践中经常用的技巧或者一些不成体系,但又很有用的“常识”。这些知识虽然很琐碎,但是对于项目实践来说是必不可少的。
# 1. 基础知识
# 数学
先说数学,我知道很多有经验的前辈都会告诉你数学其实没有什么用处,基本上平时做业务之类的根本用不上。这话没有问题,毕竟你做做 GUI 什么的是不需要微积分的。而且工作中大量的内容也是业务相关的,但是作为你选择某一方面精研之前的通识知识还是非常有必要掌握它的。不然你的路只会越走越窄。
有相当一部分领域知识其实是需要数学基础的,比如图形学、机器学习、游戏里的物理模拟等等。主要内容就是三门课 微积分、线代、概率。个人感觉常用程度上来说应该是 线代 > 概率 > 微积分的。
接下来是计算机五大件 《数据结构》、《计算机组成原理》、《操作系统》、《计算机网络》和《编译原理》。这五门课是你以后做任何方向的基础。
有的同学可能觉得这几门课中的某几门没有什么卵用。然而事实上在任何一个方向中深入以后都会和这几门课的内容纠缠在一起(计算机网络可能特殊一点,毕竟有单机的程序)。而且这几门课中所表述的思想以及解决问题所使用的模式和方法论可以说涵盖了整个计算机知识体系的精华。有时候虽然是完全不相干的领域,但是解决问题的思路却和某几门课中的方法惊人的相似。
# 数据结构
《数据结构》是所有课程的基础,重要性就不用提了,没有数据结构基本上没法写代码。
# 计算机组成原理
《计算机组成原理》这个可以薄弱一些,毕竟写代码其实和硬件打交道的机会不多。但是整个计算机运行的流程一定要搞清楚,例如缓存、内存、寄存器、CPU是如何执行指令的,IO设备是怎么输出的。一般汇编语言也会在这门课程中教一部分。有部分对于性能要求很高的程序会需要这方面的知识,比如高性能的服务器、游戏等等。
# 操作系统
《操作系统》理论上来讲你所有写到的程序都是运行在操作系统上的。文件系统 、内存管理、进程管理、I/O 这都是写一个程序必不可少的内容。缺了这一门你可能就会出现写多线程程序却不知道怎么加锁之类的低级错误。如何进行进程间的通信?如何使用系统调用?如何处理文件?等等等等
# 计算机网络
《计算机网络》这一部分其实和《操作系统》有一小部分重叠。作为一个合格的程序员,至少要能闭着眼睛说出来TCP/IP五层协议栈是什么每层的主要功能是什么。不过在实践中一般重点把握传输层,自上而下掌握到 IP 层就可以了。对于编写网络程序来说是必不可少的内容。
# 编译原理
《编译原理》很多人觉得我又不发明编程语言,《编译原理》没什么卵用。其实不然,你看web里常用的模板引擎不就是用编译原理的知识写的么。那帮搞前端的程序员搞到最后哪个不是在搞编译(笑)。掌握这门课一来可以让你在处理程序错误的时候更加的熟练,另一方面可以利用编译的知识写一些小工具,能够大大提高工作效率。在这里推荐一本书《编程语言实现模式》代替大部头学院派的《编译原理》来看真的是非常棒,作为基础知识肯定够用了。
# 其他
此外就是掌握若干门编程语言。一定是若干门而不是一门,一方面可以改变你用程序定位自己职位的想法,另一方面可以开阔视野让你在解决问题时找到最适合的工具。个人觉得静态/动态、面向过程/面向对象、编译/解释。总共凑个三门能够把这几个都覆盖了应该够用了。比如 C++、C#、Lua(写游戏),Java、Js、Python/PHP(偏web一点),C++、Python、Matlab(科学计算)之类的组合都是不错的。
最后就是软件工程的内容,大部头的东西可能大家没有兴趣看,但是一些软工的常识还是要知道的比如bug只和行数相关啊,往项目中不断加人并不会加速之类的。设计模式什么的还是要知道的,最起码常用的单例、工厂、装饰器等等都要清楚。我不是提倡过度设计,但是如果不知道你看别人的代码很可能会一脸懵逼。
# 2. 领域知识
对于不同的细分方向所需要掌握的领域知识是不同的,在你打好基础以后,如果想要成为一个“有用”的程序员,必然还需要掌握至少一个方面的领域知识。
比如说做web的 HTTP 协议要搞清楚吧,前端的同学浏览器相关的东西什么响应式啦、什么Restful、什么兼容性、什么跨域、什么XSS什么浏览器渲染网页的要搞清楚吧。
我本职工作是做游戏的其他的就不乱说了。拿游戏来举例子吧。首先要熟悉一款游戏引擎吧,其次游戏中常用的编程模式要知道吧,像什么游戏循环、双缓冲、更新方法、对象池。AI方面行为树和状态机要清楚。渲染方面基本的一个渲染流程要明白,能写shader最好等等。只是举个简单的例子,意思就是再掌握基础以后你需要将这些基础应用到一个特定的领域上去,你的体系才算是完整,不然就算是一个毛胚生。
# 3. 碎片知识
为什么叫做碎片知识呢,因为这部分内容其实还蛮难划分的,甚至你很难叫他“知识”,也许只是一些小技巧,常识之类的东西,但是却在工作中有很重要的地位。
这里推荐一本书《程序员修炼之道: 从小工到专家》虽然名字很山寨但是确实是一本好书。因为不存在体系我想到哪里就写到哪里了,可能会有遗漏,不过大家领会这个意思就好:
# 调试
调试其实是一门学问,但是很少有人会把调试作为一个单独的课程或者知识体系来说。但是他对于你写代码来说又是必不可少的。至少要会二分调试法吧,单步调试/日志输出调试,小黄鸭调试法等等。再复杂一点,如何利用操作系统提供的工具去Attach进程,监控他们的工作状态。调试网络程序时如何抓包等等。都是需要花时间来学习的。
# 版本管理
什么分支合并、如何解决冲突、如何合作、如何回滚等等。
# 工具
各种 IDE 啦,编辑器啦,包管理,Diff工具,工作流管理等等等等。需要花费一定的时间去学习。
# 检索信息
如何查找一手资料,查找官方文档、如何快速切入一个新的库或者项目等等,无数次有人私信里边问我文档里写的清清楚楚的东西,让我觉得这实在是一种需要学习的能力。
# 开源文化
什么是开源、如何加入一个社区、如果为开源项目做贡献、如何编写文档等等