標籤:
老王正式工作快10年了,前一段時間有幸去給母校的學弟學妹們聊了聊人生和理想。回來以後,有學弟學妹問我該如何學習。老王於是很認真的思索了這個問題。後來做了這樣一個假設:如果讓我講講所熟悉的互連網技術體系架構如何學,我該怎樣講?
老王頓時覺得有些緊張,雖然在二百(百度和百詞斬)做了不少關於互連網Server的工作,也做過一些總結,但是這個話題實在太大太深厚了,要聊的東西實在太多(百度搜尋“互連網服務端技術”的結果大約700萬條),需要有相當的積累。老王是一個做技術的人,不太喜歡複雜和虛幻的東東,凡事都喜歡把問題往簡單實在了想和做(Linus said:Talk is cheap. Show me the code.),於是趕緊摸出小本本,開始邊想邊畫,思索有沒有相對比較簡單的方法把這個事情說清楚。經過好幾天的思考和修改,畫出了以下的一張圖(以下的圖只代表老王自己的觀點,由於眼界和閱曆有限,如有不妥,請指正~)。
在老王的思維裡,要學習互連網服務端的技術知識,在廣度上,以上的東東大體涵蓋了相關內容;在深度上,根據要求不一樣,對於上述內容學習的程度會有不同。比如,如果你是個人web服務業務的研發人員,可能只需要對程式設計語言、架構和資料庫有一定瞭解並能運用就可以了;如果是一個大型購物網站的架構師,可能以上內容都需要比較深入的研究。
好了,有了這個藍圖,老王想接下來細細講講每一個部分的內容。每一部分內容,老王都準備分成:初級、中級、進階三個層級的能力要求來分析。如果願意,跟著老王一起來吧~
·語言(language)
我把語言放在了所有這些的首位,因為語言是做一切的基礎,他是你表達你內心思維的手段。老王經常打比方,語言好比就是武俠裡面的各種劍法、掌法……你要把你的內功心法表達出來,需要通過他們來落地。
現在流行的語言很多,c/c++、 java、 php、 c#、 obj-c、 python、 ruby、 perl……這麼多的語言可以羅列半天。而不同語言有各自的適用範圍和優缺點(前一段時間,有不少盆友總結了多個版本的語言鄙視鏈)。老王寫過c/c++、 java、 c#、 php、 python、 javascript、 scala和shell指令碼,用的比較熟的是c/c++、 java、 js和shell指令碼。最喜歡的是java,因為伺服器、用戶端都能用,而且語言本身文法不複雜(大家嫑搬出鄙視鏈來鄙視老王哈^_^)。
老王覺得語言不用學太多太雜(那麼多的語言,都要學一遍,多難受啊),最重要的是學好兩個東西:一個是精深一門語言,一個是編譯原理。
[初級能力]
會用一門語言是最基礎的,就跟農民伯伯要種田,最首要的是會挖土一樣。瞭解語言的文法、會用常用的庫、寫出基本的邏輯,這個算是對碼農們最基礎的能力要求,就是維持溫飽必須要的東東。
[中級能力]
除了用語言去寫準系統邏輯以外,我們經常還要去解決一些深入的問題(比如:java記憶體泄露、c/c++的core dump、javascript的相容性問題等等),這就要求我們學精深一門語言。要做到這一點,不光要學習語言本身的文法,還要學習大量的基礎庫、公用庫和第三方庫、運行架構、編譯器(解譯器或虛擬機器)運行原理等。就跟學英語一樣,字母、單詞、發音、文法、句法等等。這是一整套體系,只有這一套體系瞭解的比較清楚了,才敢說對xx語言比較熟悉。有了這些能力,就可以說在一個語言體系中是半個專家,基本也可以奔小康了。
[進階能力]
當對一個語言比較瞭解以後,就可以學習一下編譯原理。編譯原理是學習怎麼學習語言(Learn how to learn a language.),他告訴你代碼是怎麼樣從一個個字元變成機器指令的,這個學通了,學會的就不是“魚”而是“漁”了。學編譯原理的最好辦法,就是自己寫一個簡單語言(比如c語言子集)的編譯器(雖然寫的會很難受,但是一旦寫成,就會恍然大悟:哦,原來是tmd這個樣子的啊)。會這個,你可以去完善一個語言,去加入某個組織制定新的標準,亦或是設計屬於自己的一個全新的語言。
之前面試程式員的時候,經常會看到這樣的簡曆:“精通java、c#、python、php……等多種語言”。老王不禁感歎,能真正熟練掌握一門已經是非常難的事情,要精通N門語言,只有兩種可能:要麼是天才,要麼簡曆寫的過了。
總的來說,語言是一個做電腦技術碼工最需要掌握的基礎知識,老王個人覺得對他的瞭解,不需太雜,關鍵在精。如果想求溫飽,會用一到兩門語言寫出商務邏輯即可。如果想在這方面有所建樹,就需要對原理性的東西多深入瞭解+實踐。
·演算法和資料結構(algorithm & data-structure)
我面試過大概幾百個程式員,演算法和資料結構絕對是讓無數位工吐槽最多最深的東東:我們平時工作就搬搬磚、寫寫邏輯,又不用上什麼樹啊、圖啊之類的,學那麼多演算法和資料結構幹嘛?!
老王當年不算認真的搞過acm(全稱:acm/icpc,中文:國際大學生程式設計大賽),也在外面拉過項目,當時也是覺得,acm那些演算法在實際工作中幾乎沒用,就用來弄弄比賽,裝個B啥的。後來去了百度,進去沒多久就參加了一個工程最佳化的比賽:我們熟悉的搜尋技術遇到了麻煩,就是網頁搜尋有很多的結果,需要把這些結果做歸併排序,然後將topN的結果展示給使用者。由於線上請求量巨大,需要對排序的效率做最佳化,保證請求反應速度儘可能的快,消耗cpu資源儘可能的少。在那個最佳化比賽中,老王除了收穫獎品以外,還意識到二分搜尋、各種排序等等演算法和數組、鏈表、樹等等資料結構原來在實際項目工作中可以有這麼大的用處。後來有經曆了其他的一些項目,用到了諸如dfs、bfs、dp、trie樹、bk樹等等。
[初級能力]
想把一個東東做出來,以應對邏輯開發的需要,其實不用太瞭解高深的演算法和資料結構。只需要把常用的演算法(比如:排序)和常用的資料結構(比如:數組、鏈表)知道怎麼樣用就可以了。一般語言都有庫,會調用他們即可。
[中級能力]
如果想把一個東東做好一點,代碼更優雅,執行效率更高。就需要更深入的去瞭解一下常用的演算法和資料結構的原理。比如:數組和鏈表有什麼區別?他們各種操作的時間複雜度是怎麼樣的?在哪種情況下適合用數組,哪種情況下適合用鏈表?HashMap和TreeMap有什麼不一樣?等等。
[進階能力]
如果你是一個大型網站的技術負責人或者核心系統的負責人,可能就需要對演算法和資料結構有比較深入的瞭解了。不但要瞭解基礎的演算法和資料結構,還要深入的掌握一些進階的演算法和資料結構,讓你的代碼或者系統跑起來就是要比其他人的每次至少快千分之幾秒。為什嗎?因為如果每天有上億的請求,你的千分之幾秒就變成了每天幾十萬秒。這有可能就是對產品使用者體驗的直接提升,也可能就省下了N台伺服器。
演算法和資料結構其實是很能考配量序員能力的一個部分,所以很多牛逼的公司都把演算法和資料結構作為考察的重中之重(我有一個朋友寫了一篇關於去矽谷面試的面經,裡面就很重的談到了矽谷的這些公司對演算法和資料結構的要求,我看看什麼時候分享給大家)。從老王的經驗上講,學好這個本事,會終身受益(老王當年一起搞acm的盆友們,絕大多數現在都去矽谷了)。
那怎麼學?如果只是基本要求,可以看看基礎庫裡基本演算法和資料結構的實現代碼,自己沒事兒的時候照著寫寫。如果對自己有很高的要求,可以看《演算法導論》3遍以上 +幾個著名高校的acm online judge(線上評判系統)練習100題以上。做完這些以後,你就不光只是一條好漢了,而是一個內力深厚的硬漢!
·架構(framework)
要做好工程項目,寫好伺服器代碼,除了語言以外,架構是另外一個必修課。比如,我們要做web開發,java至少要瞭解一下J2EE的東東,懂tomcat、jboss、resin、jetty等等這些中的至少一個,否則就只有自己從輪子開始造起。進階點的,還要去瞭解一下struts(原來還有webwork)、spring和hibernate等等。而ruby的開發,可能需要瞭解rails,php需要瞭解zend或是symfony等等。
這些架構幫我們把基礎的網路連接、http協議解析、路由轉寄、會話管理、交易管理等等都做了很好的封裝,讓我們開發起來更順手和容易。因此,如果對一個架構足夠瞭解的話,會讓開發像坐上了火箭一樣快速(避免被產品經理拿著棒子在後面追著跑^o^)。
不過架構自身也有優缺點,比如很多架構為了功能大而全,用起來就比較笨重,犧牲了很多效率,配置起來也可能比較麻煩(導致入門成本高,口裡就會不斷默念:我擦……)。所以,很多對效率要求比較高的公司或者服務,一般都會自己寫一些架構,來取得功能和效率的平衡。
[初級能力]
為了開發商務邏輯,我們只需要掌握他的使用,會安裝、會配置、會運行即可。讓基本的邏輯能夠輕鬆的跑在架構上。對於通用的一些架構,我們只要百度一下,便能夠相對比較輕鬆的hold住(不過有些配置真是很煩很雜,不過沒辦法,為了要用他,只有痛苦一次)。
[中級能力]
如果架構提供的準系統有些時候不滿足我們需求的時候,或者出問題的時候,我們就需要知道他的部分工作原理,能夠定位,去判斷是哪裡產生的原因。同時,可能還要會一些進階的用法和組件,減少開發量,提升執行效率等等。比如,架構是怎麼做路由的、怎麼解析http協議參數的、cookie是怎麼存放的、session是怎麼樣管理的,等等。
[進階能力]
如果你掌管一家中大型公司的技術,很有可能你會帶領團隊重新寫一套適合相關業務的架構。這個時候,就需要你完全掌握對於語言常用架構的工作原理以及他的組件,方便你在使用的時候,對他進行最佳化,甚至直接重寫一套。要具備這樣的能力,說難也難,說不難也不難:其實就是去仔細閱讀這些常用架構的代碼,分析關鍵點,思考他們設計的邏輯。我曾經讀過一些架構代碼,有寫的好的,也有寫的不是特別好的。不過每次讀完,都有新的收穫,協助我對架構有了更深入的瞭解。
工欲善其事,必先利其器。學好用好架構,會對我們的開發效率有極大的協助,如果能掌握他的特性,瞭解他的工作原理,對我們提升執行效率也會非常有協助。所以,建議大家對於架構,還是要有一定深度的瞭解。
=== 暫時休息的分割線 ===
因為這篇文章飽含了老王多年的心血(此處應有掌聲),寫的可能會比較多。為了讓大家看的輕鬆些,老王打算拆分成上中下三篇來寫和發布。
中篇準備介紹作業系統、資料庫和網路相關的東東,而下篇則會更偏重工程中遇到的架構、組件(比如:訊息佇列、內容彙總系統等)。
如果對這幾篇文章有興趣,歡迎大家繼續關注老王的:simplemain
=== 美的分割線 ===
老規矩,文章末尾上一張老王自己拍的美圖:這一張是我2010年環青海湖騎行拍的一張落日,當時感覺還不錯,分享給大家~
互連網服務端技術——如何學(上)