前言
為什么突然想寫(xiě)這個(gè)話題呢? 最近有不少新關(guān)注的讀者,在后臺(tái)問(wèn):大學(xué)學(xué) Java 和 C++ 哪個(gè)好找工作,學(xué)前端好還是后端好,該學(xué) Vue 還是 React。。。 仿佛看到了自己當(dāng)年的模樣,所以覺(jué)得有必要單獨(dú)寫(xiě)一篇文章,單純以一個(gè)計(jì)算機(jī)應(yīng)屆畢業(yè)生的身份聊聊,我認(rèn)為大學(xué)四年,計(jì)算機(jī)科班學(xué)生應(yīng)該學(xué)些什么,哪些才是重點(diǎn)。 同樣大學(xué)四年,為什么有些同學(xué)畢業(yè)就能成為大廠 Offer 收割機(jī),各種 SP、SSP 拿到手軟,有的同學(xué)明明在學(xué)校寫(xiě)了好多網(wǎng)站,項(xiàng)目經(jīng)歷滿滿,經(jīng)歷春秋招,卻找到一份工作都很難。不能說(shuō)后者沒(méi)認(rèn)真學(xué)習(xí),或許是用力的方向不對(duì)。話不多說(shuō),直接進(jìn)正題吧。
正文
人類(lèi)的知識(shí)邊界一直在不斷的擴(kuò)張,俗話說(shuō)學(xué)無(wú)止境,這放在計(jì)算機(jī)領(lǐng)域也同樣適用,計(jì)算機(jī)本身是一個(gè)人造科學(xué),不屬于自然科學(xué)。 每年,甚至每個(gè)月都不斷有新的編程框架推出,學(xué)到頭禿你也學(xué)不完,也沒(méi)有必要去挨個(gè)學(xué)。 并且你會(huì)發(fā)現(xiàn),很多一二線大廠內(nèi)部用的東西基本都是自己搞一套的,比如服務(wù)發(fā)現(xiàn)、RPC、KV、DB、消息隊(duì)列、日志、監(jiān)控等等。 所以一般這些大廠招聘的時(shí)候基本不會(huì)因沒(méi)學(xué)過(guò)某種框架而掛你,反正很多東西都是要進(jìn)來(lái)重新學(xué)的。 他們會(huì)更加關(guān)注你的基礎(chǔ)知識(shí)、解決問(wèn)題的經(jīng)驗(yàn)以及聰明度這種更加通用的能力上。 反而是一些小公司,可能會(huì)要求你必須會(huì) Spring、Vue、Redis... 這些框架或者組件。
騰訊JD
阿里JD
某家外包JD 上面分別是騰訊、阿里、某外包公司的招聘 JD(job description),顯然,騰訊阿里看中的是扎實(shí)的編程基本功和快速學(xué)習(xí)能力,這意味著有培養(yǎng)潛力。 而外包公司就要求你會(huì) xx 數(shù)據(jù)庫(kù)、Spring 之類(lèi)。不去評(píng)價(jià)哪個(gè)好,但是如果你想去 BAT,那是不是至少對(duì)照著它們的 JD 來(lái)提高自己的能力,不失為一種捷徑。 在這里,我粗淺的把計(jì)算機(jī)編程領(lǐng)域的知識(shí)分為三個(gè)部分:
基礎(chǔ)知識(shí)
特定領(lǐng)域知識(shí)
框架和開(kāi)發(fā)技能
基礎(chǔ)知識(shí)是指不管從事任何方向的軟件工程師都應(yīng)該掌握的,比如數(shù)據(jù)結(jié)構(gòu)、算法、操作系統(tǒng)。 特定領(lǐng)域知識(shí)就是你從事某個(gè)細(xì)分方向時(shí)需要掌握的知識(shí),比如做游戲引擎的需要掌握?qǐng)D形學(xué);做前端的需要掌握瀏覽器渲染原理、前端三大件;算法工程師需要更多的數(shù)學(xué)知識(shí)。 畢竟計(jì)算機(jī)各種門(mén)類(lèi)挺多的,需要選個(gè)細(xì)分方向?qū)Q邢氯?,什么都學(xué)只會(huì)什么都不精(大佬除外啦。
一、基礎(chǔ)知識(shí)
現(xiàn)在大環(huán)境比較浮躁,很少有人愿意花心思在基礎(chǔ)上,喜歡直接學(xué) Python 搞機(jī)器學(xué)習(xí)、寫(xiě)秒殺、做商城。 找工作的時(shí)候都是想看面經(jīng)、總結(jié)速成。 但是作為優(yōu)秀的計(jì)算機(jī)系學(xué)生的你怎么能流于各種編程框架(造框架除外),糾結(jié)學(xué) SpringBoot 還是 SSH 呢? 把時(shí)間花在算法、基礎(chǔ)學(xué)科上他不香嗎?功利一點(diǎn)講,回報(bào)反而會(huì)更大。 況且在計(jì)算機(jī)領(lǐng)域,很多基礎(chǔ)的理論并不十分高深,我們努努力就可以掌握其中的核心知識(shí)。
1.1 數(shù)學(xué)
首先說(shuō)明,這里把數(shù)學(xué)列出來(lái)不是為了顯得高端,而是自己吃過(guò)數(shù)學(xué)的虧。 如果你是自學(xué)轉(zhuǎn)行當(dāng)程序員,我當(dāng)然不會(huì)推薦數(shù)學(xué),因?yàn)檗D(zhuǎn)行的大概率是去學(xué) Java、前端這類(lèi),對(duì)數(shù)學(xué)基本沒(méi)啥要求。 但是這篇文章主要面向的是還在大學(xué)的科班學(xué)生,這部分同學(xué)以后也許會(huì)去做算法(CV、NLP之類(lèi))、游戲引擎、信息安全編碼等 這些方向?qū)?shù)學(xué)要求就會(huì)偏高,在計(jì)算機(jī)領(lǐng)域,線代、概率論、統(tǒng)計(jì)學(xué)這些數(shù)學(xué)分支相對(duì)比較重要,計(jì)算機(jī)本質(zhì)上還是離散的。 比如在機(jī)器學(xué)習(xí)或數(shù)據(jù)挖掘中常常用線性代數(shù)來(lái)降低數(shù)據(jù)維度,很多問(wèn)題最終都能化為求解線性方程組。 所以為了避免以后想走這些方向卻被數(shù)學(xué)卡住,在大一、大二上數(shù)學(xué)課的時(shí)候就好好的學(xué)一下。 書(shū)到用時(shí)方恨少,不要現(xiàn)在以為沒(méi)用處就不好好學(xué),等你需要的時(shí)候,就知道后悔了。(默默流下了不學(xué)無(wú)術(shù)的眼淚┭┮﹏┭┮ 什么?你說(shuō)以后肯定做開(kāi)發(fā)方向? 那的確可以把數(shù)學(xué)優(yōu)先級(jí)放后面一點(diǎn),用得確實(shí)不多,不過(guò)上數(shù)學(xué)課的時(shí)候總該認(rèn)真聽(tīng)下吧,拿個(gè)高績(jī)點(diǎn)也是百利無(wú)一害嘛。說(shuō)不準(zhǔn)哪天你又想加入算法內(nèi)卷大軍呢?
1.2 C語(yǔ)言
你也許會(huì)很疑惑,這里明明說(shuō)基礎(chǔ)知識(shí),為什么要把一門(mén)編程語(yǔ)言單獨(dú)列出來(lái)呢? 因?yàn)樵谖铱磥?lái),沒(méi)有比 C 語(yǔ)言更適合用來(lái)理解計(jì)算機(jī)系統(tǒng)了。 我們后面將會(huì)提到的操作系統(tǒng)、體系結(jié)構(gòu) 這些東西非常適合用 C 語(yǔ)言去理解或者去實(shí)踐。 并且 C 語(yǔ)言本身的語(yǔ)言特性非常少,但是想學(xué)好又是不容易,很多人都覺(jué)得 C 語(yǔ)言難,難在哪里呢?回想了一下我大一時(shí)的感受:
簡(jiǎn)陋的標(biāo)準(zhǔn)庫(kù),幾乎沒(méi)有可用的數(shù)據(jù)結(jié)構(gòu)和算法,什么都得自己來(lái)
指針很難理解和使用
需要了解匯編、鏈接、裝載、內(nèi)存等才能把 C 語(yǔ)言用好
不巧的是,這些東西正是計(jì)算機(jī)系統(tǒng)知識(shí)的一部分,所以用 C 語(yǔ)言作為學(xué)習(xí)計(jì)算機(jī)系統(tǒng)知識(shí)是最有效率的方式。 真的很難想象用 Java 或是 Python 去給別人講解內(nèi)存,因?yàn)檫@些語(yǔ)言抽象程度都比 C 語(yǔ)言高,意味著離計(jì)算機(jī)系統(tǒng)也就越遠(yuǎn)。 在 TIOBE 編程語(yǔ)言排行榜上,C語(yǔ)言幾乎永遠(yuǎn)占據(jù)前三位,其地位自然毋庸置疑。
TIOBE-2020排行榜 而且?guī)缀跄汩_(kāi)發(fā)中用到的很多東西都是用C語(yǔ)言編寫(xiě)的,Linux、Nginx、Redis、MySQL、Git......或許你會(huì)想要探究下原理,閱讀點(diǎn)這些開(kāi)源軟件的源碼,那么 C 語(yǔ)言也是你必備的瑞士軍刀。 深入學(xué)習(xí) C 語(yǔ)言,能夠了解計(jì)算機(jī)底層的執(zhí)行原理,是理解程序運(yùn)行機(jī)制的絕佳語(yǔ)言,無(wú)出其右。 在這里,不得不引用對(duì)C語(yǔ)言最經(jīng)典的總結(jié):
任何比C語(yǔ)言更低級(jí)的語(yǔ)言,都不足以完整地抽象一個(gè)計(jì)算機(jī)系統(tǒng);任何比C高級(jí)的語(yǔ)言,都可以用C來(lái)實(shí)現(xiàn)。
這真是極高而中肯的評(píng)價(jià)! 所以對(duì)于計(jì)算機(jī)科班來(lái)說(shuō),不管你是做前端還是后端,算法還是開(kāi)發(fā),C 語(yǔ)言都建議你好好學(xué)習(xí)。這是無(wú)關(guān)方向的一門(mén)語(yǔ)言,就是基礎(chǔ)!
1.3 操作系統(tǒng)
我們編程的 IDE、寫(xiě)出來(lái)的程序全部都需要運(yùn)行在操作系統(tǒng)上,說(shuō)操作系統(tǒng)是計(jì)算機(jī)軟件的基石也不為過(guò)。 程序運(yùn)行起來(lái)就需要?jiǎng)?chuàng)建進(jìn)程,這涉及到操作系統(tǒng)的進(jìn)程管理;寫(xiě)程序需要定義變量、存儲(chǔ)數(shù)據(jù)吧,這又涉及到內(nèi)存,對(duì)應(yīng)內(nèi)存管理;有時(shí)候我們還需要讀寫(xiě)文件,這又離不開(kāi)和文件系統(tǒng)打交道;你需要學(xué)習(xí)使用鎖、條件變量、臨界區(qū)來(lái)保證程序并發(fā)執(zhí)行時(shí)不會(huì)錯(cuò)亂。 而讀寫(xiě)文件、分配內(nèi)存這些又離不開(kāi)系統(tǒng)調(diào)用(System call)。 并且當(dāng)你真正做起工程就會(huì)發(fā)現(xiàn),很多問(wèn)題是和操作系統(tǒng)緊密相關(guān)的,不理解操作系統(tǒng),你連問(wèn)題的原因都分析不出來(lái)。 比如前段時(shí)間我們出現(xiàn)的在基于協(xié)程(libco)的框架下,使用多線程的鎖去做同步互斥偶發(fā)死鎖,后來(lái)分析才發(fā)現(xiàn)原因: 由于協(xié)程是應(yīng)用層實(shí)現(xiàn)的,一個(gè)線程內(nèi)多個(gè)協(xié)程對(duì)于操作系統(tǒng)是感知不到的:
協(xié)程模型 那么當(dāng)一個(gè)協(xié)稱(chēng) A 上鎖后發(fā)起網(wǎng)絡(luò) IO 請(qǐng)求,這個(gè)時(shí)候會(huì)被切換到另外一個(gè)協(xié)程B,而協(xié)程 B 又去請(qǐng)求這個(gè)鎖。 那么這個(gè)時(shí)候操作系統(tǒng)會(huì)認(rèn)為這個(gè)鎖已經(jīng)被上了,因此會(huì)將協(xié)程 B 對(duì)應(yīng)的線程掛起到等待隊(duì)列,這樣的話就導(dǎo)致協(xié)程 A 永遠(yuǎn)無(wú)法運(yùn)行,也就無(wú)法釋放鎖,導(dǎo)致死鎖。 解決的方法也很簡(jiǎn)單,就是將鎖設(shè)置為可重入鎖,可重入意味著同一個(gè)線程多次去請(qǐng)求同一個(gè)鎖不會(huì)導(dǎo)致掛起。這樣當(dāng)協(xié)程 B 再去請(qǐng)求鎖的時(shí)候,操作系統(tǒng)就會(huì)認(rèn)為協(xié)程 B 所在的線程已經(jīng)持有這個(gè)鎖了,直接返回,繼續(xù)執(zhí)行。 總之,我們寫(xiě)程序每時(shí)每刻都在和操作系統(tǒng)交互,沒(méi)有理由不學(xué)好。
1.4 編譯原理
編譯原理可能是我們平時(shí)接觸得最少的了,大家也許會(huì)覺(jué)得自己又不用去造新的編程語(yǔ)言,學(xué)編譯原理干啥。 學(xué)好編譯原理有啥用? 你會(huì)站在更高的角度去審視這些編程語(yǔ)言,看到的不再是表面的語(yǔ)法,更會(huì)想到語(yǔ)法背后的實(shí)現(xiàn)。 這種感覺(jué)很透徹,就像搞懂了操作系統(tǒng)、體系結(jié)構(gòu)你會(huì)明白一個(gè)程序從雙擊鼠標(biāo)開(kāi)始,到底是如何被運(yùn)行起來(lái)的,這種掌握一切細(xì)節(jié),透徹的感覺(jué),真的很奇妙,不信你去試試。 說(shuō)人話! 那學(xué)了編譯原理你能干啥? 當(dāng)你學(xué)完有限狀態(tài)機(jī)以后,你會(huì)發(fā)現(xiàn)以前覺(jué)得很牛逼正則表達(dá)式似乎自己也能用 DFA、NFA 實(shí)現(xiàn)一下了。狀態(tài)機(jī)的思想在編程中很多地方都用得上。 比如解析 HTTP 協(xié)議,如果沒(méi)學(xué)過(guò)狀態(tài)機(jī)思想,你可能會(huì)一行行的 if/else 去做解析,這里最麻煩的地方在于,if/else 需要提前將 HTTP 頭部字段都接收到再來(lái)判斷,而我們知道 HTTP 基于 TCP,而 TCP 是流式傳輸,所以你很有可能是幾個(gè)字符一組組接收到的,這個(gè)時(shí)候用 if/else 寫(xiě)出來(lái)就很難看了。 而用狀態(tài)機(jī)編寫(xiě)起來(lái)代碼就會(huì)非常優(yōu)雅。狀態(tài)的轉(zhuǎn)移是由規(guī)則驅(qū)動(dòng)的,接收到一個(gè)字符就判斷一個(gè),非常的方便。 繼續(xù)學(xué)完語(yǔ)法分析,你會(huì)掌握遞歸下降分析這樣非常重要的思想,你可以使用遞歸下降快速的實(shí)現(xiàn)四則運(yùn)算計(jì)算器。 如果不用遞歸下降你可能需要先中綴表達(dá)式轉(zhuǎn)后綴,然后求值,這是我們大一數(shù)據(jù)結(jié)構(gòu)課寫(xiě)的,當(dāng)時(shí)用棧寫(xiě)的,有點(diǎn)麻煩。后來(lái)學(xué)完編譯原理,又用遞歸下降重寫(xiě)了一遍,區(qū)區(qū)幾十行代碼遍搞定。 還有一類(lèi)場(chǎng)景在實(shí)際開(kāi)發(fā)中的用的很多,比如淘寶、京東這樣的電商,它們的營(yíng)銷(xiāo)規(guī)則有很多,比如滿減、直減、跨店等等,這樣的規(guī)則是不可能寫(xiě)死在代碼里的。 那是怎么做的呢? 一般會(huì)實(shí)現(xiàn)一個(gè)配置系統(tǒng),并設(shè)計(jì)一個(gè)DSL(領(lǐng)域特定語(yǔ)言)來(lái)表達(dá)這些規(guī)則,將規(guī)則直接配置到系統(tǒng)中,這樣可以非常方便的修改,那么如何在代碼里去解析 DSL 定義的規(guī)則呢?這就需要為 DSL 寫(xiě)一個(gè)語(yǔ)法解析器,這里就會(huì)用到語(yǔ)法分析的方法。 DSL(Domain Specific Language),是一種用于某個(gè)特定領(lǐng)域的程序設(shè)計(jì)語(yǔ)言。這種特定于某個(gè)領(lǐng)域是相對(duì)于 C、C++、Python 這種通用語(yǔ)言而言的,通用語(yǔ)言可以在各個(gè)領(lǐng)域使用,我們熟悉的大多數(shù)程序設(shè)計(jì)語(yǔ)言都是通用語(yǔ)言,它們都是圖靈完備的。 像我們平常經(jīng)常使用的 JSON、SQL、HTML 這些都算是一種 DSL,你甚至可以嘗試用遞歸下降去寫(xiě)一個(gè) JSON、XML 解析器,這比寫(xiě)電商網(wǎng)站更有價(jià)值的。 繼續(xù)往下學(xué)你會(huì)了解到抽象語(yǔ)法樹(shù) AST 如何生成、如何轉(zhuǎn)化為中間代碼、如何對(duì)中間代碼優(yōu)化、最終又是怎么生成機(jī)器指令的。 你會(huì)看到貪心算法在寄存器分配中的應(yīng)用,也會(huì)看到圖論中的可達(dá)性分析又是如何實(shí)現(xiàn)死代碼消除。 IDE上面那個(gè)綠色的編譯按鈕對(duì)你不再是黑魔法。 為啥點(diǎn)一下就能生成可執(zhí)行的程序? 你寫(xiě)的英文字母又是如何變成一個(gè)個(gè)二進(jìn)制指令的? 學(xué)完編譯原理,這些通通不是問(wèn)題,媽媽再也不用擔(dān)心你的學(xué)習(xí)~ 當(dāng)然完成一個(gè)像 GCC、Clang 這樣的編譯器難度太高太高,我們學(xué)習(xí)編譯原理的目的也不是去造這樣的輪子,而是為了更好的理解和運(yùn)用編程語(yǔ)言。
1.5 體系結(jié)構(gòu)&組成原理
上面說(shuō)的都是軟件層面,體系結(jié)構(gòu)則是關(guān)于計(jì)算機(jī)是如何工作的,你會(huì)了解到典型的存儲(chǔ)程序計(jì)算機(jī)是怎樣運(yùn)轉(zhuǎn)的。 記得南大有個(gè)老師說(shuō)過(guò) “我們不是學(xué)習(xí)使用計(jì)算機(jī)的,而是學(xué)習(xí)如何造計(jì)算機(jī)”,雖然造計(jì)算機(jī)有點(diǎn)夸張,但是至少我們得了解下計(jì)算機(jī)的實(shí)現(xiàn)原理,了解下代碼是怎么被 CPU 執(zhí)行的吧?不然其實(shí)你會(huì)很困惑,明明一堆英文字母,怎么在 CPU 這種電路上跑起來(lái)的,我大一學(xué) C 語(yǔ)言就百思不得其解,直到后來(lái)學(xué)了組成原理和數(shù)字邏輯。 我們說(shuō)計(jì)算機(jī)中一切都是 0、1,0、1 又是通過(guò)高低電平來(lái)表達(dá)的,通過(guò)與、或、非等邏輯門(mén)電路來(lái)表達(dá)二進(jìn)制的數(shù)值運(yùn)算,再將這些簡(jiǎn)單的電路集成在一起,就形成了 ALU 等具有運(yùn)算能力的處理器。 你會(huì)看到一條指令是如何被CPU執(zhí)行的,CPU 從內(nèi)存或 Cache 中取出指令,放入指令寄存器,并對(duì)指令譯碼。譯碼就是按照指令的編碼規(guī)則,將指令拆分成一系列的微操作和操作數(shù)。然后發(fā)出各種設(shè)備控制指令,執(zhí)行微操作。這樣就完成一條指令的執(zhí)行。 我們說(shuō)學(xué)完編譯原理,能夠明白寫(xiě)的英文代碼是如何被變成二進(jìn)制指令的,學(xué)完操作系統(tǒng)能搞懂二進(jìn)制程序是如何被鏈接在一起,又是如何被操作系統(tǒng)加載、執(zhí)行的。而組成原理則會(huì)告訴你二進(jìn)制指令是如何控制 CPU 跑起來(lái)的,我們的操作系統(tǒng)本質(zhì)上也是一個(gè)二進(jìn)制的程序。 當(dāng)你理解了計(jì)算機(jī)存儲(chǔ)層次結(jié)構(gòu),理解了多級(jí) Cache,你就會(huì)通過(guò)優(yōu)化數(shù)據(jù)訪問(wèn)方式來(lái)編寫(xiě)出速度更快的程序。 你會(huì)學(xué)到底層體系結(jié)構(gòu)對(duì) C 這些語(yǔ)言的棧幀和參數(shù)傳遞的支持,參數(shù)是如何被傳遞給另外一個(gè)函數(shù)的?函數(shù)的返回值又是如何拿到。 這是學(xué)習(xí)組成原理對(duì)于寫(xiě)代碼的意義。 學(xué)這些到底有什么意義? 你會(huì)完整的看到寫(xiě)的代碼如何變成二進(jìn)制指令,又是如何去控制各種門(mén)電路,最后變成屏幕上花花綠綠的程序的(當(dāng)然這里可能還需要學(xué)習(xí)顯示器的原理),這就是我們常說(shuō)的“基礎(chǔ)”和“原理”。 并且計(jì)算機(jī)體系結(jié)構(gòu)中的很多思想,是能夠廣泛運(yùn)用于現(xiàn)代軟件開(kāi)發(fā)的,比如 CPU 的多級(jí) Cache 思想,就是我們現(xiàn)在服務(wù)器開(kāi)發(fā)中提高并發(fā)度常用的緩存技術(shù),包括緩存的替換策略等等。 當(dāng)計(jì)算機(jī)對(duì)你不再是黑盒,你了解寫(xiě)下的代碼到執(zhí)行的每一步,而這也將成為你以后的核心競(jìng)爭(zhēng)力,作為科班畢業(yè)生不應(yīng)該只會(huì)使用 Java、Redis、Mysql、Spring 來(lái)寫(xiě)各種網(wǎng)站。 如果讀者里有半路轉(zhuǎn)行或者從培訓(xùn)班出來(lái)的,也希望你們能夠抽出空余時(shí)間去補(bǔ)補(bǔ)這些基礎(chǔ)課,這會(huì)讓你在編程這條路上走的更遠(yuǎn)和更穩(wěn)。
1.6 數(shù)據(jù)結(jié)構(gòu)與算法
為什么把算法放到最后來(lái)講,是不重要嗎?相反,它太重要了,所以才讓它來(lái)壓軸。 如果要問(wèn)我大學(xué)什么最后悔?那肯定是沒(méi)有從大一就開(kāi)始好好學(xué)算法,去打 ACM。 現(xiàn)在還在大一、大二的同學(xué)還不抓緊機(jī)會(huì),別等到以后來(lái)后悔。當(dāng)然,不打 ACM,我們也是能夠?qū)W好數(shù)據(jù)結(jié)構(gòu)和算法的。 數(shù)據(jù)結(jié)構(gòu)和算法你能在任何計(jì)算機(jī)領(lǐng)域里看到,比如在編譯原理中寄存器的分配會(huì)用到貪心,死代碼檢測(cè)與消除會(huì)用到圖論里不可達(dá)的知識(shí);操作系統(tǒng)進(jìn)程、線程調(diào)度會(huì)用到多級(jí)隊(duì)列和調(diào)度算法;組成原理中 Cache 的替換會(huì)用到 LRU、FIFO 等算法;開(kāi)發(fā)必備的數(shù)據(jù)庫(kù)也離不開(kāi) B+ 樹(shù)、LSM 等數(shù)據(jù)結(jié)構(gòu)和查找算法。 很多時(shí)候我們需要的算法都被封裝到編程語(yǔ)言的基礎(chǔ)庫(kù)里了,以至于很多同學(xué)會(huì)覺(jué)得算法離我們太遠(yuǎn),其實(shí)不是的。 如果不學(xué)習(xí)算法,連什么時(shí)候用 Map(紅黑樹(shù)實(shí)現(xiàn))、什么時(shí)候用 HashMap 都分不清。 所以學(xué)習(xí)算法有助于我們根據(jù)應(yīng)用場(chǎng)景選擇最合適的數(shù)據(jù)結(jié)構(gòu)。 日常開(kāi)發(fā)中也一定離不開(kāi)算法,比如小北最近工作中涉及的某種嵌套 TLV(Tag-Length-Value)結(jié)構(gòu)編碼的解析,就需要用到遞歸、多叉樹(shù)等知識(shí)。如果不學(xué)習(xí)算法,那么程序中只能見(jiàn)到大量的 if/else、while/for。。??梢哉f(shuō)不會(huì)算法的工程師一定不是一個(gè)優(yōu)秀的工程師。
1.7 為什么我不說(shuō)計(jì)網(wǎng)、數(shù)據(jù)庫(kù)等
很多人喜歡把計(jì)算機(jī)網(wǎng)絡(luò)、數(shù)據(jù)庫(kù)原理這些也歸為計(jì)算機(jī)基礎(chǔ)來(lái),我當(dāng)然也認(rèn)同,因?yàn)橐粋€(gè)知識(shí)結(jié)構(gòu)完整的計(jì)算機(jī)科班學(xué)生,應(yīng)該了解這些知識(shí)。 但是我個(gè)人是覺(jué)得計(jì)算機(jī)網(wǎng)絡(luò)、數(shù)據(jù)庫(kù)無(wú)非就是建立在操作系統(tǒng)、編譯原理、組成原理之上的應(yīng)用層軟件。 什么是數(shù)據(jù)庫(kù)?沒(méi)有數(shù)據(jù)庫(kù)之前你會(huì)用文件去存儲(chǔ)數(shù)據(jù),但是不方便查找、修改等,數(shù)據(jù)庫(kù)只是提高了這個(gè)過(guò)程的效率。 網(wǎng)絡(luò)干什么的?網(wǎng)絡(luò)就是讓不在同一臺(tái)電腦上的程序互相通信,本質(zhì)上就是進(jìn)程間通信的手段。 如果你只是開(kāi)發(fā)單機(jī)工業(yè)軟件,甚至真的可以不學(xué)網(wǎng)絡(luò),只是由于現(xiàn)在大多數(shù)程序員都是在互聯(lián)網(wǎng)公司工作,所以不管前后端,都離不開(kāi)和HTTP等網(wǎng)絡(luò)協(xié)議打交道。再次重申:不是計(jì)網(wǎng)、數(shù)據(jù)庫(kù)不重要,只是我認(rèn)為它們屬于構(gòu)建在操作系統(tǒng)之上的軟件,不劃在基礎(chǔ)之列。
二、領(lǐng)域知識(shí)
這個(gè)我不敢說(shuō)太多,因?yàn)楦鱾€(gè)領(lǐng)域我也不太懂。只簡(jiǎn)單提一點(diǎn),拋磚引玉罷了。 如果你想去騰訊、網(wǎng)易做游戲引擎開(kāi)發(fā),那么圖形學(xué)一定是你繞不開(kāi)的知識(shí),此外你還得學(xué)習(xí)渲染管線、著色器、物理、光照等等。 如果你想去 PingCap 這樣的公司做分布式存儲(chǔ),那么分布式理論知識(shí)一定是你繞不開(kāi)的關(guān)口,包括 CAP 定理、Paxos 算法、Raft 算法、ZAB 協(xié)議等等。 如果你想寫(xiě)一個(gè)數(shù)據(jù)庫(kù),那么你需要去了解磁盤(pán)、索引實(shí)現(xiàn)、SQL 解析(編譯原理)、事務(wù)、如何用 MVCC 解決讀寫(xiě)沖突等等一大堆的東西,還得了解一大堆編程語(yǔ)言層面的東西,比如鎖、信號(hào)量、并發(fā)編程技巧,不得不說(shuō)造數(shù)據(jù)庫(kù)是一個(gè)臟活也是一個(gè)累活。 更進(jìn)一步你想去做分布式數(shù)據(jù)庫(kù),那可能還得去學(xué)習(xí)數(shù)據(jù)分片的知識(shí),查詢?nèi)蝿?wù)如何做,是集中做,還是將邏輯下推給各個(gè)節(jié)點(diǎn),如何實(shí)現(xiàn)分布式事務(wù)等等。 你說(shuō)你只想去大廠 CRUD?沒(méi)毛病,老鐵! 那你得熟悉一門(mén)編譯型語(yǔ)言(C/C++、Java、Go),理解語(yǔ)言部分底層原理,比如 C++ 你得看看 STL、看看對(duì)象模型吧,你不懂什么虛函數(shù)表、智能指針還想去騰訊寫(xiě) C++? Java 的你得背背 JVM,什么垃圾回收算法吧,你不看看ConcurrentHashMap 好意思說(shuō)你是做Java的? 咱CRUD的對(duì)象是數(shù)據(jù)庫(kù)吧?那不得學(xué)學(xué)怎么才能把數(shù)據(jù)庫(kù)用好。用戶通過(guò) HTTP 訪問(wèn)我們得服務(wù),總得了解 HTTP吧?順帶著不看下 TCP 三次握手、四次揮手你好意思說(shuō)是學(xué)計(jì)算機(jī)的? 用戶把錢(qián)、信息放咱們這,總得保證用戶數(shù)據(jù)安全吧?那 XSS、SQL 注入、CSRF 這些常見(jiàn)的 Web 攻擊手段你總得了解吧?HTTPS、RSA、簽名、數(shù)字證書(shū)這些安全手段總得知道吧。 雙十一流量太大,老板還讓你必須頂住,那你總得了解下緩存、異步、消息隊(duì)列、NoSQL 這些千萬(wàn) QPS 必備的大殺器吧? 看看!要想做好CRUD也不是那么容易滴。(上面這段只是換一種方式把做后端的同學(xué)要學(xué)的知識(shí)寫(xiě)出來(lái),不是吐槽更不是調(diào)侃,純屬娛樂(lè)。
技能
這就很多了,包括 VSCode、Jetbrains 全家桶這些 IDE,文檔編寫(xiě) Markdown、Git 等版本管理工具。SSH 遠(yuǎn)程登錄、端口轉(zhuǎn)發(fā),Ngrok 內(nèi)網(wǎng)穿透等等這些提高你開(kāi)發(fā)效率的工具,都算是技能,這個(gè)沒(méi)啥好說(shuō)的,平時(shí)用到多學(xué)習(xí)多積累就好了。 我只提一點(diǎn),盡早使用 Linux、類(lèi) Unix(Mac)作為主力開(kāi)發(fā)電腦。我大二的時(shí)候,就是看了王 ying 的那篇《完全用 Linux 工作》,直接買(mǎi)了個(gè) SSD 套上 U 盤(pán)外殼,做了一個(gè)啟動(dòng)盤(pán),后來(lái)用了將近一年的 Ubuntu,只有在選課、提交作業(yè)等需要用的 IE 瀏覽器的時(shí)候才會(huì)打開(kāi) Windows(這里不得不吐槽學(xué)校老古董網(wǎng)站!) 當(dāng)然了,我也不是狂熱的 Linux 愛(ài)好者,只是單純覺(jué)得做開(kāi)發(fā)的話,離不開(kāi)各種環(huán)境安裝、命令行的使用,這點(diǎn)上面類(lèi) Unix 系統(tǒng)帶有天然的優(yōu)勢(shì),誰(shuí)用誰(shuí)知道!
總結(jié)
寫(xiě)完才發(fā)現(xiàn),這篇文章連篇幅都是「基礎(chǔ) : 領(lǐng)域知識(shí) : 技能」 接近 7 : 2 : 1。 這也是我推薦你在大學(xué)期間分配學(xué)習(xí)時(shí)間的比例,至少學(xué)習(xí)基礎(chǔ)知識(shí)的時(shí)間不少于 50%,當(dāng)然,這些東西你都學(xué)完了那可以去找找感興趣的方向?qū)Q幸幌隆?千萬(wàn)不要大一、大二一上來(lái)就扎進(jìn) Java Web、Python 爬蟲(chóng)這種東西,這些可以學(xué),但不是重點(diǎn)。 這篇文章由于篇幅限制,沒(méi)有寫(xiě)到具體該如何去學(xué),有哪些好的資料,我準(zhǔn)備把這個(gè)單獨(dú)再寫(xiě)一個(gè) 《How 篇》,持續(xù)關(guān)注我喲~ 那么如何檢驗(yàn)學(xué)得如何呢? 想必你一定聽(tīng)說(shuō)這個(gè)計(jì)網(wǎng)面試題:“從 URL 輸入到頁(yè)面展現(xiàn)到底發(fā)生什么?“ 這個(gè)問(wèn)題換個(gè)表達(dá)就是「一個(gè)數(shù)據(jù)包是如何發(fā)送到另外一臺(tái)電腦的」。 如果你能完整的說(shuō)出整個(gè)過(guò)程,那么計(jì)網(wǎng)你一定是學(xué)懂了!這就是為啥面試這么喜歡問(wèn)這個(gè)問(wèn)題的原因。 那么我們依葫蘆畫(huà)瓢提一個(gè)問(wèn)題 “從代碼被寫(xiě)下到程序運(yùn)行起來(lái)到底發(fā)生了什么?” 這個(gè)問(wèn)題回答得越詳細(xì)越好,基本上能說(shuō)清楚了,你就理解了編譯原理、操作系統(tǒng)、組成原理這三座大三。 這個(gè)問(wèn)題也放在這,后續(xù)發(fā)文總結(jié),請(qǐng)持續(xù)關(guān)注編程指北哦。 唉,當(dāng)年要是有這么個(gè)貼心學(xué)長(zhǎng)告訴我這些,也不至于在 Andorid 開(kāi)發(fā)、Java Web、Python 爬蟲(chóng)這些玩大半年啊。。。 不過(guò)還好后來(lái)自己意識(shí)到了基礎(chǔ)的重要性,開(kāi)始學(xué)匯編、重學(xué) C、搞 mini os、看 Linux 內(nèi)核實(shí)現(xiàn)原理,最后成功的把頭發(fā)掉了一把。。。 責(zé)任編輯:lq
-
操作系統(tǒng)
+關(guān)注
關(guān)注
37文章
6859瀏覽量
123501 -
C語(yǔ)言
+關(guān)注
關(guān)注
180文章
7613瀏覽量
137247 -
數(shù)據(jù)結(jié)構(gòu)
+關(guān)注
關(guān)注
3文章
573瀏覽量
40163
原文標(biāo)題:怎樣才算一個(gè)計(jì)算機(jī)知識(shí)體系完整的畢業(yè)生-- What篇
文章出處:【微信號(hào):TheAlgorithm,微信公眾號(hào):算法與數(shù)據(jù)結(jié)構(gòu)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論