一樣大學四年,爲何有些同窗畢業就能成爲大廠Offer收割機!

最近有很多學弟學妹問:大學學 Java 和 C++ 哪一個好找工做,學前端好仍是後端好,該學 Vue 仍是 React。。。前端

彷彿看到了本身當年的模樣,單純以一個計算機應屆畢業生的身份聊聊,我認爲大學四年,計算機科班學生應該學些什麼,哪些纔是重點。程序員

一樣大學四年,爲何有些同窗畢業就能成爲大廠 Offer 收割機,各類 SP、SSP 拿到手軟,有的同窗明明在學校寫了好多網站,項目經歷滿滿,經歷春秋招,卻找到一份工做都很難。正則表達式

不能說後者沒認真學習,或許是用力的方向不對。算法

 

1、開始吧

人類的知識邊界一直在不斷的擴張,俗話說學無止境,這放在計算機領域也一樣適用,計算機自己是一我的造科學,不屬於天然科學。sql

每一年,甚至每月都不斷有新的編程框架推出,學到頭禿你也學不完,也沒有必要去挨個學。數據庫

而且你會發現,不少一二線大廠內部用的東西基本都是本身搞一套的,好比服務發現、RPC、KV、DB、消息隊列、日誌、監控等等。編程

因此通常這些大廠招聘的時候基本不會因沒學過某種框架而掛你,反正不少東西都是要進來從新學的。windows

他們會更加關注你的基礎知識、解決問題的經驗以及聰明度這種更加通用的能力上。後端

反而是一些小公司,可能會要求你必須會 Spring、Vue、Redis... 這些框架或者組件。瀏覽器


 

上面分別是騰訊、阿里、某外包公司的招聘 JD,顯然,騰訊阿里看中的是紮實的編程基本功和快速學習能力,這意味着有培養潛力。

而外包公司就要求你會 xx 數據庫、Spring 之類。不去評價哪一個好,可是若是你想去 BAT,那麼是否是至少對照着它們的 JD 來提升本身的能力,不失爲一種捷徑。

在這裏,我粗淺的把計算機編程領域的知識分爲三個部分:

● 基礎知識

● 特定領域知識

● 框架和開發技能

基礎知識是指無論從事任何方向的軟件工程師都應該掌握的,好比數據結構、算法、操做系統。

特定領域知識就是你從事某個細分方向時須要掌握的知識,好比作遊戲引擎的須要掌握圖形學;作前端的須要掌握瀏覽器渲染原理、前端三大件;算法工程師須要更多的數學知識。

畢竟計算機各類門類挺多的,須要選個細分方向專研下去,什麼都學只會什麼都不精(大佬除外啦。

 


 

★ 必備基礎知識

如今大環境比較浮躁,不多有人願意花心思在基礎上,喜歡直接學 Python 搞機器學習、寫秒殺、作商城。

找工做的時候都是想看面經、總結速成。

可是做爲優秀的計算機系學生的你怎麼能流於各類編程框架(造框架除外)?

把時間花在算法、基礎學科上他不香嗎?功利一點講,回報反而會更大。

何況在計算機領域,不少基礎的理論並不十分高深,咱們努努力就能夠掌握其中的核心知識。

 


 

1.數學

首先說明,這裏把數學也列出來不是爲了顯得高端,而是本身吃過數學的虧。

若是你是自學轉行當程序員,我固然不會推薦數學。

可是這篇文章主要面向的是還在大學的科班學生,這部分同窗之後也許會去作算法(CV、NLP之類)、遊戲引擎、信息安全編碼等

這些方向對數學要求就會偏高,在計算機領域線代、機率論、統計學這些數學分支相對比較重要,計算機本質上仍是離散的。

好比在機器學習或數據挖掘中經常用線性代數來下降數據維度,不少問題最終都能化爲求解線性方程組。

因此爲了不之後想走這些方向卻被數學卡住,在大1、大二上數學課的時候就好好的學一下。

書到用時方恨少,不要如今覺得沒用處就很差好學,等你須要的時候,就知道後悔了。(默默流下了不學無術的眼淚┭┮﹏┭┮

什麼?你說之後肯定走開發方向?

那的確能夠把數學優先級放後面一點,用得確實很少,不過上數學課的時候總該認真聽下吧,拿個高績點也是百利無一害嘛。說不許哪天你又想加入算法內卷大軍呢?

 


 

2.C語言

你也許會很疑惑,這裏明明說基礎知識,爲何要把一門編程語言單獨列出來呢?

由於在我看來,沒有比C語言更適合用來理解計算機系統了。

咱們後面將會提到的操做系統、體系結構 這些東西很是適合用 C 語言去理解或者去實踐。

而且 C 語言自己的語言特性很是少,可是想學好又是不容易,不少人都以爲C語言難,難在哪裏呢?回想了一下我大一時的感覺:

✿ 簡陋的標準庫,幾乎沒有可用的數據結構;

✿ 指針很難理解和使用;

✿ 須要瞭解彙編、連接、裝載、內存等才能把 C 語言用好。

不巧的是,這些東西正是計算機系統知識的一部分,因此用 C 語言做爲學習計算機系統知識是最有效率的方式。

真的很難想象用 Java 或是 Python 去給別人講解內存,由於這些語言抽象程度都比 C 語言高,意味着離計算機系統也就越遠。

在 TIOBE 編程語言排行榜上,C語言幾乎永遠佔據前三位,其地位天然毋庸置疑。


 

並且幾乎你開發中用到的不少東西都是用C語言編寫的,Linux、Nginx、Redis、MySQL、Git......或許你會想要探究下原理,閱讀點這些開源軟件的源碼,那麼 C 語言也是你必備的瑞士軍刀。

深刻學習 C 語言,可以瞭解計算機底層的執行原理,是理解程序運行機制的絕佳語言,無出其右。

在這裏,不得不引用對C語言最經典的總結:

任何比C語言更低級的語言,都不足以完整地抽象一個計算機系統; 任何比C高級的語言,均可以用C來實現。

這真是極高而中肯的評價!

因此對於計算機科班來講,無論你是作前端仍是後端,算法仍是開發,C 語言都建議你好好學習。這是無關方向的一門語言,就是基礎!

 


 

3.操做系統

咱們編程的 IDE、寫出來的程序所有都須要運行在操做系統上,說操做系統是計算機軟件的基石也不爲過。

程序運行起來就須要建立進程,這涉及到操做系統的進程管理;寫程序須要定義變量、存儲數據吧,這又涉及到內存,對應內存管理;有時候咱們還須要讀寫文件,這又離不開和文件系統打交道;你須要學習使用鎖、條件變量、臨界區來控制程序併發執行時不會錯亂。

而讀寫文件、分配內存這些又離不開系統調用(System call)。

而且真正作起工程就會發現,不少問題是和操做系統緊密相關的,不理解操做系統,你連問題的緣由都分析不出來。

好比前段時間咱們出現的在基於協程(libco)的框架下,使用多線程的鎖去作同步互斥偶發死鎖,後來分析才發現緣由:

協程是應用層實現的,一個線程內多個協程對於操做系統是感知不到的:


那麼當一個協稱 A 上鎖後發起網絡 IO 請求,這個時候會被切換到另一個協程B,而協程 B 又去請求這個鎖。

那麼這個時候操做系統會認爲這個鎖已經被上了,會將協程 B 對應的線程掛起到等待隊列,這樣的話就致使協稱 A 永遠沒法運行,也就沒法釋放鎖,致使死鎖。

解決的方法也很簡單,就是將鎖設置爲可重入鎖,可重入意味着同一個線程屢次去請求同一個鎖不會致使掛起。這樣當協程 B 再去請求鎖的時候,操做系統就會認爲協程 B 所在的線程已經持有這個鎖了,直接返回,繼續執行。

總之,咱們寫程序每時每刻都在和操做系統交互,沒有理由不學好。

 


 

4.編譯原理

編譯原理多是咱們平時接觸得最少的了,你們也許會以爲本身又不用去造新的編程語言,學編譯原理幹啥。

學好編譯原理有啥用?

你會站在更高的角度去審視這些編程語言,看到的再也不是表面的語法,更會想到語法背後的實現。

這種感受很透徹,就像搞懂了操做系統、體系結構你會明白一個程序從雙擊鼠標開始,究竟是如何被運行起來的,這種掌握一切細節,透徹的感受,真的很奇妙,不信你去試試。

說人話!

那學了編譯原理你能幹啥?

當你學完有限狀態機之後,你會發現之前以爲很牛的正則表達式彷佛本身也能用 DFA、NFA 實現一下了。狀態機的思想在編程中不少地方都用得上。

好比解析 HTTP 協議,若是沒學過狀態機思想,你可能會一行行的 if/else 去作解析,這裏最麻煩的地方在於,if/else 須要提早將 HTTP 頭部字段都接收到再來判斷,而咱們知道 HTTP 基於 TCP,而 TCP 是流式傳輸,因此你頗有多是幾個字符一組組接收到的,這個時候用 if/else 寫出來就很難看了。

而用狀態機編寫起來代碼就會很是優雅。狀態的轉移是由規則驅動的,接收到一個字符就判斷一個,很是的方便。

繼續學完語法分析,你會掌握遞歸降低分析這樣很是重要的思想,你可使用遞歸降低快速的實現四則運算計算器。

若是不用遞歸降低你可能須要先中綴表達式轉後綴,而後求值,這是咱們大一數據結構課寫的,當時用棧寫的,有點麻煩。後來學完編譯原理,又用遞歸降低重寫了一遍,區區幾十行代碼遍搞定。

還有一類場景在實際開發中的用的不少,好比淘寶、京東這樣的電商,它們的營銷規則有不少,好比滿減、直減、跨店等等,這樣的規則是不可能寫死在代碼裏的。

那是怎麼作的呢?

通常會實現一個配置系統,並設計一個DSL(領域特定語言)來表達這些規則,將規則直接配置到系統中,這樣能夠很是方便的修改,那麼如何在代碼裏去解析 DSL 定義的規則呢?這就須要爲 DSL 寫一個語法解析器,這裏就會用到語法分析的方法。

DSL(Domain Specific Language),它是一種用於某個特定領域的程序設計語言。這種特定於某個領域是相對於 C、C++、Python 這種通用語言而言的,通用語言能夠在各個領域使用,咱們熟悉的大多數程序設計語言都是通用語言,它們都是圖靈完備的。

像咱們日常常用的 JSON、SQL、HTML 這些都算是一種 DSL,你甚至能夠嘗試用遞歸降低去寫一個 JSON、XML 解析器,這比寫電商網站更有價值的。

繼續往下學你會了解到抽象語法樹 AST 如何生成、如何轉化爲中間代碼、如何對中間代碼優化、最終又是怎麼生成機器指令的。

你會看到貪心算法在寄存器分配中的應用,也會看到圖論中的可達性分析又是如何實現死代碼消除。

IDE上面那個綠色的編譯按鈕對你再也不是黑魔法。

爲啥點一下就能生成可執行的程序?

你寫的英文字母又是如何變成一個個二進制指令的?

學完編譯原理,這些統統不是問題~

固然完成一個像 Gcc、Clang 這樣的編譯器難度過高過高,咱們學習編譯原理的目的也不是去造這樣的輪子,而是爲了更好的理解和運用編程語言。

 


 

5.體系結構&組成原理

上面說的都是軟件層面,體系結構則是關於計算機是如何工做的,你會了解到典型的存儲程序計算機是怎樣運轉的。

「咱們不是學習使用計算機的,而是學習如何造計算機」,造計算機有點誇張,可是至少咱們得了解計算機的實現原理,瞭解計算機的各個部分是如何協調工做的。

咱們說計算機中一切都是0、1,0、1又是經過高低電平來表達的,經過與、或、非等邏輯門電路來表達二進制的數值運算,再將這些簡單的電路集成在一塊兒,就造成了ALU等具備運算能力的處理器。

你會了解到一條指令是如何被 CPU 執行的,CPU 從內存或 Cache 中取出指令,放入指令寄存器,並對指令譯碼。譯碼就是按照指令的編碼規則,將指令拆分紅一系列的微操做和操做數。而後發出各類設備控制指令,執行微操做。這樣就完成一條指令的執行。

咱們說學完編譯原理,你可以明白咱們寫的英文代碼是如何被變成二進制指令的,學完操做系統你能搞懂,二進制程序是如何被連接在一塊兒,又是如何被操做系統加載、執行的。而組成原理則會告訴你二進制指令是如何控制電腦的,咱們的操做系統本質上也是一個二進制的程序。

你理解了計算機存儲層次結構,理解了多級 Cache,你就會經過優化數據訪問方式來編寫出速度更快的程序。

你會學到底層體系結構對 C 等語言的棧幀和參數傳遞的支持,參數是如何被傳遞給另一個函數的?函數的返回值又是如何拿到。

這是學習組成原理對於寫代碼的意義。

爲何說這些是基礎?

由於你會完整的看到寫的代碼如何變成二進制指令,又是如何去控制各類門電路,最後變成屏幕上花花綠綠的程序的(固然這裏可能還須要學習顯示器的原理),這就是咱們常說的「基礎」和「原理」。

計算機對你再也不是黑盒,這將成爲你之後的核心競爭力,不然做爲科班畢業生若是隻會使用 Redis、Mysql、Spring 來寫各類網站,那麼大學四年的學習如何體現呢?

若是讀者裏有半路轉行或者從培訓班出來的,我也但願大家可以抽出空餘時間去補補這些基礎課,這會讓你在編程這條路上走的更遠和更穩。

 


 

6.數據結構與算法

爲何把算法放到最後來說,是不重要嗎?相反,它過重要了,因此才讓它來壓軸。

若是要問我大學什麼最後悔?那確定是沒有從大一就開始好好學算法,去打 ACM。

如今還在大1、大二的同窗還不抓緊機會,別給本身留下遺憾。固然,不打 ACM,咱們也是可以學好數據結構和算法的。

數據結構和算法你能在任何計算機領域裏看到,好比在編譯原理中寄存器的分配會用到貪心,死代碼檢測與消除會用到圖論裏不可達的知識;操做系統進程、線程調度會用到多級隊列和調度算法;組成原理中 Cache 的替換會用到 LRU、FIFO 等算法;開發必備的數據庫也離不開B+樹、LSM 等數據結構和查找算法。

不少時候咱們須要的算法都被封裝到編程語言的基礎庫裏了,以致於不少同窗會以爲算法離咱們太遠,其實不是的。

若是不學習算法,連何時用 Map(紅黑樹實現)、何時用 HashMap 都分不清。

因此學習算法有助於咱們根據應用場景選擇最合適的數據結構。

平常開發中也必定離不開算法,好比小北最近工做中涉及的某種嵌套 TLV(Tag-Length-Value)結構編碼的解析,就須要用到遞歸、多叉樹等知識。若是不學習算法,那麼程序中只能見到大量的 if/else、while/for。。。

能夠說不學算法的工程師必定不是一個優秀的工程師。

 


 

7.爲何我不說計網、數據庫等

不少人喜歡把計算機網絡、數據庫原理這些也歸爲計算機基礎來,我固然也認同,由於一個知識結構完整的計算機科班學生,應該瞭解這些知識。

可是我我的是以爲計算機網絡、數據庫是創建在操做系統、編譯原理、組成原理之上的應用層軟件。

什麼是數據庫?沒有數據庫以前你會用文件去存儲數據,可是不方便查找、修改等,數據庫只是提升了這個過程的效率。

網絡幹什麼的?網絡就是讓不在同一臺電腦上的程序互相通訊,本質上就是進程間通訊的手段。

若是你只是開發單機工業軟件,甚至真的能夠不學網絡,只是因爲如今大多數程序員都是在互聯網公司工做,因此無論先後端,都離不開和HTTP等網絡協議打交道。

再次重申:不是計網、數據庫不重要,只是我認爲它們屬於構建在操做系統之上的軟件,不劃在基礎之列。

 


 

2、領域知識

這個我不敢說太多,由於各個領域我也不太懂。只簡單提一點,拋磚引玉罷了。

若是你想去騰訊、網易作遊戲引擎開發,那麼圖形學必定是你繞不開的知識,此外你還得學習渲染管線、着色器、物理、光照等等。

若是你想去 PingCap 這樣的公司作分佈式存儲,那麼分佈式理論知識必定是你繞不開的關口,包括 CAP 定理、Paxos 算法、Raft 算法、ZAB 協議等等。

若是你想寫一個數據庫,那麼你須要去了解磁盤、索引實現、SQL 解析(編譯原理)、事務、如何用 MVCC 解決讀寫衝突等等一大堆的東西,還得了解一大堆編程語言層面的東西,好比鎖、信號量、併發編程技巧,不得不說造數據庫是一個髒活也是一個累活。

更進一步你想去作分佈式數據庫,那可能還得去學習數據分片的知識,查詢任務如何作,是集中作,仍是將邏輯下推給各個節點,如何實現分佈式事務等等。

你說你只想去大廠 CRUD?沒毛病,老鐵!

那你得熟悉一門編譯型語言(C/C++、Java、Go),理解語言部分底層原理,好比 C++ 你得看看 STL、看看對象模型吧,你不懂什麼虛函數表、智能指針還想去騰訊寫 C++? Java 的你得背背 JVM,什麼垃圾回收算法吧,你不看看ConcurrentHashMap 好意思說你是作Java的?

咱CRUD的對象是數據庫吧?那不得學學怎麼才能把數據庫用好。用戶經過 HTTP 訪問咱們得服務,總得了解 HTTP吧?順帶着不看下 TCP 三次握手、四次揮手你好意思說是學計算機的?

用戶把錢、信息放我們這,總得保證用戶數據安全吧?那 XSS、SQL 注入、CSRF 這些常見的 Web 攻擊手段你總得了解吧?HTTPS、RSA、簽名、數字證書這些安全手段總得知道吧。

雙十一流量太大,老闆還讓你必須頂住,那你總得了解下緩存、異步、消息隊列、NoSQL 這些千萬 QPS 必備的大殺器吧?

看看!要想作好CRUD也不是那麼容易滴。

(上面這段只是換一種方式把作後端的同窗要學的知識寫出來,不是吐槽更不是調侃,純屬娛樂。)

 


 

3、技能

這就不少了,包括 VS、Jetbrains 全家桶這些 IDE,文檔編寫 Markdown、Git 等版本管理工具。

SSH 遠程登陸、端口轉發,Ngrok 內網穿透等等這些提升你開發效率的工具,都算是技能,這個沒啥好說的,平時用到多學習多積累就行了。

我只提一點,儘早使用 Linux、類 Unix(Mac)做爲主力開發電腦。

固然了,我也不是狂熱的 Linux 愛好者,只是單純以爲作開發的話,離不開各類環境安裝、命令行的使用,這點上面類 Unix 系統帶有自然的優點,誰用誰知道!

 

4、總結

寫完才發現,這篇文章連篇幅都是「基礎 : 領域知識 : 技能」 接近 7 : 2 : 1。

這也是我推薦你在大學期間分配學習時間的比例,至少學習基礎知識的時間很多於 50%,固然,這些東西你都學完了那能夠去找找感興趣的方向專研一下。

不要大1、大二一上來就扎進 Java Web、Python 爬蟲這種東西,這些能夠學,但不是重點。

最後我想送給你一句我挺喜歡的話:

萬丈高樓平地起,勿在浮沙築高臺。

無論你是轉行也好,初學也罷,進階也可~

——【值得關注】個人編程學習進階俱樂部 ——

涉及到:C語言、C++、windows編程、網絡編程、QT界面開發、Linux編程、遊戲編程、黑客等等......

相關文章
相關標籤/搜索