真·程式設計師必修書單

hellogithub 發佈 2020-01-16T10:02:45+00:00

全球簡訊系統每日收發約200 億條信息,而僅僅靠 57 名工程師,現在的 WhatsApp 每日收發 420 億條。


本文作者:削微寒

迫近年關,很多人都寫了 19 年的總結和 20 年的展望。我在回想 2019 年的時候,想到自己只讀完了幾本『雜』書,真正技術的書籍一本也沒有讀完。焦慮就悄然湧上心頭,有種不學習就退步的煩躁。然後我回想起了之前看到的一個網站:

  • Teach Yourself Computer Science:https://teachyourselfcs.com/
  • GitHub 上的中文翻譯:https://github.com/keithnull/TeachYourselfCS-CN

現在的技術書籍很多,怎麼才能找到其中的精華,從而讓我花在書籍上的時間『勞有所獲』,哪些書籍值得花時間多讀幾遍?

下面要介紹的內容就是為了解決以下兩個問題:

  • 你應該學習哪些科目,為什麼要學?
  • 這些科目對應的最好的學習資料(書籍、視頻)是什麼?

接下來,你將得到答案。(我尋找的書單要來啦!)

一、概覽

按照列出的順序,藉助建議的書籍和視頻課程,學習下面的 9 門科目。如果你是一個自學成才的工程師,或者從編程培訓班畢業,那麼你很有必要學習計算機科學。

(我本科餵了 Dota,編程算是自學的。工作了後我深刻的體會到,這些科目的重要性。)

二、為什麼要學習計算機科學

軟體工程師分為兩種:

  • 一種充分理解了計算機科學,從而有能力應對充滿挑戰的創造性工作;
  • 另一種僅僅憑著對一些高級工具的熟悉而勉強應付。(直白有力,直擊心靈)

這兩種人都自稱軟體工程師,都能在職業生涯早期掙到差不多的工資。然而,隨著時間流逝,第一種工程師不斷成長,所做的事情將會越來越有意義且更為高薪,不論是有價值的商業工作、突破性的開源項目、技術上的領導力或者高質量的個人貢獻。

全球簡訊系統每日收發約 200 億條信息,而僅僅靠 57 名工程師,現在的 WhatsApp 每日收發 420 億條。

— Benedict Evans (@BenedictEvans)

第一種工程師總是尋求深入學習計算機科學的方法,或是通過傳統的方法學習,或是在職業生涯中永無止息地學習;

第二種工程師通常浮於表面,只學習某些特定的工具和技術,而不研究其底層的基本原理,僅僅在技術潮流的風向改變時學習新的技能。

如今,湧入計算機行業的人數激增,然而計算機專業的畢業生數量基本上未曾改變。第二種工程師的供過於求正在開始減少他們的工作機會,使他們無法涉足行業內更加有意義的工作。對你而言,不論正在努力成為第一種工程師,還是只想讓自己的職業生涯更加安全,學習計算機科學是唯一可靠的途徑。

(成為不可或缺的人才,而不是可以隨意被替代的熟練工。我的熱血沸騰起來了,我要知道如何成為真·程式設計師!)

三、分科目指引

注意:因為篇幅問題,我刪除了視頻部分的推薦。有需求的小夥伴,可點擊閱讀原文。

3.1 編程

大多數計算機專業本科教學以程序設計「導論」作為開始。這類課程的最佳版本不僅能滿足初學者的需要,還適用於那些在初學編程階段遺漏了某些有益的概念和程序設計模式的人。

對於這部分內容,我們的標準推薦是這部經典著作:《電腦程式的構造和解釋》。在網絡上,這本書既可供免費閱讀(英文版)

我們建議至少學完 SICP 的前三章,並完成配套的習題。如果需要額外的練習,可以去解決一些小的程序設計問題,比如exercism

(這本書我讀完序章就睡著了,我要擦乾口水,扶我起來)

3.2 計算機架構

計算機架構——有時候又被稱為「計算機系統」或者「計算機組成」——是了解軟體底層的的重要視角。根據我們的經驗,這是自學的軟體工程師最容易忽視的領域。

《計算機系統要素》,又名「從與非門到俄羅斯方塊」(「Nand2Tetris」)。這本書規模宏大,讓讀者對計算機內的所有部分如何協同工作有完全的認識。這本書的每一章節對應如何構建計算機整體系統中的一小部分,從用 HDL(硬體描述語言)寫基本的邏輯門電路出發,途經 CPU 和彙編,最終抵達諸如俄羅斯方塊這般規模的應用程式。

我們推薦把此書的前六章讀完,並完成對應的項目練習。這麼做,你將更加深入地理解,計算機架構和運行其上的軟體之間的關係。

這本書的前半部分(包括所有對應的項目)均可從Nand2Tetris 的網站上免費獲得。

硬體是平台。

— Mike Acton, Engine Director at Insomniac Games

(不明白遊戲平台的規則,很難成為超級玩家)

3.3 算法與數據結構

正如幾十年來的共識,我們認為計算機科學教育所賦予人們的最大能量在於對常見算法和數據結構的熟悉。此外,這也可以訓練一個人對於各種問題的解決能力,有助於其他領域的學習。

關於算法與數據結構,有成百上千的書可供使用,但是我們的最愛是 Steven Skiena 編寫的 《算法設計手冊》。顯而易見,他對此充滿熱愛,迫不及待地想要幫助其他人理解。在我們看來,這本書給人一種煥然一新的體驗,完全不同於那些更加經常被推薦的書。

至於練習,我們推薦學生在Leetcode上解決問題。Leetcode 上的問題往往有趣且帶有良好的解法和討論。此外,在競爭日益激烈的軟體行業,這些問題可以幫助你評估自己應對技術面試中常見問題的能力。我們建議解決大約 100 道隨機挑選的 Leetcode 問題,作為學習的一部分。

最後,我們強烈推薦 《怎樣解題》。這本書極為優秀且獨特,指導人們解決廣義上的問題,因而一如其適用於數學,它適用於計算機科學。

我可以廣泛推薦的方法只有一個:寫之前先思考。

— Richard Hamming

(我這個算法渣默默的捧起了《我的第一本算法書》,上面的推薦的書明年再戰!)

3.4 數學知識

從某個角度說,計算機科學是應用數學的一個「發育過度」的分支。儘管許多軟體工程師試圖——並且在不同程度上成功做到——忽視這一點,我們鼓勵你用學習來擁抱數學。如若成功,比起那些沒有掌握數學的人,你將獲得巨大的競爭優勢。

對於計算機科學,數學中最相關的領域是「離散數學」,其中的「離散」與「連續」相對立,大致上指的是應用數學中那些有趣的主題,而不是微積分之類的。由於定義比較含糊,試圖掌握離散數學的全部內容是沒有意義的。較為現實的學習目標是,了解邏輯、排列組合、機率論、集合論、圖論以及密碼學相關的一些數論知識。考慮到線性代數在計算機圖形學和機器學習中的重要性,該領域同樣值得學習。

學習離散數學,我們建議從 László Lovász 的課程筆記開始。Lovász 教授成功地讓這些內容淺顯易懂且符合直覺,因此,比起正式的教材,這更適合初學者。

對於更加高階的學習,我們推薦 《計算機科學中的數學》,MIT 同名課程的課程筆記,篇幅與書籍相當(事實上,現已出版)。

對於線性代數,我們建議從 Essence of linear algebra 系列視頻開始,然後再去學習 Gilbert Strang 的《線性代數導論》

如果人們不相信數學是簡單的,那麼只能是因為他們沒有意識到生活有多麼複雜。

— John von Neumann

(放我一條活路)

3.5 作業系統

《作業系統概念》(「恐龍書」)和 《現代作業系統》是作業系統領域的經典書籍。二者都因為寫作風格,長達 1000 頁的篇幅以及每隔幾年就增加內容來鼓勵人們購買「最新版本」招致了一些批評。

《作業系統導論》(Operating Systems: Three Easy Pieces)是一個不錯的替代品,並且可在網上免費獲得(英文版)。我們格外喜歡這本書的結構,並且認為這本書的習題很值得一做。

在讀完《作業系統導論》後,我們鼓勵你探索特定作業系統的設計。可以藉助「{OS name} Internals」風格的書籍。

為了鞏固對作業系統的理解,閱讀小型系統內核的代碼並且為其增加特性是一個很不錯的方法。

(寫一個小型系統內核很酷)

3.6 計算機網絡

鑒於有那麼多關於網絡服務端和客戶端的軟體工程,計算機網絡是計算機科學中價值最為「立竿見影」的領域之一。我們的學生,系統性地學習了計算機網絡,最終能夠理解那些曾困擾他們多年的術語、概念和協議。

在這一主題上,我們最愛的書籍是 《計算機網絡:自頂向下方法》。書中的小項目和習題相當值得練習,尤其是其中的「Wireshark labs」(這部分在網上可以獲得)。

對於計算機網絡的學習,做項目比完成小的習題更有益。一些可能的項目有:HTTP 伺服器,基於 UDP 的聊天 APP、迷你TCP棧、代理、負載均衡器或者分布式哈希表。

你無法盯著水晶球預見未來,未來的網際網路何去何從取決於社會。

— Bob Kahn

(之前有人給我推薦過,我沒買來看。然而現在正在讀:真香~)

3.7 資料庫

比起其他主題,自學資料庫系統需要更多的付出。這是一個相對年輕的研究領域,並且出於很強的商業動機,研究者把想法藏在緊閉的門後。此外,許多原本有潛力寫出優秀教材的作者反而選擇了加入或創立公司。

鑒於如上情況,我們鼓勵自學者大體上拋棄教材,而是從2015 年春季學期的 CS 186 課程(Joe Hellerstein 在 Berkeley 的資料庫課程)開始,然後前往閱讀論文。

對於初學者,有一篇格外值得提及的論文:「Architecture of a Database System」。這篇論文提供了獨特的對關係型資料庫管理系統(RDBMS)如何工作的高層次觀點,是後續學習的實用梗概。

《Readings in Database Systems》,或者以資料庫「紅書」更為人知,是由 Peter Bailis,Joe Hellerstein 和 Michael Stonebraker 編纂的論文合集。對於那些想要在 CS 186 課程的水平更進一步的學習者,「紅書」應當是下一步。

如果你堅持一定要一本導論教材,那我們推薦 Ramakrishnan 和 Gehrke 所著的 《資料庫管理系統:原理與設計》

如果沒有編寫足夠數量的代碼,很難鞏固資料庫理論。CS 186 課程的學生給 Spark 添加特性,倒是不錯的項目,不過我們僅僅建議從零實現一個簡單的關係型資料庫管理系統。自然,它將不會有太多的特性,但是即便只實現典型的關係型資料庫管理系統每個方面最基礎的功能,也是相當有啟發的。

(國內做資料庫的公司越來越多了,但這塊我還啃不下先放放)

3.8 程式語言與編譯器

多數程式設計師學習程式語言的知識,而多數計算機科學家學習程式語言 相關 的知識。這使得計算機科學家比起程式設計師擁有顯著的優勢,即便在編程領域!因為他們的知識可以推而廣之:相較只學習過特定程式語言的人,他們可以更深入更快速地理解新的程式語言。

權威的導論書籍是《編譯原理》,通常稱為「龍書」。不幸的是,這本書不是為自學者而設計的,而是供教師從中挑選一些主題用於 1-2 學期的教學。因此十分重要的是,你需要從中甄選主題,而且最好是在導師的幫助下。

對於項目練習,我們建議為諸如 COOL 的簡單教學語言或者你所感興趣的某個語言的一個子集寫一個編譯器。如果感覺這樣的項目讓人生畏,可以先從 Make a Lisp開始,在一步步的指引下完成項目。

不要做一個只寫樣板代碼的程式設計師。相反,給用戶和其他程式設計師創造工具。從紡織工業和鋼鐵工業中學習歷史教訓:你想製造機器和工具,還是操作這些機器?

— Ras Bodik 在他的編譯器課程伊始

(我說為什麼大神學習一門語言那麼快!)

3.9 分布式系統

隨著計算機在數量上的增加,計算機同樣開始**分散((。儘管商業公司過去願意購買越來越大的大型機,現在的典型情況是,甚至很小的應用程式都同時在多台機器上運行。思考這樣做的利弊權衡,即是分布式系統的研究所在,也是越來越重要的一項技能。

對於自學者,我們推薦的教材是 Maarten van Steen 和 Andrew Tanenbaum 所著的《分布式系統原理與范型》(中文第二版英文第三版)。相較之前的版本,第三版有巨大的改進,並且多虧了其作者的慷慨,這本書在網上可以免費獲得。考慮到分布式系統是一個迅速變化的領域,沒有教材可以完全作為路標指引,不過就我們所見,這本書是基礎紮實的最佳總覽。

不管選擇怎樣的教材或者其他輔助資料,學習分布式系統必然要求閱讀論文。這裡有一個不錯的論文清單.

(工作中會遇到,安排上)

四、常見問題解答

4.1 人工智慧/計算機圖形學/XX主題怎麼樣?

我們試圖把計算機科學主題清單限制到那些我們認為每一個軟體工程師都應該了解的內容,不限於專業或行業。擁有了這些基礎,你將能更加輕鬆地挑選教材或論文,然而無需指引地學習核心概念。在這裡,我們給出一些其他常見主題的自學起點:

  • 人工智慧:通過觀看視頻並完成Pacman項目來學習 Berkeley 的 AI 課程。至於教材,使用 Russell 和 Norvig 編寫的 《人工智慧:一種現代方法》
  • 機器學習:學習吳恩達在 Coursera 上的課程。耐心學習,先確保理解了基礎概念再奔向類如深度學習的誘人新主題。
  • 計算機圖形學:學習 Berkeley CS 184 課程的材料,使用《計算機圖形學:原理及實踐》作為教材。

4.2 一定要嚴格遵守推薦的學習次序嗎?

事實上,所有主題之間都有一定程度的重疊,彼此循環引用。以離散數學和算法的關係為例:先學習數學可以幫助你更深入地分析和理解算法,然而先學習算法可以為學習離散數學提供更大的動力和應用背景。理想情況下,你將在你的職業生涯多次重溫二者。

因此,我們所推薦的次序主要是為了幫助你起步……如果你出於某種強烈的原因而傾向以不同的順序學習,那也沒有關係,勇敢開始吧!不過在我們看來,最重要的「先決條件」是:先學計算機架構再學作業系統或資料庫,先學計算機網絡和作業系統再學分布式系統。

4.3 這份指引的目標受眾是?

我們面向自學的軟體工程師、培訓班學生、「早熟的」高中生或者想要通過自學補充正式教育的大學生。關於何時開啟這段自學旅程,完全取決於個人,不過多數人在有一定的職業經歷後深入學習計算機科學理論會獲益匪淺。比如:我們注意到,如果學生在工作中曾經使用過資料庫,他們會喜愛學習資料庫系統課程;如果學生從事過一兩個 Web 項目,他們會喜愛學習計算機網絡。

4.4 XX 程式語言怎麼樣?

學習一門特定的程式語言和學習計算機科學的一個領域完全不在一個維度——相比之下,學習語言容易缺乏價值。如果你已經了解了一些語言,我們強烈建議遵照我們的指引,然後在學習的空當中習得語言,或者暫且不管以後再說。如果你已經把編程學得不錯了(比如學完了《電腦程式的構造和解釋》),尤其是如果你學習過編譯器,那麼面對一門新的語言,你只需要花一個周末稍多的時間即可基本掌握。

4.5 XX 流行技術怎麼樣?

沒有任何一種技術的重要程度可以達到學習其使用足以成為計算機科學教學的核心部分。不過,你對學習那門技術充滿熱情,這很不錯。訣竅是先從特定的技術回退到基本的領域或概念,判斷這門流行技術在技術的宏觀大局中位於何處,然後才深入學習這門技術。

五、最後

鳴謝本文的原作者:Ozan Onay 和 Myles Byrne,譯者:keithnull

以上就是本文推薦的書單了,20 年的讀書計劃可以安排起來了。本片文章不是一篇廣告,買書的方式請自行尋找,說到廣告那就去 HG 的群里潛水吧。各大有電商平台減價的時候,群里會有積極的小夥伴通知大家的,畢竟技術書籍都不便宜,大家都盯著呢。

最後,《代碼大全》中有一句話我很喜歡:

「作為一個初學者或者進階者,這並沒有什麼錯。當一個有能力的程式設計師而不是領導者,這也沒有什麼錯。真正的錯誤是,當你知道應該如何去提高時仍然選擇做一名初學者。」

希望上面的書單能夠為你點亮成為:真·程式設計師的前進之路。

快餐知識能夠速成,能夠快速感受到實現的快感,同樣的門檻也是比較低的。真正的技術是有一定門檻的,同時需要付出成倍的時間,一定要沉下心耐住寂寞。

你選擇吃頓快餐,還是談一場刻骨銘心的戀愛?


關鍵字: