计算机基础知识对程序员来说有多重要?
程序员吴师兄
读完需要
7分钟速读仅需 3 分钟
数据结构和算法,操作系统,编译原理,计算机组成原理这些课程对普通程序员来说是否需要去学习?会带来哪些帮助?
这是一个知乎上的热门问题,以下是我的回答。
我们依次来了解这几门课程是在工作中有啥用,回答有点长,请保持耐心:)
1
一、数据结构与算法
正如 N.Wirth 教授所说的:数据结构+ 算法=程序。
遇到一个实际问题,充分利用所学的数据结构,将数据及其之间的关系有效地存储在计算机中,然后选择合适的算法策略,并用程序高效实现。
这句话可能有点抽象,我举个例子给你们解释一下。
在工作过程中,我们多多少少都接触过 OAuth2 ,在使用 OAuth2 授权的时候,通常应用会弹出一个类似这样的信息:
1) 获取用户基本信息接口
2) 获取用户列表接口
3) 用户分组管理接口
。。。
思考一下,如果让你设计数据库,应该怎么设计信息存储权限?
如何你熟练掌握了各种数据结构的特点的话,那自然而然想到使用 bitmap 来存储权限。
我们把权限划分成最小粒度之后,每一个 bit 都它的含义, 例如我们把权限划分为以下几种:
获取你的头像、性别、昵称等基本用户信息
以你的身份发布微博
获取你的好友列表
获取你的朋友圈信息
每勾选一个选项,就代表着这个权限被授权,为了保证可扩展性,我们使用一个 uint64 来保存这些 bit ,也就是说,我们一共可以划分 64 种细分权限,然后对这些权限进行组合。
例如,第一个 bit 如果设置了,那么就代表可以获取你的昵称、头像、地区、性别等基本用户信息, 第二个 bit 如果设置了,就可以用你的身份发状态。
数据结构的实际作用还有挺多,感兴趣的可以搜索以下知识点:
二叉树搜索用于中断处理、登记缓存查找等
哈希表,用于实现索引节点、文件系统完整性检查等
红黑树用于调度、虚拟内存管理、跟踪文件描述符和目录条目等
Radix 树,用于内存管理、NFS 相关查找和网络相关的功能
......
上面这些例子是关于数据结构的,我再举一个算法的例子。
同样的也来思考一个问题:计算机的缓存容量无论再大,缓存满了还是要删除一些内容,给新内容腾位置。
那么删除哪些内容呢?我们肯定希望删掉哪些没什么用的缓存,而把有用的数据继续留在缓存里,方便之后继续使用。那么,什么样的数据,我们判定为「有用的」的数据呢?
这个时候采取的策略就是 LRU 缓存淘汰算法。
LRU 的全称是 Least Recently Used,也就是说我们认为最近使用过的数据应该是是「有用的」,很久都没用过的数据应该是无用的,内存满了就优先删那些很久没用过的数据。
具体的关于 LRU 缓存淘汰算法 的介绍可以看我之前写的一篇文章。
2
二、操作系统
先来看一下操作系统都有哪些内容。
现代计算机系统由一个或多个处理器、主存、打印机、键盘、鼠标、显示器、网络接口以及各种输入/输出设备构成。
说实话,程序员不可能会掌握所有计算机系统的细节,所以在硬件的基础之上,计算机安装了一层软件,这层软件能够通过响应用户输入的指令达到控制硬件的效果,从而满足用户需求,这种软件称之为 操作系统 ,它的任务就是为用户程序提供一个更好、更简单、更清晰的计算机模型。
我们依旧通过一个例子来解释操作系统在工作中的帮助。
例子来源于 知乎大佬 @invalid s 。
比如说,做一个网络代理软件,不过是从 socket 上收一个包然后转发给另一个 socket 而已,这好像和操作系统没多大关系吧?
但真做了,你会发现,用一个线程处理网络 IO,只要写对了,那么哪怕系统压力很大,只要 CPU 顶得住,就可以保证引入的延迟总是在几个毫秒之内;但如果用了多线程分别处理收/发,那么只要网络压力稍大,引入的延迟就会增加,很快额外延迟就可能突破几十个毫秒(这实际上已经完全不能用了)。
想搞明白这是为什么,对操作系统调度原理、时间片等概念没有足够深刻的理解,是不可能的。
尤其是,当你突然遇到类似“系统压力一大网络延迟急剧升高”的 bug 时,如果对操作系统没有深入理解,你连准确描述都做不到,连查资料、求帮助都不知道该往哪个方向努力,更不用说 debug 了。
换句话说,你可以不造轮子,但是你要知道这轮子是怎么造的,否则你连问问题都不知道如何去描述。
再降维一点,你总要掌握如何安装 Windows 系统吧,否则妹子让你去她房间里修电脑你都只能拒绝掉!
3
三、编译原理
众所周知,编译技术是计算机科学史上的明珠之一。
对于编译原理,很多程序员的困惑就是:我也不会去设计一门新的编程语言,有必要学习编译原理吗?学了有什么用呢?
实际上,编译原理不是用于炫耀的屠龙技,程序员在工作中经常会碰到需要编译技术的场景,比如:
编写界面模板引擎;
为项目编写各种各样的 DSL;
深度理解甚至开发出 Spring、Hibernate、阿里巴巴 Druid 这样的工具。
除此之外,解析用户输入,防止代码注入,为前端工程师提供像 React 那样的 DSL,像 TypeScript 那样把一门语言翻译成另一门语言,像 CMake 和 Maven 那样通过配置文件来灵活工作,运维工程师分析日志文件等等高级别的需求,都会用到编译技术。
当然,说实话,编译原理并非随随便便就能入门的!
换言之,需要准备一些基础知识在学习。
编译原理的学习和实践通常基于对计算机编译过程、计算机基本工作原理、甚至一定的数学知识有一定积累,这些知识分别分布并应用在了编译原理的不同阶段。
没有这些基本知识的积累,很快就会在某个阶段由于功底不够而无法再继续后面的学习。
所以不要一开始就去啃编译原理。
4
四、计算机组成原理
从上面这张图可以看出来,整个计算机组成原理,就是围绕着计算机是如何组织运作展开的。
我们依旧来举例子:)
每个程序员应该都知道 Ascii 码,GB2312,GBK,Utf8,Unicode 等编码格式,如果你没接触过,那总出现过文件压缩后解压乱码的情况吧?
了解了这些编码的存储格式,你才会明白为什么会有中文乱码问题,靠,我在写这个回答的时候,我的后端同事发给我的日志就出现了中文乱码。。。。
再来个例子。
我们上面举的关于 LRU 缓存算法 的例子,它的设计也是借鉴计算机组成原理的内容的,
在计算机的世界里,空间换时间,时间换空间这个概念在复杂的设计中时常出现。
如果你想更详细的了解 计算机组成原理 的知识,推荐一本书:《计算机组成:结构化方法》。
书的内容完全建立在“计算机是由层次结构组成的,每层完成规定的功能”这一概念之上。
1、数字逻辑层
2、微体系结构层
3、指令系统层
4、操作系统层
5、汇编语言层
6、并行体系结构
以上就是我对 计算机基础知识对程序员来说有多重要 的一个回答。