一名合格的程式設計師需要具備哪些技能?

2020-07-16 10:05:19
程式世界是一片廣闊的大地,相比我十多年前進入這個世界時,這片大地的邊界又擴大了很多倍。初入程式世界難免迷茫,要在這個世界立足、生存,並得到很好的發展,應首要具備怎樣的技能呢?未來的程式之路,先給自己準備一份基本的技能地圖,先有圖,再上路。

在程式的技能地圖中,需要先開啟和點亮哪些部分呢?回顧過去的經歷並結合現實的需要,下面我從「掌握」和「了解」兩個不同程度的維度來說明:
  • 掌握,意味著一開始就要求熟練掌握的硬技能,這是生存之本。而至於掌握的深度,是動態的,倒是可以在行進過程中不斷迭代加深。
  • 了解,相對掌握不是必需,但也需要達到知其然的程度,甚至知其所以然更好。

需要掌握的技能

程式設計師需要掌握的核心生存技能有哪些呢?

開發平台

開發平台包括一種程式語言、附帶的平台生態及相關的技術。

在如今這個專業化分工越來越精細的時代,開發平台決定了你會成為什麼型別和方向的程式設計師。比如,伺服器端、用戶端或前端開發等。其中,進一步細分用戶端還可以有 Windows、Mac、iOS 和 Android 等不同的平台。

1) 程式語言

語言選擇後基本決定了開發平台的性質,但有些語言可能例外,如 C++、JavaScript、C# 等,這些語言都可以跨多個平台。但即使你選的是這些語言,基本也會歸屬到某一類平台上。好比你選了 C++,如果你去做了用戶端開發,就可能很少再去用 C++ 寫伺服器端程式了。

關於語言的選擇,我們已經在《程式設計師如何選擇技術方向或程式語言?》一文中講解選擇的邏輯,這裡不再贅述。但選擇好語言後,我們不僅僅要熟悉語言自身的特性,還需要掌握支撐語言的平台庫。Java 若僅從語言特性上來說,有其優點,但其瑕疵和缺陷也一直被吐槽,若沒有 JDK 強大的平台庫支撐,想必也不會有今天的繁榮。

2) 平台生態

與語言平台關聯的還有其技術生態以及各種技術框架的繁榮程度。這些平台技術生態的存在讓使用這門語言完成特定的程式設計任務變得容易和簡單得多。Java 的生命力除了依靠 JDK 的強大支撐,其平台生態的繁榮也起了決定性的作用。

在選擇了開發平台後,除了語言和平台庫之外,其生態體系內主流的技術框架和解決方案也是必選的掌握內容。

常用演算法

在學校學習的演算法,基本是解決各種電腦科學問題的通用方法。

還記得在學校時看過一本演算法經典書《演算法導論》。最近又把這本書的目錄翻出來過了一遍,發現自己已經忘記了百分之七八十的內容。因為忘記的這部分內容,在過去十多年的工作中我基本都沒機會用上。那麼掌握演算法的目的是為了什麼呢?

有時候你可能會覺得學校教科書上學習的經典演算法,在實際工作中根本就用不上。我還記得考研的時候,專業考試課就是演算法與資料結構,在考卷上隨手寫個排序、樹遍歷手到擒來。但到研究生畢業去參加騰訊校招面試時,被要求在白紙上手寫一個快排演算法,我卻被卡住了,自然也就沒通過。因為已經好久沒有進行這樣的練習,在研究生階段一年期的公司實習工作場景也沒有這樣的需求。

那麼為什麼還要學習這些經典演算法呢?

演算法,表達的是一個計算的動態過程,它引入了一個度量標準:時空複雜度。當我回思時,發現這個度量標準思維在我工作的十餘年中一直在發揮作用。

如今,幾乎所有的經典演算法都能在開發平台庫裡找到實現,不會再需要自己從頭寫。但結合工作的實際業務場景,我們需要去設計更貼合需求的演算法,而只要是演算法,它都會受到時空複雜度的約束,我們只是在其中進行平衡與折中。

學校教科書裡的經典演算法,是剝離了業務場景的高度抽象,當時學來有種不知道用在哪裡的感覺;如今回頭結合真實的業務場景需求再看,會有一種恍然大悟之感。

資料結構

資料結構通常都和演算法一起出現,但演算法表達的是動態特性,而資料結構表達的是一種靜態的結構特性。

大部分開發平台庫都提供了最基礎和常用的資料結構實現,這些都是我們需要熟悉並掌握的,包括:
  • 陣列(Array)
  • 連結串列(Linked List)
  • 佇列(Queues)
  • 堆疊(Stacks)
  • 雜湊(Hashes)
  • 集合(Sets)

另外,還有兩種資料結構不屬於基礎結構,但在現實中有非常廣泛的直接對映場景。
  • 樹(Trees)
  • 圖(Graphs)

每種結構都有各種變體,適用於不同的場景,甚至很多時候你還會需要組合不同的結構去解決一些更複雜的問題。

需要了解的技能

需要了解的內容比需要掌握的更廣泛,但了解了這些方面會讓你更高效地共同作業並解決問題。

資料儲存

不管你寫什麼樣的程式系統,估計都離不開資料儲存。資料是一個業務系統的核心價值所在,所以如何儲存不同型別的生產資料,是你必須要了解的。如今廣泛流行的資料儲存系統有下面三類:
  • SQL(關係型資料庫),如:MySQL、Oracle
  • NoSQL(非關係型資料庫),如:HBase、MongoDB
  • Cache(快取),如:Redis、Memcached

每一種資料儲存系統都有其特定的特性和應用場景。作為程式設計師,我們通常的需求就是最有效地用好各類資料儲存,而按了解的深度需要依次知道如下幾點:
  1. 如何用?在什麼場景下,用什麼資料儲存的什麼特性?
  2. 它們是如何工作的?
  3. 如何優化你的使用方式?
  4. 它們的量化指標是什麼,並能夠進行量化分析。

這4點雖不要求一開始就能掌握到一定程度,但你最好一開始就有這個層次思維,並在日後的工作中不斷去疊代它的深度。

測試方法

為什麼做開發還需要了解測試?

測試思維是一種與開發完全不同的思維模式。有一種流行的開發方法論叫“測試驅動開發(TDD)”,它的流行不是沒有道理的。

在寫程式碼的時候,用測試的思維與方式(提供單元測試)去審視和檢測程式碼,也就是說,明確要開發某個功能後,先思考如何對這個功能進行測試,並完成測試程式碼的編寫,然後編寫相關的程式碼以滿足這些測試用例。

開發與測試這兩種相反視角的切入維度,能真正長期地提高你寫程式碼的效率和水平。

工程規範

每一種開發平台和語言,估計都有其相應約定俗成的一些工程規範要求。最基礎的工程規範是程式碼規範,包括兩個方面:
  • 程式碼結構
  • 程式碼風格

像 Java 發展這麼多年,逐漸形成了一種基於 Maven 的程式碼組織結構規範,這種約定俗成的程式碼結構規範省卻了很多不必要的溝通。有時候,同樣的內容,有更規範的結構,其可閱讀性、理解性就能得到提升。

而至於程式碼風格,相對沒那麼標準化,但為了寫出更清晰、易讀的程式碼,我們至少要堅持自己寫的程式碼具有某種一致性的風格。

另外,除了風格問題,也可以藉助靜態程式碼檢查工具來規避一些新手愛犯的低階錯誤,通過這些工具老手也可以找到自己的認知與習慣盲點。

開發流程

在開發流程方法論上,敏捷基本已經橫掃天下,所以我們至少要了解下敏捷開發方法論。

雖然敏捷方法論定義了一些參考實踐,但它依然是一組非常鬆散的概念。每個實踐敏捷的開發團隊,估計都會根據自己的理解和摸索建立一整套逐漸約定成型的開發流程規範。而為了和團隊其他成員更好地共同作業,估計每個新加入團隊的成員都需要了解團隊演進形成的開發流程規範。

先了解,再優化。

原始碼管理

既然我們生產程式碼,自然也需要了解如何管理好程式碼。

在我的從業經歷中,原始碼管理工具經歷了從 CVS 到 SVN 再到 Git 的變遷。Git 是為 Linux 這樣超大規模的開源專案準備的,自然決定了其能應對各種複雜場景的原始碼管理需求。所以,你至少要了解 Git,並用好它。

當工具變得越來越強大時,工具背後的思想其實更重要,對其的理解決定了我們應用工具的模式。而對原始碼進行管理的最基本訴求有以下三點:
  • 並行:以支援多特性,多人的並行開發。
  • 共同作業:以協調多人對同一份程式碼的編寫。
  • 版本:以支援不同歷史的程式碼版本切換。

總結

最後,我把以上內容總結為一張圖:中心區域(開發平台和常用演算法)相對更小而聚焦,是需要掌握的部分,要求深度;外圍區域的部分更廣而泛,需要廣度。

程序員需要具備的技能圖譜