3年,從雙非到百度的學習經驗總結
- 2019 年 11 月 10 日
- 筆記
01
近年來,有些讀者會問我一些形形色色的問題,讓我很難去回答,甚至給不出建設性的意見。
舉個例子:
- 我學習什麼能進入優秀的互聯網公司工作?
- 我想做研發我應該學習什麼?
眾所周知,這問題就像你問學霸說你這麼厲害一樣讓人難以回答。我作為一個雙非軟工本科學生,經過大學自己摸索和不斷試錯,畢業開始在百度從事研發工作。其實,我當時也有很多的疑惑,在這裡給大家講講我的踩坑歷程。
記憶中,我當年逛知乎、求助高人、甚至我的導師,都無法給出一個可操作的建議。除此之外,在我那種二本學校,知名企業都不會去咱學校校招,我和學長們對春秋招的概念微乎其微,進大廠是件很困難的事情,概率與踩狗屎不相上下。
作為探路者,求助知乎和論壇,給出的結論幾乎都是好好學習數據結構/演算法、現在大數據很火你應該學學Hadoop/Spark、你要是會微服務、docker、k8s一定會很加分。
讓我想起了我當年問學霸題目如何解?學霸說:這個題目是來源於第X章第X例題,你這樣解,答案就出來了,很容易的。至於為什麼他能想到,鬼也不知道。
當時,我真的是花里胡哨的啥都學,啥都去倒騰,不知道是不是梁靜茹給我的勇氣。前端、後端技術棧、Hadoop/Spark、docker/k8s這些幾乎都實操過,只是很多只是入門並沒有深入研究,效果自然也十分有限。
這些概念,對於小白或者在校生來說,這彷彿在對說你不用學了,除非你天生技術慾望特彆強烈。這對於大多數普通人來說,明顯是勸退的節奏,可操行十分有限,幾乎沒有參考價值,不知道從何下手。
其實,道理是沒有錯的,多研究底層和熱門技術棧是有益的。但是,脫離實際情況談技術就是扯犢子,就像讓中國男足拿世界盃冠軍顯然不符合實際,更應該是根據實際情況,做產出最大的事情,否則會信心全無。
接下來,我系統性拆分問題,在不同階段應該「學什麼」、「如何學」、「學到什麼程度」,重點講我當時遇到的問題,還有我是如何去思考的,最終如何解決的,思路比結論重要。
02
根據問題歸類來看,主要在我自己的角度談談普通本科如何實現進入Top級互聯網工作?
首先,說說在大廠工作都是些什麼樣的人,他們當年都是背著什麼光環混進去的?
經過我的調研和分析,重點說一下在校招中面試官看中和考察的東西。
- 學歷/專業、紮實專業基本功
- 有成果的科研經歷
- 省/國家級軟體設計大賽
- 豐富互聯網公司實習經歷
- 小有名氣的開源項目經歷
大概思路就是,要麼你證明你令人信服的天賦如邏輯系統思維、聰明,讓人覺得你可以被快速培養;要麼你有豐富的工程實戰經驗,證明你具備優秀工程師的潛質。
當然,你可能會說這麼多要求,恐怕神仙也做不到啊,簡單太苛刻了。在這裡,並不是上述要點全部滿足,只是滿足其中兩項證明你的實力即可,畢竟面試時間十分有限必須有點讓人信服的東西啊。
舉個例子:
1、假設你是上海交大、華中科大大學畢業的學生,你可能只需要重點複習數據結構/演算法等專業知識,輔之把學校的科研經歷說一下。可能進入什麼阿里華為百度問題都不是很大,專業知識對於你們來說自己不再話下,畢竟考理論就是你們的特長。
2、假如你是雙非大學畢業的學生,那麼你必須用國家級大賽、開源項目、互聯網公司經歷證明自己。總之,多做項目,專註於技術本身,讓自己更早具備職業軟體工程師的實戰技能。
簡而言之,你沒有光環,那就比別人多努力點,提前做好職業規劃,把時間投入技術本身不要投機取巧。
03
鑒於上述分析,知道需求是什麼?對於我們來說,主要把精力投入在技術本身。
接下來,我們將面臨一系列問題。
- 我應該做什麼方向?(方向)
- 我應該學習什麼內容?(規劃)
- 我如何學這些內容?(方法/策略)
- 我應該學到什麼程度?(量化)
- 如何把理論用到實際項目/產品中?(產出)
不同方向,意味著不同領域不同,學習的知識和實戰項目有共性也有差異。在這裡,我主要講一下通用的思路。重點拿我擅長方向舉例,其他方向可按照同樣思路舉一反三。
根據我的經驗,可將內容分為原理、應用、擅長方向三個緯度。原理和應用緯度必須學習,方向緯度根據自己擅長方向深入學習。
原理:電腦網路、作業系統、數據結構/演算法,這些東西都是專業課好好學即可,數據結構/演算法可以偶爾刷題。校招的時候再重點複習,初級階段不必花太多時間深究。
應用:它是最基礎的內容,不管你從事什麼領域都將離不開它們。這也是小白入門重點花費時間的地方,你將在這裡不斷與程式鬥爭如調試、驗證、異常、解決。
方向:不同方向本質上就是在基礎應用上擴充,發揮它們擅長領域和特性去解決特定問題。在這裡,簡單列一下涉及的技術棧。
- 後端開發:消息隊列、快取、rpc、微服務。
- 大數據開發:Hadoop、Spark、Storm、Flink
- 自動化運維:elk、ansible、zabbix、docker、k8s
04
基於上述分析,主要講了整體思路,大家可能會覺得有點不太好理解。接下來,拿我當時遭遇的處境進行舉例闡述,這樣讓不同水平或時期的同學有不一樣的體會。
假如有時光機讓時間往後倒退3年,時間來到我剛上大二的時候,作為一枚小萌新開始學習JAVA走上後端開發之路。
對於我來說,作業系統原理、電腦網路先戰略性放棄,畢竟剛接觸編程,看高大上的原理,每次上課都想睡覺。當然,數據結構/演算法我還能好好聽聽,畢竟我數學功底還行讓我不排斥。
為什麼不先學習基礎性原理?
舉例:假設你學騎自行車,你是直接上去就蹬?還是先把輪子拆下來研究清楚原理再去學習怎麼蹬?
重點:根據我的經歷,在新手階段不管是接觸新的語言,還是新的方向。最快的方式就是先把自行車蹬起來,等你蹬熟練了再去研究輪子是怎麼造出來的。
根據上述策略,刨除我踩的一些坑,我把學習征途劃分四個階段,實現學習效率的最優解。
第一階段:新手入門
在我入門的時候,我遇到的最大困難是程式碼不會寫,DEBUG不會做,程式報錯不會看毫無頭緒,甚至大家常說的百度一下的關鍵字我也不知道搜。
這時候,最大的目標就是根據百度/查文檔/看影片,把程式調試出預期結果,甚至你抄程式碼都行,很多時候抄程式碼你都不一定能DEBUG出預期結果。這就是現實,主要就是要把對編程的排斥消磨殆盡。
這個階段,不需要太關注底層實現原理,最重要的工作就是把應用層面的技術,不斷練習直到熟練掌握上面提到的應用緯度「 程式語言、Linux、資料庫、HTTP網路協議 」。
- 時間:3-6月
- 目標:會調試、會查文檔、會用搜索引擎
- 內容:JAVA基礎語法、MYSQL資料庫、Linux作業系統、HTTP通訊協議
- 方法:只關注如何使用技術,難以理解的背下來,不關注底層原理。
- 成果:實現常見的管理系統模組,能部署在伺服器上,供他人訪問。
對於現已從事電腦行業的同學,其實這部分內容非常簡單,可能按照正常水平少則幾天,多則不超過一周就能開發出簡單模組。簡單說,它頂多是普通本科畢設設計水準,主要是讓新手在感官上體驗軟體產品。本質上,在電腦世界裡,抽象來看就是數據的計算、傳輸、存儲。隨著你的經驗增多,你會發現很多技術都是誕生或優化性能都是在解決計算、存儲、傳輸的問題。
在這裡,主要讓大家在系統的角度感受最簡單、最初級的技術模型。
- Linux作業系統:承載應用程式、資料庫的運行,提供CPU供應用程式計算。
- 應用程式(Java/Python/Php):JAVA主要採用Servlet、JDBC承載網路的傳輸、資料庫連接管理。
- 資料庫(MYSQL):主要理解關係類資料庫的存儲,對數據進行操作。
- HTTP/TCP:熟悉重點網路協議,它分為包頭/包體進行傳輸,包體格式可能分為form、json、pb、二進位。
第二階段:項目練習
通過第一個階段學習,你對編程從一無所知到有所斬獲,對電腦世界充滿了好奇,甚至有所開心。這時候,你最應該做的就是去滿足你裝逼的夢想。
假設你是爬蟲方向,你應該去爬表情包、爬知乎數據、自動搶票,去滿足你無數個裝逼夢想。
假設你是演算法方向,你可以去研究推薦演算法、影像識別模型,去做個商品推薦、人臉識秀一秀。
假設你是後端方向,你可以去研究下網路編程/網站開發開發個仿微信聊天應用,體驗下lowB版微信。
畫外音:多做項目,坑是一步一步踩出來的。
作為大學生,實驗室、軟體設計比賽、開源社區都是你發揮現象力的天堂,這些倒騰的經歷將是你畢業時最寶貴的經歷。
第三階段:強化理論
經過前兩個階段實踐,時間來到大三,這時候基本的軟體開發已入門差不多達到普通培訓班畢業水平。同時,專業課如數據結構/作業系統/電腦網路也上的差不多了,對概念多多少少有初步了解。
這時候,你會發現很多原理你不懂,將很難更上一層樓。
- 你不知道使用ArrayList還是LinkedList?
- 你不知道為什麼要使用執行緒池?
- 你不知道為什麼分層設計使用分散式場景?
你將處於寫程式碼一時爽,一直寫一直爽,遇到性能問題直接土崩瓦解。所以,你不得不去學習理論知識讓你走得更遠。
問題:為什麼在這個階段強化理論知識?
在新手階段去強化理論知識,會讓你興趣驟減且產生學了有何用的錯覺。同時,這是最好的時機,學校專業課學完你有基礎概念,你有實際軟體應用場景,這些東西讓你深挖理論的時候會快速給你構建起基礎圖譜,讓你興趣激增不斷體驗學會的東西,將戳痛你最痛的神經,瞬間把你以前遇到的問題有新的認知,這就是答案。簡單說,面向問題,解決問題,讓你實實在在感受到成長,這就是成就感的力量。
問題:如何高效的學習理論?
其實,程式語言和電腦基礎都是相通的,只要你學透一門程式語言剩下的就大同小異。當然,電腦基礎畢竟是枯燥無味的,學習畢竟是有方法的。
舉個例子:
站在程式語言的角度,你用心去總結,你會發現不管什麼程式語言,變來變去都是換了個花樣在談以下內容。
- 程式結構(數據類型、控制語句、面對對象、異常處理)
- 集合(list、set、map)
- 文件操作、網路通訊(io、bio、nio)
- 執行緒、執行緒池
不管在面試還是技術探討,重點考察的都是集合、網路通訊、執行緒/執行緒池。源自於它跟電腦基礎有緊密結合,你要優化它們你必須具備紮實基本功。
基於我的研究經驗,我建議大家在學習電腦基礎的時候,不要因為理論而理論。你應該去通過程式語言源碼去學習電腦基礎,只學你當前認為最重要的。
舉個例子:
當我去學習數據結構/演算法的時候,我會一邊學習源碼一邊思考數據結構,這樣就讓我有實際應用場景不會因為理論而理論。我學習list、set源碼的時候,我就學會鏈表、棧。我學習map的時候,我就學會了紅黑樹、散列表。
當我去學習電腦網路的時候,我會一邊學習socket的用法,學習Linux網路通訊模型epoll,這樣就重點把網路協議學會了。同時,很多應用場景極少的理論知識,我就粗略記憶或者跳過,這樣就節約了很多時間。
當我去學習執行緒/執行緒池的時候,我會學習鎖機制、生產者/消費者模型這些作業系統原理的重要知識,跟程式語言中關聯不大的我就粗略記憶。
第四階段:深究專長
經過前面三個階段的學習,你已經具備紮實基本功和項目實戰經驗。接下來,你需要做的就是更加的專業化,研究一些有生產意義的東西。如果你一直寫學生管理系統,這些沒有價值沒有意義的東西,那麼毫無意義。
這時候,你應該去互聯網公司驗證你學習的技能。除此之外,你可以去學習額外的成熟先進技術棧。這樣,你就有實際業務經驗,就有技術的寬度,同時又有深度,這就是你核心優勢,畢竟演算法/數據結構這些東西在競爭的時候大家都會。
畫外音:去實習,最好去大廠實習,接受互聯網軟體開發的挑戰。要是不能,那麼去研究實際企業技術棧的應用與底層研究。
舉個例子:
假設你是後端開發,你就可以去學習微服務的技術棧,springboot、dubbo、docker、hadoop都可以去學習。除此之外,設計模式,redis原理都可以去學習研究,只有這樣當你去面試的時候,你有很多話題和故事講給別人聽,你的專長研究既可以讓你說業務場景,你又可以講底層原理,對答如流。
05
經過上面的訓練,已經具備了解決問題、快速學習、編寫程式碼能力,也就是具備軟體工程師的職業素養和紮實基本功。
這時候,進入互聯網公司開啟職業道路,你將會很快有產出,不會陷入徘徊自閉的狀態。更何況,你的職業素養已經能夠讓你遇到問題,能快速的學習克服困難。但是,要是讓你去參加面試可不一定能獨善其身,畢竟工作擰螺絲,面試造火箭可不能疏忽大意。
接下來,重點講一下如何應對面試?
面試也就是把自己賣出去,讓別人覺得你值。簡歷是至關重要的環節,所有的知識和技能全都是圍繞它展開,否則毫無意義。因為在面試中,面試官關心你有什麼,也就是面試完全圍繞著你會的東西展開提問,所以你就把你的優勢發揮到極致就行。
環節一:準備簡歷
簡歷一定要認真對待,一定要簡介精鍊,儘可能把內容壓縮到一頁,畢竟簡歷篩選就30秒不到。這時候,簡歷排版、簡歷字體、簡歷模板都有講究,細節決定成敗。
在寫簡歷的時候,主要分為個人資料、實習經歷、項目經歷、專業技能。其實,沒什麼技巧,參考STAR原則,重點體現你在項目中的價值和思考。
- 要體現做了什麼事情?
- 遇到什麼困難?
- 怎麼解決的?
- 產出是什麼?
假設有讀者需要簡歷模板,可關注提供給大家。
環節二:梳理知識體系和刷面經
以前,學習知識是零散的,學習策略更多是面向解決問題,以至於知識不系統,表達邏輯層次有限。面試官邏輯思維強,所以你必須做好充足準備才能脫穎而出。
最好的策略就是梳理知識體系和準備面經,我們都知道要是你面試官問的問題是你剛好熟悉的問題,你豈不是輕鬆闖關成功?所以,準備考綱、梳理知識體系、瘋狂刷題這就是最好的策略。
按照互聯網面試流程大多數分為三輪面。
一輪面試:主要是考察電腦基礎知識和擅長語言基礎知識,重點考察數據結構/演算法、網路編程、擅長語言基礎。但是,絕對不是死記硬背的東西,一定是深度和廣度緊密結合,環環相扣直到把你肚子里的東西全部挖出來。
舉個例子:
- 獲取鏈表倒數第N個節點的值,只許遍歷一次。
- 有一個1G大小的一個文件,裡面每一行是一個詞,詞的大小不超過16位元組,記憶體限制大小是1M,返回頻數最高的100個詞。
- 談談HashMap,說下它們的數據結構?
- Key在HashCode取余以後,它可能全部堆積在某幾個Key對應的鏈表上,這樣就會造成該數據結構存儲或者查詢低效,那怎麼解決呢?
- 為什麼會鏈表要變成紅黑樹,什麼時候從鏈表變成紅黑樹,什麼時候從紅黑樹變回鏈表?
- 假設多個執行緒並發訪問,那可能造成容器更新或者操作出現問題?
- 除了使用synchronized加同步鎖,還有沒有其他辦法解決呢?
- 為什麼採用CAS,能說一下ConcurrentHashMap的具體實現嗎?
你會發現每個問題都是環環相扣,從簡單到難,目的就是挖掘出你的極限。大多數情況都是,從數據結構/演算法入手,擴展到程式語言特性,再擴展到並發/網路編程不斷進行深挖。當直接問實際用法應試者答不出來的時候,就會再次引入到電腦基礎知識,這樣不斷反覆調度試探應試者的是深度和廣度。
二輪面試:這輪考察實習/項目經歷,重點考察你的面試儲備。眾所周知,大部分應屆生項目經驗十分有限,大多數是圖書館管理系統、電商系統這樣。重點說一下應對策略,可以去網上找你做的項目可能遇到的領域難題,去找解決辦法,最終擴展補充到你的項目中。
三輪面試:這輪面試更多是經理考察應試者的基礎能力。也就是邏輯思維、抗壓、時間管理等基礎能力,看下是否能融入團隊,畢竟適合團隊的才是最好的。
這裡主要講了思路和應對策略,至於篇幅有限,面試題只能讀者自己梳理,假設有需要後續再聊。大體的思路:
- 梳理知識體系看面試可能考哪些東西?
- 去網上搜尋和整理面試題?
- 把數據結構/演算法、並發編程、網路編程串聯起來,還要學會理論知識和實際實戰中來回串聯。
總之,作為普通學校的同學,你只有花更加多的時間在項目實戰中,實習/打比賽/逛開源社區,這些時間讓你更快接近成為職業軟體工程師。當機會來臨的時候,你抓住機會就踏入大廠的大門了,幸運永遠不會無緣無故眷顧你。