- 原文地址:Warning: Your programming career
- 原文作者:Vardan Grigoryan (vardanator)
- 譯文出自:掘金翻譯計劃
- 本文永久連結:github.com/xitu/gold-m…
- 譯者:kezhenxu94
- 校對者:swants luochen1992
如何避免迷失在程式設計的黑色森林中
在我的程式設計生涯剛剛開始的時候,主要困擾我的一件事情就是程式語言/程式設計技術的選擇。我應該學什麼,從哪裡入門?要得到我的第一份程式設計工作我需要學會什麼?回望過去(距今大概已經 10 年),那時還沒有像 Coursera、Udemy 和 SoloLearn 這樣的線上教育學習平臺。那時的我也還無法全靠自己就能尋找到通往成功事業的正確方向和完整道路。對於程式設計師這個崗位,高回報、待遇好,簡直堪稱 21 世紀的宇航員。
同樣的問題至今依然存在:初學者苦於選擇。沒有成為好程式設計師的直達途徑,社群通常對於像“Python 是一門膠水語言嗎???”這樣的新手問題不太熱情。通往成功的程式設計事業的道路似乎比以前還更加迷茫。你(假設你是個初學者)必須面臨以下選擇:C++/C++11/C++14/C++17, Java, C#, Kotlin, PHP(神馬?),Python, Node.js, JavaScript(慢著,還包括 Angular, React 或 Vue 嗎?),等等。
語言、技術、還是技能?
為了回答這個關鍵的問題,我必須得先問你,你想要的是什麼?你是對構建手機應用感興趣、還是對構建像 Facebook 和 Medium 這樣的網站感興趣、或者說你更想構建像 Photoshop 這樣型別的桌面應用?還是說你全身心喜愛遊戲開發?移動端遊戲還是桌面遊戲?
“為了得到一個科技公司的軟體工程師職位,我應該學會什麼?”,我覺得回答這個問題最明智的方式就是先找出為了通過這次技術面試你必須掌握的關鍵技能。但我們應該首先把事情整理妥當,現在讓我們深入瞭解程式設計的世界、它的國家、城市,它的文化、戰爭,它的成功、失敗。對於那些沒有耐心看這麼多的讀者,你可以直接滾動到“為技術面試做準備”那一節。
探索程式設計的世界首先讓我們面臨著 3 大主要平臺:
- Web 端(像 Google 搜尋引擎、Facebook、亞馬遜、Twitter、諸如此類)
- 桌面端(像 Dropbox、Photoshop、Visual Studio、Skype 等等)
- 移動端(SoloLearn、Instagram、Uber 以及其他)
其實以上所說的大部分服務幾乎在三個平臺上都有產品,比如 Skype 就有桌面應用、手機端應用以及 Web 應用(儘管做得很爛),Twitter 就有 Web 應用和手機端應用,諸如此類。
Web
Web 在此語境下本身就是個巨大的概念,為了解釋這個概念,我們應該把它分為所謂的“前端”和“後端”,後者正是我個人所偏愛的。前端就是你在網頁上所能看見的東西,後端則為你所能看見的東西提供必不可少的支援。總的來說就是,前端就是網站的外觀和體驗,後端了就是執行著用來處理使用者請求的服務,包括像處理資料庫查詢諸如此類的事。
前端。如果你想精通如何處理網站的外觀和體驗,例如:構建精美絕倫的網站,讓使用者愛不釋手,那你就應該學習 HTML(外觀)、CSS(外觀和體驗)、JavaScrip(體驗)。當然這還不夠。從現在看來,使用純 JavaScript 是不足夠的,所以你得選擇一個合適的框架,目前比較流行的有 Angular,React 和 Vue。選擇哪個主要取決於你最想去哪個公司,Google 還是 Facebook?如果是 Google 那就選 Angular,如果是 Facebook 那就選 React。如果兩個都不喜歡(有點奇怪),那就選 Vue。簡單明瞭!除了這些你還需要掌握一些基礎概念,像 HTTP 協議的內部工作原理;你還需要熟悉一些 Web 伺服器(至少不應該被像 Apache 和 Nginx 這樣的名詞嚇壞)。成為一名前端工程師意味著你必須要渲染你從後臺伺服器得到的資料(為使用者做美化),所以對像“什麼是 API“、“什麼是 JSON(以及為何它比 XML 要好)”之類的問題有個最基本的瞭解是必須的。(如果以上所說的你有任何覺得很陌生的,可以檢視本文末尾“參考文獻”那一節的內容)。
一張網路上描述前端和後端區別的趣圖。
後端。就是看不見的真理,道不清的故事了。在上古時代,瞭解 PHP 的話你就可以宣稱自己是個後端工程師了,後來微軟引入了 ASP.NET,兩者相互角逐,直到 Node.js 駕著七彩祥雲來到,整治混沌,讓一切各得其所。在 Node.js 中,事件驅動開發的概念被應用得淋漓盡致,因此如果你選擇了它,你就已經為你的專案幫了一個大忙。
後端領域中很令人困惑的一個部分就是它的語言多樣性,就是說,你可以使用任何你希望使用的語言來實現後端,但關鍵是:“後端”本身是個簡稱,它包含了“查詢資料庫、處理資料、響應客戶端,以及盡最大努力使得響應最高效”,這並非你選擇了“對的”語言/技術/資料庫就搞定了的。有一些開發者選擇類似 MySQL 或 PostgrSQL 這樣的關係型資料庫,也有一些新入圈的開發者選擇了另一種,就像 Cassandra 或 MongoDB。做出什麼樣的選擇當然取決於你了,但我有個簡單的法則。你的資料有嚴格的模式、並且在短時間內不會發生改變?那就選擇關係型資料庫吧。你的服務每分鐘有超過數百萬的訪問量了?那就得切換到 NoSQL 了(切換過程很蛋疼)。你的產品變化得非常迅速?那就選擇 NoSQL。假如說你已經選擇好了資料庫型別了,那具體的資料庫你應該怎麼選呢?你喜歡微軟並且有 Windows 伺服器?那就選擇 MsSQL。你喜歡 Oracle?那就選 Oracle 資料庫。你對 Oracle 覺得還行、但是同時又討厭微軟?那就選擇 MySQL。或者說你誰也不願得罪?那就選擇 PostgreSQL 吧。
對 NoSQL 資料庫的選擇而言就略顯糾結了。這真的取決於你的後端服務和資料架構。你只有一些文件然後它們之間的聯絡還很微弱?那就選 MongoDB 吧。你需要儲存一大堆的鍵-值對?那就選 Redis。你正在處理像圖這種結構的資料(Facebook 的好友關係圖,Google 的知識網路圖,等等)?那就選 Neo4j。還不確定你究竟需要什麼,但你覺得以上所說的你都需要?那就選 ArangoDB 吧。
資料庫儲存了所有必要的資料,同時你也應該定義一種 API,使得你的客戶端可以通過它來請求對資料庫進行讀/寫。這裡更有用的選擇就是 Node.js。Facebook 選擇了 PHP 來作為它的後端實現,然後他們又用 C++ 重寫了其中的很大一部分 PHP 程式碼。有人使用 Python 但也有人更喜歡 Ruby。確實是這樣的,你能選擇任何語言來實現後端服務。比如說:Google 使用 C++、Java 和 Python(跟 Go 結合使用)。對於底層的資料處理,C++ 最合適不過了;對於後臺任務,像更新使用者的朋友推薦,Java 是個好的選擇;對於資料分析、自然語言處理或當今最流行的與人工智慧相關的任務,你很可能會選擇 Python。
重申一遍,後端除了各種各樣的程式語言、框架、資料庫,還有一些你必須掌握的核心概念。
- 快取。從底層的 CPU 快取(有不同層級的快取)到頂層的瀏覽器快取。到處都在使用快取。對於高負載的服務,像 Google 搜尋引擎或 Facebook,快取都是至關重要的。
- 伺服器。你可能會覺得這是關於硬體的(如果你知道怎麼把多臺計算機設定得像一臺那樣儲存和處理資料的話,那最好不過了),對於後端工程師來說,伺服器僅意味著 Web 伺服器。目前流行的 Web 伺服器就是 Nginx,瞭解如何設定和配置 Nginx 對你以後的努力會有高回報的。
- 套接字(Sockets)。網路程式設計的基石。你通過網路傳送和接受的所有東西都是通過套接字完成的。瞭解套接字程式設計的底層細節在你的技能譜中是一種額外加成,要是瞭解 TCP 套接字和 UDP 套接字的區別以及什麼是 WebSocket,那就更是極大的附加價值了。
- 資料庫設計。不管你自己選擇或不得已使用哪種資料庫管理系統(DBMS),運算元據將是你的主要任務之一。看清整個資料庫的大局、將資料視覺化、瞭解資料單元之間的聯絡,在你的程式設計生涯中這些能力都是必須掌握的。
- 安全性。與上述提及的概念不同的是,這個概念相對非常廣泛。你甚至不可能完全掌握它,因此你至少要熟悉一些相關的最佳實踐,比如不能明文存放密碼,要使用密碼的雜湊值/雜湊值(hash);通過 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++ 確實缺乏圖形化使用者介面,最好的藉口莫過於“C++ 本來就是為大神級開發者準備的,大神級的開發者通常都只用終端(命令列介面)”。不過,還是有好心的開發者聚到一起開發了 Qt,這可是完美相容 C++ 的跨平臺圖形化使用者介面庫。
最後一點,如果你很煩 C++ 的複雜性,很煩為了構建完整的影象化使用者介面還不得不連結一個另外的像 Qt 這樣的庫,也很討厭為了適配不同的作業系統的使用者而不得不在每一種作業系統上編譯、移植你的應用,那就選擇 Java 吧。Java 擁有自己的虛擬機器,使得移植可執行檔案很容易。你的應用將在所有安裝了 JVM(Java 虛擬機器)的作業系統上完美執行。
移動端
當談到 Java 時,首先映入腦海的就是 Android 了。早在 Kotlin 問世之前,Java 就是開發 Android 應用的事實標準了。現如今,Kotlin 佔據了開發者的內心,使得開發 Android 應用的體驗更好。因此,如果你想開發 Android 應用的話,你應該在 Java 和 Kotlin 之間進行選擇。為了做出正確的選擇,我們得看看幕後的真相。真相就是 Google 和 Oracle 不是很和諧,但 Oracle 擁有 Java,同時 Java 又主導了 Google 的 Android,因此為了靈活不受限於人,Google 不得不向邪惡勢力(或者說正義,隨你怎麼說)低頭,引入了 Kotlin,並且假裝說“哇,我們支援這麼好用的程式語言,你們就別再用 Java 啦”。如果你剛開始 Android 程式設計的話,我個人建議你從 Kotlin 入門,儘管為了在人才市場中提高競爭力你不得不為用 Java 實現的舊應用提供一些支援,所以這時候學會 Java 就會為你的簡歷增添一些亮點。
最後就是 iOS 了。所謂的 “iLand”(譯註:由於蘋果大部分產品都以 i 打頭,原作者使用 iLand 表示蘋果的產品線),就是全然不同的故事了。很長一段時間內 Objective-C 都是 iOS 的主要開發語言,老實講,不是隨隨便便就能夠掌握 Objective-C 程式設計的,它需要堅定不移的毅力,這就是為數不多的 Objective-C 開發者的主要問題。蘋果公司最終總算邁出正確的一步,引入了 Swift。Swift 相比 Objective-C 來講要容易得多,這使得 iOS 開發者數量有所上漲。所以說要成為 iOS 開發者,你得學習 Swift,但要成為合格的開發者,我還建議你要掌握 Objective-C,因為你需要給以前使用 Objective-C 編寫的應用(有成千上萬這樣的應用)提供支援。
這裡不得不提一下 React Native,因為它使得開發者能夠僅僅使用 JavaScript 就同時為 Android 和 iOS 編寫應用,但是 React Native 作為市場上一個新興且善變的角色,我們就讓它刷一下存在感好了,如果你還會一些 JavaScript 的話,就權當你已經能編寫一些簡單的應用了。
為技術面試做準備
程式設計領域中有很多基礎的概念。大部分技術面試目的都是發現你解決問題的能力以及是否瞭解這些概念,所以除了掌握一門程式語言之外,你還要熟悉這些概念,某種程度上講,這些概念在程式設計師的技能譜中是必須的。以下是我最近在 SoloLearn 上釋出的課程的概要,下面是 SoloLearn 的 Android 和 iOS 應用下載地址。
為了成功為技術面試做準備,你必須對以下的領域感到非常自信:
- 演算法與資料結構
- 計算機組成結構與作業系統
- 程式設計
- 系統設計
演算法與資料結構 這是程式設計師最需要的技能譜。以下是每一個程式設計師都必須熟知的:
演算法複雜度:大 O 記法和如何計算演算法複雜度;掌握如何根據演算法的複雜度來比較演算法的優劣,如 O(N) 和 O(logN) 孰優孰劣。
基本資料結構和介面卡:陣列、連結串列、棧、佇列。
排序與查詢:掌握各種排序演算法能夠幫你定下專案的最佳可能實現。作為練習,嘗試一下自己實現插入排序、選擇排序和歸併排序,然後找出線性查詢和二分查詢的不同點。
樹、圖:到處都有樹和圖的蹤影,從 Facebook 的“朋友關係圖”,到 Google 的“知識聯絡圖”。
雜湊表/雜湊表:史上最高效的資料結構,雜湊表總是一個好的選擇。你應該要能夠自己實現一個雜湊表,並熟知解決雜湊衝突的技術。
計算機組成結構與作業系統 強烈建議你要熟悉以下主題:
- 位運算
- CPU 如何執行機器程式碼
- 靜態隨機訪問儲存(RAM) 和動態隨機訪問儲存(RAM)的區別
- 有哪些型別的作業系統核心
- “互斥鎖”和“訊號量”的區別
- 什麼是死鎖、什麼是活鎖
程式設計 你應該精通至少一門程式語言。知道你最喜愛的那門程式語言的優勢、劣勢以及最佳實踐總會幫你寫出更高效、更優雅和可讀性更強的程式碼。 強烈建議你通過解決有挑戰的難題來練習程式設計,比方說(以下問題都可以在 SoloLearn 找到):
- 約瑟夫問題
- 漢諾塔
- 字串壓縮
- 匹配的括號
- 孿生素數
系統設計 瞭解物件導向程式設計是現代程式設計師的必備技能。 系統設計意味著要考慮整個系統、能夠設計其架構、將其分解成一個個的類、定義物件之間的互動。 嘗試回答以下問題來對此做準備:
- 如果是你,你會怎麼設計 Google 搜尋引擎?如果每秒有上百萬請求同時來到怎麼辦?
- 如果是你,你會怎麼實現 Facebook 的好友搜尋?
- 什麼情況下你會使用關係型資料庫管理系統?
- 什麼情況下你會使用 NoSQL 資料庫?
強烈建議你學習和使用正確的設計模式。比如你應該瞭解組合模式和裝飾器模式的區別。
儘管通常都只要求初級開發者擁有良好的解決問題的能力,你的第一份工作可能也不會要求你瞭解以上所列的所有點,但這個列表還是能幫助你規劃以後的職業生涯。
掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 Android、iOS、前端、後端、區塊鏈、產品、設計、人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。