如何学电脑基础知识 怎样才算一个计算机知识体系完整的毕业生

栏目:军事 2021-09-26 20:10:58
分享到:

前言

为什么突然想写这个题目?

最近有很多新读者在后台问:学Java和C++哪个更好找工作,前端和后端哪个更好,Vue和React哪个更好。。。

仿佛看到了当年自己的样子,觉得有必要单独写一篇文章,以计算机应届毕业生的身份谈谈。我认为计算机专业的学生在大学四年应该学习什么,重点是什么。

同样是大学四年,为什么有些学生毕业后成了大厂Offer矿车,各种SP和SSP都拿到了软手?有同学明明在学校写了很多网站,项目经验也满满的,但是春秋搬家之后找工作就很难了。

不能说后者没有好好学习,也许用力的方向错了。

话不多说,言归正传吧。

文本

人类知识的边界一直在不断扩大。俗话说,学无止境,这也适用于计算机领域。计算机本身是人工科学,不是自然科学。

每年,甚至每个月都有新的编程框架不断推出,学秃了学不完,没必要一个一个学。

而且你会发现很多一二线厂商基本上都是自己做一套东西,比如服务发现、RPC、KV、DB、消息队列、日志、监控等等。

所以一般来说,这些大公司招聘的时候,基本上不会因为没有学到一定的框架就吊死你。反正很多东西都要进来重新学习。

他们会更注重你的基础知识、解决问题的经验和更一般的智力能力。

相反,一些小公司可能会要求你了解Spring、Vue、Redis等框架或组件。

腾讯京东

阿里JD

某外包JD

以上是某外包公司招聘的腾讯、阿里、京东。显然,腾讯阿里感兴趣的是扎实的基础编程技能和快速的学习能力,这意味着有培养的潜力。

外包公司要求你了解xx数据库,Spring等等。不评判哪个更好,但如果你想去BAT,至少是提高自己对抗他们JD能力的捷径吧?

在这里,我简单地将计算机编程领域的知识分为三个部分:

基础知识

特定领域知识

框架和发展技能

基础知识是指任何方向的软件工程师都应该掌握的,比如数据结构、算法、操作系统等。

特定领域知识是从事某个细分方向时需要掌握的知识,比如当游戏引擎时掌握图形;做前端,需要掌握浏览器渲染原理和前端;算法工程师需要更多的数学知识。

毕竟电脑的种类很多,所以我们需要选择一个细分的方向去研究。如果我们什么都学,我们只会一无所获。我们想学SpringBoot还是SSH?

花时间在算法和基础科目上不是很香吗?实际上,回报会更大。

而且在计算机领域,很多基础理论都不是很先进,通过努力可以掌握核心知识。

1.1数学

首先,这里列举的数学并不是为了高端,而是为了苦于数学的弊端。

如果你是自学的程序员,我肯定不会推荐数学,因为转行的大概率是学Java,前端之类的,对数学基本没有要求。

然而,这篇文章主要是针对还在大学的学生。这些学生将来可能会做算法、游戏引擎、信息安全编码等等

这些方向对数学的要求更高。在计算机领域,线生成、概率论、统计学等数学分支相对重要,计算机本质上还是离散的。

例如,在机器学习或数据挖掘中,经常使用线性代数来降低数据维数,许多问题最终可以简化为求解线性方程。

所以,为了避免以后想往这些方向走的时候数学陷入困境,大一大二的时候上数学课的时候就要好好学习。

用书的时候少恨。不要觉得学了没用。当你需要他们的时候,你会知道你后悔了。。

而当你真正开始项目的时候,你会发现很多问题都和操作系统息息相关。如果你不了解操作系统,你甚至不能分析问题的原因。

比如前段时间,在基于协同学的框架下,我们用多线程锁做同步互斥意外死锁。后来,我们发现了原因:

因为协同程序是由应用层实现的,所以一个线程中的多个协同程序是操作系统察觉不到的:

协同模型

然后,当一个共名A锁定并发起网络IO请求时,会切换到另一个共名B,共名B会再次请求锁定。

此时操作系统会认为锁已经被锁定,所以会将协调器B对应的线程挂到等待队列中,导致协调器A永远不会运行,也不会释放锁,导致死锁。

解决方法也很简单,就是把锁设置为可重入锁,也就是说同一个线程多次请求同一个锁不会导致挂起。这样,当协调器B再次请求锁时,操作系统会认为协调器B所在的线程已经持有锁,直接返回继续执行。

总之,我们的编程无时无刻不在与操作系统交互,没有理由不学好。

1.4编制原则

编译原理可能是我们平时接触最少的,人们可能会觉得不需要构建新的编程语言,也不需要学习编译原理。

学好编译原理有什么用?

你会从更高的角度去看待这些编程语言,你不仅会看到表面的语法,还会想到语法背后的实现。

这种感觉很透彻,就像理解操作系统和架构一样,双击鼠标你就会明白一个程序是怎么运行的。这种掌握所有细节又透彻的感觉真的很奇妙,试试吧。

说人话!

学了编译原理可以做什么?

当你学完有限状态机,你会发现以前很牛逼的正则表达式好像是DFA和NFA实现的。状态机的思想可以用在编程的很多地方。

比如解析HTTP协议,如果还没有学会状态机的思想,可以用if/else一行一行的做解析。这里最麻烦的是if/else在判断之前需要提前接收所有的HTTP头字段,但是我们知道HTTP是基于TCP的,而TCP是流传输,所以很有可能你是几个字符一组一组的收到的。这个时候用if/else来写是很难看的。

用状态机写的代码会非常优雅。状态转换是由规则驱动的,接收到一个字符后判断非常方便。

继续学习语法分析后,你会掌握递归下降分析非常重要的思想,可以用递归下降快速实现四个算术计算器。

如果不需要递归下降,可能需要先把中缀表达式翻译成后缀,然后再求值。这是我们大一数据结构课写的,当时是栈写的,有点麻烦。后来学了编译原理,用递归下降重写,只写了几十行代码。

还有一种场景在实际开发中被大量使用,比如淘宝、JD.COM这样的电商公司,有很多营销规则,比如全减、直减、跨店等。这样的规则不能写在代码里。

这是怎么做到的?

一般会实现一个配置系统,设计一个DSL来表达这些规则,将规则直接配置到系统中,可以非常方便的修改。那么如何解析代码中DSL定义的规则呢?有必要为DSL编写一个解析器,这里将使用解析的方法。

DSL是一种用于特定领域的编程语言。与特定领域的C、C++、Python相比,通用语言可以应用于各个领域。我们熟悉的大多数编程语言都是通用语言,都是图灵完备的。

我们经常使用的JSON、SQL、HTML都是DSL。你甚至可以尝试通过递归下降的方式编写一个JSON和XML解析器,这比编写电子商务网站更有价值。

如果你继续学习,你将学习如何生成抽象语法树AST,如何将其转换为中间代码,如何优化中间代码,最后如何生成机器指令。

您将看到贪婪算法在寄存器分配中的应用,也将看到图论中的可达性分析如何消除死代码。

IDE上的绿色编译按钮对你来说不再是黑暗魔法。

为什么一次点击就可以生成一个可执行程序?

你写的英文字母是怎么变成二进制指令的?

学完编译原理,这些都不是问题,妈妈再也不用担心你的学习了~

当然像GCC和Clang这样的编译器完成起来太难了。学习编译原理的目的不是为了构建这样的轮子,而是为了更好地理解和使用编程语言。

1.5架构和组成原则

以上都是关于软件的,架构是关于计算机如何工作的。您将了解典型的存储程序计算机是如何工作的。

我记得NTU的一位老师说过:“我们不学习使用计算机,而是学习如何制造计算机。”虽然造计算机有点夸张,但至少我们需要了解计算机的实现原理,以及代码是如何被CPU执行的。否则,其实你会很迷茫。一堆英文字母怎么可能在CPU这样的电路上运行?大一学C的时候很困惑,直到学了作文原理和数字逻辑。

我们说计算机中的一切都是0、1、0、1,用高低电平表示,二进制数值运算用and、OR、NOT等逻辑门表示,然后把这些简单的电路集成在一起,就形成了ALU这样的具有运算能力的处理器。

你可以看到一条指令是如何被中央处理器执行的,它从内存或缓存中取出指令,放入指令寄存器,并对指令进行解码。解码是根据指令的编码规则将指令拆分成一系列微操作和操作数。然后,发出各种设备控制指令来执行微操作。这就完成了指令的执行。

我们说,学习了编译原理之后,就能理解书面的英文代码是如何变成二进制指令的,学习了操作系统之后,就能理解二进制程序是如何链接在一起的,是如何被操作系统加载和执行的。组成原理会告诉你二进制指令是如何控制CPU运行的,我们的操作系统本质上就是一个二进制程序。

当你理解了计算机存储层次结构和多级缓存,你将通过优化数据访问方法编写更快的程序。

您将学习底层架构对C语言堆栈框架和参数传递的支持,以及参数如何传递给另一个函数。如何获取函数的返回值?

这就是学习作文原理对于写代码的意义。

学习这些东西有什么意义?

你完全可以看到写出来的代码是如何变成二进制指令的,以及如何控制各种门电路,最后变成屏幕上五颜六色的程序。这就是我们常说的“基础”和“原则”。

而且计算机架构中的很多思想都可以广泛应用于现代软件开发中,比如CPU的多级cache思想,就是服务器开发中常用的提高并发性的cache技术,包括Cache替换策略等等。

当电脑对你来说不再是黑匣子的时候,你知道从编写代码到执行的每一步,这将成为你未来的核心竞争力。作为一名毕业生,你不应该只使用Java、Redis、Mysql和Spring来编写各种网站。

如果有读者转行或者从培训班出来,希望你能抽出空的时间来补充这些基础课程,这会让你在编程的道路上走得更远更稳。

1.6数据结构和算法

为什么把算法放在最后不重要?相反,太重要了,就让它成为大结局吧。

如果要问我大学最后悔的是什么?肯定是大一开始算法没学好,去打ACM了。

还是大一大二的学生,不要抓住机会,不要等到以后才后悔。当然,没有ACM我们也能很好地学习数据结构和算法。

你可以在任何计算机领域看到数据结构和算法。比如在编译原理中,寄存器的分配会用到贪婪,死代码的检测和消除会用到图论中不可达的知识;多级队列和调度算法用于操作系统进程和线程的调度。在合成原理上,将采用LRU、FIFO等算法代替Cache必要数据库的开发离不开B+树、LSM等数据结构和搜索算法。

很多时候,我们需要的算法都封装在编程语言的基础数据库中,所以很多学生认为算法离我们太远,其实不然。

如果不学习算法,甚至分不清什么时候用Map或者HashMap。

因此,学习算法可以帮助我们根据应用场景选择最合适的数据结构。

算法在日常开发中也是不可或缺的。比如小北近期工作中涉及的一些嵌套TLV结构码的分析,就需要递归、多分支树等知识。如果不学习算法,只能在程序中看到很多if/else和while/for。。。

可以说不会做算法的工程师一定不是优秀的工程师。

1.7我为什么不谈网络、数据库等

很多人喜欢把计算机网络和数据库原理归为计算机基础,我当然同意,因为一个知识结构完整的计算机专业学生应该知道这些知识。

但我个人认为计算机网络和数据库无非是基于操作系统、编译原理和组成原理的应用层软件。

什么是数据库?在有数据库之前,会用文件来存储数据,但是查找和修改不方便,数据库只是提高了这个过程的效率。

互联网是做什么的?网络是不在同一台计算机上的程序相互通信的手段,本质上是进程之间的通信手段。

如果只开发单机工业软件,甚至真的不学网络,只是因为现在大部分程序员都在互联网公司工作,不处理HTTP等网络协议是不行的。

还是那句话,并不是说网络和数据库不重要,而是我觉得它们属于建立在操作系统上的软件,不包含在基础里面。

二、领域知识

这个我不敢说太多,因为我对各个领域都不太了解。简单提一下,就是抛砖引玉。

如果你想去腾讯和网易做游戏引擎开发,那么显卡肯定是你无法回避的。除此之外,你还要学习渲染管道、着色器、物理、灯光等等。

如果你想在像PingCap这样的公司做分布式存储,那么分布式理论的知识一定是你无法回避的网关,包括Cap定理、Paxos算法、Raft算法、ZAB协议等等。

如果你想写一个数据库,你需要知道很多东西,比如磁盘、索引实现、SQL解析、事务、如何解决与MVCC的读写冲突等。您还需要了解编程语言级别的很多东西,例如锁、信号量和并发编程技能。必须说,建立数据库是一项脏活累活。

进一步说,如果想做分布式数据库,可能要学习数据分片的知识,如何做查询任务,是集中做,还是把逻辑下推到各个节点,如何实现分布式事务等等。

你说你只想去CRUD?没错,老铁!

然后你要熟悉一门编译语言,理解一些语言的底层原理,比如C++。你要看STL和对象模型。你不知道任何虚函数表。智能指针想去腾讯写C++?你必须记住Java中的JVM和垃圾收集算法。如果你不看ConcurrentHashMap,你可以说你做Java。

我们的CRUD对象是数据库,对吗?你不必学习如何很好地使用数据库。用户通过HTTP访问我们的服务,所以他们一定知道HTTP,对吗?对了,别看TCP三次握手,四次挥手。你怎么敢说你学计算机?

当用户把钱和信息放在这里的时候,我们一定要保证用户数据的安全,对吗?你一定要知道一些常见的Web攻击方法,比如XSS、SQL注入、CSRF?必须知道HTTPS、RSA、签名和数字证书。

双十一的流量太大,老板还是让你不得不抵制。然后你必须了解缓存、异步、消息队列和NoSQL,它们是成千上万QPS人的必要杀手。

你看!做好CRUD不是那么容易的。

以发展计算机为主力军。大二的时候看了王莹的《完全用Linux工作》,直接在u盘壳上买了一个SSD,做了一个启动盘。后来我用了将近一年的Ubuntu,只有选课、交作业的时候才打开Windows。

摘要

写完之后发现这篇文章的篇幅是“基础:领域知识:技能”接近7: 2: 1。

这也是我建议你在大学期间分配学习时间的比例。至少学习基础知识的时间不少于50%。当然,在你学会了所有这些东西后,你可以寻找有趣的方向并专攻它们。

大一大二千万不要一头扎进Java Web、Python爬虫之类的东西。这些东西可以学,但不是重点。

由于篇幅所限,本文没有具体说明如何学习,有哪些好的资料。我准备单独写一篇“如何”的文章,持续关注我~

那么你如何测试自己的表现呢?

我相信你一定听过这样一个面试问题:“从URL输入到页面呈现发生了什么?”

这个问题的另一种表达是“数据包是如何发送到另一台计算机的?”。

如果你能完整地讲述整个过程,那么你一定学会了如何数网!这也是为什么面试这么喜欢问这个问题的原因。

然后让我们根据葫芦画提出一个问题

"从写下代码到程序运行这段时间发生了什么?"

这个问题的答案越详细越好。基本上你可以讲清楚,你就会明白编译原理、操作系统原理、组成原理。

这个问题也放在这里。后续总结请留意编程方向。

唉,要是这么有思想的学长告诉我这些,我也不会花半年时间在Andorid开发、Java Web、Python爬虫上玩。。。

幸运的是,我意识到了基础的重要性,开始学习汇编,重新学习C,做mini os,阅读Linux内核实现原理,最后成功掉毛。。。

最后想给大家说一句我很喜欢的话:

不要在流沙上建高塔。

日常聊天

小北的每一篇文章都写得很认真。每一个转发、关注和赞美你的人对我来说都很重要。动动小指,点一下~

遇到这样的良心博主,没有一波一键三连,你的小心脏不会痛吗???

(说实话,如果有大一大二的,真心希望你转发给你的好朋友,可能对他很重要。

目标