編者按:編程是確保在21世紀能立足的關鍵技能之一,但是在語言、框架、平臺令人眼花繚亂的編程世界裡,初學者應該學習什麼樣的語言和框架呢?如何才不會在這個黑森林中迷失自己呢?有10多年編程經驗的後端工程師Vardan Grigoryan提供了很好的入門指導。儘管初級開發者基本上需要的是有好的問題解決技能,而且你的第一份工作不會要求你了解本文所有的東西,但是這篇文章對於你的職業生涯規劃還是會起到很好的幫助作用。
我剛開始碼農生涯的時候,主要的煩惱之一是語言/技術的選擇問題。我應該學什麼,應該從哪裡開始?去找第一份程式設計師工作的時候應該了解什麼?當時(10年前)還沒有Coursera、 Udemy 或者 SoloLearn。我沒法找到明確的方向,光靠自己沒法找到通往成功就業的完整路徑。這就是21世紀薪水高待遇好衣食無憂的太空人工作:程式設計師。
這樣的問題仍然存在:初學者仍然受困於選擇,想要成為一名好的程式設計師沒有康莊大道,而且社區對於「pythn是不是一門直覺語言??」這樣的菜鳥問題也沒有那麼熱心了。走向成功編程生涯的道路甚至比以往還要模糊。你應該在C++/C++11/C++14/C++17、Java、C#、Kotlin、PHP (什麼?)、Python、Node.js、JavaScript(等一下,是用Angular、React還是Vue呢?)等等之間做出選擇。
語言、技術還是技能?
為了回答你的主要問題,我必須先問你一個問題。你想要什麼?你是對開發移動app感到興奮呢,還是對網站或者Facebook這樣的網站或者Medium這樣的網站感興趣?還是說你想開發一款像Photoshop那樣的桌面應用?也許你想全情投入到遊戲開發?是移動的還是桌面的呢?
回答「要想被技術公司聘為軟體工程師我應該了解哪些東西?」的最明智方式是找出成功通過技術面試應該掌握的的主要技能。不過首先,我們應該把一些事情先理順,來深入探討一下編程的世界,看看裡面都有哪些國家和城市,看看其中的文化和戰爭,看看個中的得與失。不過如果你性子就是這麼急的話,直接往下翻到「準備編碼面試」章節吧。
探索編程的世界把我們帶到了3個主要平臺面前:
Web(Google Search、Facebook、Amazon、Twitter等)桌面(Dropbox、Photoshop、Visual Studio、Skype等)移動(SoloLearn、Instagram、Uber等)
上述大多數服務在這三個平臺都有。比方說Skype就是一個桌面、移動和web(雖然做得很糟糕)應用。Twitter是一個web和移動應用等等。
Web
在這個上下文背景下web本身就是一個很大的概念,為了講清楚情況,我們會把他分成所謂的前端和後端,後者是我個人很喜歡的一塊。前端是你看到的東西,後端是跑應用的伺服器,負責處理用戶請求、資料庫請求等等。
前端。如果你希望掌握外觀,比方說開發好看到讓用戶愛上的網站,你就應該了解HTML(樣子),CSS(外觀與感覺),JavaScript(感覺)。不過這還不夠,利用純粹的JavaScript在今天已經不夠了,你必須選擇合適的框架,比如目前流行的Angular、React和Vue。要選擇哪一種主要取決於你最喜歡哪一家公司,是Google還是Facebook?如果你喜歡Google的話,那就用Angular,如果喜歡Facebook的話就用React。如果這兩個你都不喜歡(很怪異),那就用Vue吧。簡單!除了這些,你還應該掌握一些基本概念,比如HTTP協議的內部工作機制,要熟悉web伺服器(至少不應該被Apache或者Nginx這樣的名字嚇著)。身為一名前端開發者意味著你從後端拿到要渲染(為了用戶而裝點)的數據,所以要對什麼是API有最小限度的理解,對JSON(以及為什麼它比XML好)的認知是必須的。(如果這些你都聽得一頭霧水的話,看看本文末尾的參考章節)。
dWeb上描述前端與後端差異的眾多迷因之一。
後端。看不見的真相,未透露的故事。在過去,知道PHP足以自稱為後端開發者,然後微軟引入了ASP.NET。這兩個就開始打架,直到Node.js冒出來把東西整理得井然有序。一些事件驅動開發的概念在Node.js上得到了最好的應用,所以如果你選擇這個的話,你就是幫了你的項目大忙了。
後端令人困惑的一部分是語言的多樣性,在後端你可以採用任何想要的語言,關鍵是,「後端」其實是「查詢資料庫、處理書、對客戶端進行響應並且儘可能高效執行」的簡稱。,而選擇「合適」的語言/技術/資料庫並非選項。儘管一些開發者鍾情MySQL或者PostgreSQL這類的關係資料庫,但新進入者卻選擇黑暗面,NoSQL(比如Cassandra 或者MongoDB)。這個選擇完全是個人的,但是我有一個簡單的方程式。你有沒有給你的數據制訂嚴格的計劃並且在不遠的將來它都不會有太大的變化?如果是的話選擇關係式資料庫。你是不是每分鐘的訪問量超過了100萬次?那就選NoSQL(很痛苦)。你的產品是不是頻繁變更?那就選NoSQL。現在,假設你選好資料庫,但是你又打算具體選擇什麼樣的技術呢?你喜歡微軟嗎?有Windows Server嗎?那就選MsSQL。你喜歡Oracle?那就選Oracle。你對Oracle沒意見,但是很討厭微軟?選MySQL。你只是不想傷害任何人?那就選PostgreSQL吧。
NoSQL這玩意兒其實挺棘手的。這東西要取決於你的服務和數據架構。你得到的只是文檔以及其中的一些弱連接?選MongoDB。你需要存儲一大堆的鍵值對?選Redis。你正致力於類似圖的結構(Facebook的朋友圖譜,Google的知識圖譜等)?選擇Neo4j。其實你也不確定自己究竟想要什麼,但是覺得這些全都需要?選ArangoDB吧。
資料庫保存了所有的必要數據,但是你得客戶端要想讀/寫該資料庫卻要你定義一個API。這裡最有用的選項是Node.js,儘管你也可以用PHP或者ASP.NET、Ruby、Python,但我的個人推薦還是Node.js。好吧,Facebook後端用的是PHP,算是吧。他們用C++重寫了PHP的很大一部分。一些人用Python而有的則喜歡用Ruby。誠然,你幾乎可以用任何一種語言寫後端,比方說Google用的是C++、Java和Python(以及Go)。對於底層的數據處理,C++是最合適的,對於像更新用戶朋友推薦這樣的後臺任務,Java是一個好的選項。對於數據分析或者自然語言處理或者目前紅得發紫額AI相關任務,你極有可能用的是Python。
再次地,後端除了各種語言、框架、資料庫以外,你還需要掌握一些核心概念。
緩存(Caching)。從CPU緩存(有不同的級別)開始,到瀏覽器緩存結束,緩存無所不在。對於像Google Search或者Facebook這樣的高負載服務來說,緩存是極其必要的。伺服器(Server)。你可能會認為這個跟硬體有關(如果你懂得如何設置幾臺伺服器讓它們成為一個整體去存儲和處理數據的話當然很棒),不過對於後端開發者來說伺服器意味著web伺服器。當今流行的web伺服器是Nginx,知道如何安裝和配置這個玩意兒的話會對你今後大有裨益。套接字(Sockets)。套接字是網絡編程的基石。你通過網絡發送/接收所有東西都是通過套接字進行的。了解套接字編程的底層細節對於你的技能軍火庫來說是非常有用的補充(知道TCP套接字、UDP套接字之間的區別,以及什麼是WebSockets更是錦上添花)。資料庫設計。不管你選擇了什麼樣的DBMS,對數據進行操作都會是你的主要任務之一。看清數據全貌,對數據進行可視化,並且將數據單元連接起來,這是你在編程生涯中需要掌握的一項技能。安全。就像前面提到的其他概念一樣,這個概念也非常寬泛。你無法徹底掌握其中的任何一種,所以至少你應該熟悉一些最佳實踐,比如存儲面哈希值而不是明文。通過API令牌檢查請求,要對每一項請求驗證用戶許可等等。
桌面
我們會討論桌面應用中令其成為桌面應用的那部分內容。在桌面平臺上需要特殊技能組合的應用數不勝數,比方說,Photoshop處理的是圖像,如果你想寫類似Photoshop這樣的東西的話,了解圖像處理算法和技術就是必須。如果你想寫類似Dropbox這樣的東西,了解套接字編程就是必須。如果你想編寫編譯器或者類似Visual Studio這樣的IDE,則知道如何設計編譯器就是必須。具體細節這裡就不談了,我們就先探討一下如果要做桌面平臺的東西的話,你最有可能會用到的語言吧。
說到桌面應用的語言,開發者得在C++、Java或者C#之中做出艱難選擇。不過這裡有一個簡單的公式幫你做出正確選擇:如果你喜歡微軟,用C#。如果你喜歡Oracle,用Java。如果你認為語言不應該從屬於從何一家公司,用C++。如果這個的幫助作用不大,我們就討論一下具體的子平臺。如果你編寫的軟體只是給Windows用戶用的,C#是最佳選擇。理由很顯然,這兩個都是微軟的產品,自然也會是最佳拍檔。儘管C#的開發者堅稱在發布了.Net Core之後,其實C#也可以用於Linux環境,但我個人建議是如果你也想覆蓋Linux的話,那就用C++。其關鍵是,C++本身就是作為跨平臺程式語言開發出來的,在所有作業系統中都表現得很好(是的,甚至在MacOS上)。在這個上下文中跨平臺會假設你要把你的C++項目在各個作業系統中都要獨立地進行編譯,從而在具體的OS中交付「不同」的應用可執行文件。還有,說實話C++缺乏任何的GUI。實際上,這一點最大的藉口可以說「C++是給鐵桿開發者準備的,而鐵桿開發者除了Terminal(命令行接口)以外什麼都不用。」然而,一群很友好的開發者聚到一起開發出了Qt,這是完美適配C++的跨平臺GUI庫。
最後,如果你對C++的複雜性以及你得連接像Qt這樣的獨立庫用戶才能擁有完整的GUI體驗感到憤怒,並且你討厭要為不同的OS給你的產品編譯和交付不同的可執行文件的話,那就用Java。Java有一個虛機,所以交付可執行文件很容易。你的應用在任何安裝了JVM(Java虛擬機器)的OS都能工作得一樣好。
移動
說到Java,第一個想到的東西就是Android。在Kotlin被引進之前很久時,Java是實現Android app事實上的標準語言。而在今天,Kotlin俘獲了開發者的心,使得Android平臺的應用開發體驗變得更好。所以,如果你想要製作Android app的話,你應該在Java和Kotlin之間進行選擇。為了做出正確的選擇,我們應該看看幕後的東西。關鍵是,Google對Oracle不太感冒。Java是Oracle的,而Java統治著Google的Android,所以為了讓自己有點靈活性,Google在明面上必須引入一個選項(或者在暗面上,這取決於你),而引入Kotlin的目的就是「哇哦,如果有這麼個好東西的話為什麼要用Java呢。」如果你剛開始你的Android開發者生涯的話,我個人建議你從Kotlin開始,儘管要想在市場上成為一名勝任的開發者,你必須支持此前已經用Java實現的app,所以,知道Java的話對你的簡歷會是個加分項。
最後是iOS。iLand完全是另一個故事。很長一段時間以來,Objective-C是iOS的統治性語言,而且說實話,掌握Objective-C需要非常認真,要有一些好耐性。這也是look開發者數量相對較少的主要原因之一,所以蘋果最終做出了正確的選擇,引入了Swift。Swift掌握起來要比Objective-C容易多了,這使得iOS的開發者數量出現了增加。所以,要想成為一名iOS開發者,你需要跟進Swift,但要想成為一名真正自信的開發者,建議你掌握Objective-C,從而為app(無數app都是用Objective-C寫的)提供支持。
這裡我還必須提一提React Native,因為它允許你只用JavaScript編寫同時支持Android和iOS平臺的app,然而,作為這個市場一個新的變化節奏很快的玩家,我們知道有這麼一個東西,而如果你只知道JavaScript的話自己就能寫簡單的app了。
準備編碼面試
在編程世界有些概念是基礎。大多數技術面試的目的都是為了發現你的問題解決技能以及看看你是否了解那些概念,所以除了掌握一門程式語言之外,你應該熟悉一些在程式設計師軍火庫中必須的一些概念。
要想為編碼面試做好成功準備,你應該對以下領域有自信:
算法與數據結構計算機組織&作業系統編碼系統設計
算法&數據結構
這是程序眼最迫切需要的技能集。以下是每一位程式設計師都應該熟悉的主題:
算法複雜性:大O的概念以及如何計算算法複雜性;基於複雜性知道哪一種算法更好,比方說O(N) vs O(logN)。
基本數據結構&適配器:數組、連結表、堆棧、隊列。
排序&搜索:知道各種排序算法可幫助你識別項目的最佳的實現。作為練習,不妨試著實現以下插入排序選擇排序或者合併排序,然後識別線性搜索與折半搜索的不同。
數&圖:樹和圖無所不在,可以從Facebook的「朋友圖譜」和Google Search的「知識圖譜」開始。
哈希表:作為世界上最有效的數據結構之一,哈希表一直都是一個好選擇。你應該能夠實現一個哈希表並且熟悉解決衝突的技巧。
計算機組織&作業系統
強烈建議你要熟悉的主題包括:
逐位運算CPU是如何執行機器代碼的RAM與動態RAM之間的區別時什麼有哪些類型的OS內核「互斥」與「信號量」之間的區別是什麼什麼是死鎖,什麼是活鎖
編碼
你應該至少對一門語言有著非常好的了解。要知道你喜歡的語言所有的優缺點,最佳實踐,這有助於你寫出優雅高效可讀性強的代碼。
高度推薦你通過解決有挑戰性的問題來進練習,比如:
約瑟夫斯問題漢諾塔字符串壓縮平衡括號(Balanced Parenthesis)孿生素數
系統設計
知道面向對象編程對現代程式設計師來說是必須的。
系統設計意味著要考慮整個系統,能夠設計其架構、對其按類進行詳細分析,定義對象的交互。
要準備好回答下述問題:
——讓你設計Google Search的話你會怎麼設計?如果每秒鐘有數百萬的並發請求該怎麼辦?
——你會如何去實現Facebook的朋友查找?
——為什麼你需要使用關係式資料庫管理系統?
——為什麼你要使用NoSQL DB?
高度建議你了解和使用正確的設計模式。比方說,你應該知道Composite(組成)與Decorator(裝飾)這兩種結構型模式的不同。
儘管初級開發者基本上需要的是有好的問題解決技能,而且你的第一份工作不會要求你上述所有的東西都懂,但是這個列表對於你的職業生涯規劃還是會起到很好的幫助作用。
原文連結:
編譯組出品。編輯:郝鵬程。