自學計算機科學

https://github.com/keithnull/TeachYourselfCS-CN/blob/master/TeachYourselfCS-CN.md

本文檔是對TeachYourselfCS內容的中文翻譯,原作者爲Ozan OnayMyles Byrne。如需瞭解翻譯相關信息或幫助改進翻譯,請參見本文檔結尾

This document is a Chinese translation of TeachYourselfCS, which is written by Ozan Onay and Myles Byrne. For more information about this translation, please refer to the end of this document.

如果你是一個自學成才的工程師,或者從編程培訓班畢業,那麼你很有必要學習計算機科學。幸運的是,不必爲此花上數年光陰和不菲費用去攻讀一個學位:僅僅依靠自己,你就可以獲得世界一流水平的教育💸。

互聯網上,到處都有許多的學習資源,然而精華與糟粕並存。你所需要的,不是一個諸如“200+免費在線課程”的清單,而是以下問題的答案:

  • 你應當學習哪些科目,爲什麼?
  • 對於這些科目,最好的書籍或者視頻課程是什麼?

在這份指引中,我們嘗試對這些問題做出確定的回答。

簡而言之

大致按照列出的順序,藉助我們所建議的教材或者視頻課程(但是最好二者兼用),學習如下的九門科目。目標是先花100到200個小時學習完每一個科目,然後在你職業生涯中,不時溫習其中的精髓🚀。

科目 爲何要學? 最佳書籍 最佳視頻
編程 不要做一個“永遠沒徹底搞懂”諸如遞歸等概念的程序員。 《計算機程序的構造和解釋》 Brian Harvey’s Berkeley CS 61A
計算機架構 如果你對於計算機如何工作沒有具體的概念,那麼你所做出的所有高級抽象都是空中樓閣。 《計算機組成與設計》 Berkeley CS 61C
算法與數據結構 如果你不懂得如何使用棧、隊列、樹、圖等常見數據結構,遇到有難度的問題時,你將束手無策。 《算法設計手冊》 Steven Skiena’s lectures
數學知識 計算機科學基本上是應用數學的一個“失控的”分支,因此學習數學將會給你帶來競爭優勢。 《計算機科學中的數學》 Tom Leighton’s MIT 6.042J
操作系統 你所寫的代碼,基本上都由操作系統來運行,因此你應當瞭解其運作的原理。 《操作系統導論》 Berkeley CS 162
計算機網絡 互聯網已然勢不可擋:理解工作原理才能解鎖全部潛力。 《計算機網絡:自頂向下方法》 Stanford CS 144
數據庫 對於多數重要程序,數據是其核心,然而很少人理解數據庫系統的工作原理。 《Readings in Database Systems》 (暫無中譯本) Joe Hellerstein’s Berkeley CS 186
編程語言與編譯器 若你懂得編程語言和編譯器如何工作,你就能寫出更好的代碼,更輕鬆地學習新的編程語言。 《編譯原理》 Alex Aiken’s course on Lagunita
分佈式系統 如今,多數 系統都是分佈式的。 《分佈式系統原理與範型》(中文第二版英文第三版 🤷‍

爲什麼要學習計算機科學?

軟件工程師分爲兩種:一種充分理解了計算機科學,從而有能力應對充滿挑戰的創造性工作;另一種僅僅憑着對一些高級工具的熟悉而勉強應付。

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

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

— Benedict Evans (@BenedictEvans) 2016年2月2日

第一種工程師總是尋求深入學習計算機科學的方法,或是通過傳統的方法學習,或是在職業生涯中永無止息地學習;第二種工程師 通常浮於表面,只學習某些特定的工具和技術,而不研究其底層的基本原理,僅僅在技術潮流的風向改變時學習新的技能。

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

23333 然而他們... pic.twitter.com/XVNYlXAHar

— Jenna Bilotta (@jenna) 2017年3月4日

分科目指引

編程

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

對於這部分內容,我們的標準推薦是這部經典著作:《計算機程序的構造和解釋》。在網絡上,這本書既可供免費閱讀(英文版),也作爲MIT的免費視頻課程。不過儘管這些視頻課程很不錯,我們對於視頻課程的推薦實際上是Brian Harvey 開設的 SICP 課程(即 Berkeley 的 61A 課程)。比起MIT的課程,它更加完善,更適用於初學者。

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

如果你覺得SICP過於難,那我們推薦 《程序設計方法》(中文版英文版 ;如果你覺得SICP過於簡單,那我們推薦 《Concepts, Techniques, and Models of Computer Programming》 。

計算機程序的構造和解釋

計算機架構

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

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

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

這本書的前半部分(包括所有對應的項目)均可從Nand2Tetris的網站上免費獲得。同時,在Coursera上,這是一門視頻課程

爲了追求簡潔和緊湊,這本書犧牲了內容上的深度。尤其值得注意的是,流水線和存儲層次結構是現代計算機架構中極其重要的兩個概念,然而這本書對此幾乎毫無涉及。

當你掌握了Nand2Tetris的內容後,我們接下來推薦Patterson和Hennessy二人所著的 《計算機組成與設計》,一本優秀的經典著作。這本書中的不同章節重要程度不一,因此我們建議根據Berkeley的CS61C課程 “計算機架構中的偉大思想”來着重閱讀一些章節。這門課的筆記和實驗在網絡上可以免費獲得,並且在互聯網檔案中有這門課程的過往資料。

計算機系統要素 計算機組成與設計

硬件是平臺。

— Mike Acton, Engine Director at Insomniac Games (觀看他在CppCon上的演說)

算法與數據結構

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

關於算法與數據結構,有成百上千的書可供使用,但是我們的最愛是Steven Skiena編寫的 《算法設計手冊》。顯而易見,他對此充滿熱愛,迫不及待地想要幫助其他人理解。在我們看來,這本書給人一種煥然一新的體驗,完全不同於那些更加經常被推薦的書(比如Cormen,Leiserson,Rivest 和 Stein,或者 Sedgewick的書,後兩者充斥着過多的證明,不適合以 解決問題 爲導向的學習)。

如果你更喜歡視頻課程,Skiena慷慨地提供了他的課程。此外,Tim Roughgarden的課程也很不錯, 在Stanford的MOOC平臺Lagunita,或者Coursera上均可獲得。Skiena和Roughgarden的這兩門課程沒有優劣之分,選擇何者取決於個人品味。

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

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

算法設計手冊 怎樣解題

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

— Richard Hamming

數學知識

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

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

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

對於更加高階的學習,我們推薦 《計算機科學中的數學》,MIT同名課程的課程筆記,篇幅與書籍相當(事實上,現已出版)。這門課程的視頻同樣可免費獲得,是我們所推薦的學習視頻。

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

計算機科學中的數學

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

— John von Neumann

操作系統

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

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

在讀完《操作系統導論》後,我們鼓勵你探索特定操作系統的設計。可以藉助“{OS name} Internals”風格的書籍,比如 Lion's commentary on Unix, The Design and Implementation of the FreeBSD Operating System,以及 Mac OS X Internals

爲了鞏固對操作系統的理解,閱讀小型系統內核的代碼並且爲其增加特性是一個很不錯的方法。比如,xv6,由MIT的一門課程所維護的從Unix V6到ANSI C和x86的移植,就是一個很棒的選擇。《操作系統導論》有一個附錄,記載了一些可能的xv6實驗項目,其中充滿了關於潛在項目的很棒想法。

操作系統導論

計算機網絡

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

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

如果更喜歡視頻課程,我們推薦Stanford的Introduction to Computer Networking,可在他們的MOOC平臺Lagunita上免費觀看。

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

《計算機網絡:自頂向下方法》

你無法盯着水晶球預見未來,未來的互聯網何去何從取決於社會。

— Bob Kahn

數據庫

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

鑑於如上情況,我們鼓勵自學者大體上拋棄教材,而是從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所著的 《數據庫管理系統:原理與設計》。如需更深一步,Jim Gray的經典著作 《Transaction Processing: Concepts and Techniques》 值得一讀,不過我們不建議把這本書當作首要資源。

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

最後,數據模型往往是數據庫中一個被忽視的、教學不充分的方面。關於這個主題,我們推薦的書籍是 Data and Reality: A Timeless Perspective on Perceiving and Managing Information in Our Imprecise World

Readings in Database Systems 數據庫管理系統:原理與設計

編程語言與編譯器

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

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

如果你選擇使用龍書進行自學,我們建議依據某個視頻課程來設定學習的結構,然後按需從龍書中獲取深入的內容。我們推薦的在線課程是Alex Aiken在Stanford的MOOC平臺Lagunita所開設的

我們所推薦的龍書替代品是Terence Parr所著的 《編程語言實現模式》。這本書更加直接地面向那些想要着手於諸如DSL的小型編程語言項目的軟件工程師,因此從你的角度來看可能會更加實用。當然,這樣做犧牲了一些有價值的理論內容。

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

編譯原理編程語言實現模式

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

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

分佈式系統

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

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

MIT的6.824(研究生課程)是一門在網絡有部分視頻的優秀課程,不過不幸的是,錄像中的聲音質量很差,並且不確定這些錄像是否經過許可。

不管選擇怎樣的教材或者其他輔助資料,學習分佈式系統必然要求閱讀論文。這裏有一個不錯的論文清單,而且我們強烈建議你出席你當地的Papers We Love(僅限美國)。

分佈式系統原理與範型

常見問題解答

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

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

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

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

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

這份指引的目標受衆是?

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

和Open Source Society、freeCodeCamp curricula等比起來,這份指引?

OSS指引涵蓋太多主題,在許多主題中推薦劣質資源,沒有就特定課程哪些方面有價值提供原因或指引。我們努力對這份指引中的課程加以限制,僅僅包括那些你作爲軟件工程師 確實需要了解的,不論你的專業方向,並且對每門課程爲何必要做出瞭解釋以幫助你理解。

FreeCodeCamp主要關注編程,而不是計算機科學。至於你爲什麼要學習計算機科學,參見上文

XX編程語言怎麼樣?

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

XX流行技術怎麼樣?

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

爲什麼你們還在推薦龍書?

龍書依舊是內容最爲完整的編譯器單本書籍。由於過分強調一些如今不夠時新的主題的細節,比如解析,這本書招致了惡評。然而事實上,這本書從未打算供人一頁一頁的學習,而僅僅是爲了給教師準備一門課程提供足夠的材料。類似地,自學者可以從書中量身按需挑選主題,或者最好依照公開課授課教師在課程大綱中的建議。

如何便宜獲取教材?

我們所建議的許多教材在網上都可以免費獲得,這多虧了作者們的慷慨。對於那些不免費的書籍,我們建議購買舊版本的二手書籍。廣而言之,如果一本教材有多個版本,舊版本大概率是完全足夠使用的。即便新版本的價格是舊版本的10倍,新版本也絕不可能比舊版本好10倍!

中文翻譯新增: 事實上,比起美國,在國內購買技術書籍可以說是相當“廉價”了。如果仍舊尋求更加便宜的購買渠道,可以參考這篇V2EX上的討論帖子,其中提到了一些不錯的購買渠道。

這份指引是誰寫的?

這份指引由Bradfield School of Computer Science(舊金山)的兩位教員:Ozan OnayMyles Byrne編寫。這份指引基於我們對數百名自學成才的工程師和培訓班學生教授計算機科學基礎的經驗。感謝我們所有學生對自學資源的持續反饋。同樣感謝Alek Sharma,Omar Rayward,Ammar Mian和Tyler Bettilyon對這份指引的反饋。

這份指引是誰翻譯的?

這份指引的中文翻譯是社區共同貢獻的成果,我們歡迎任何反饋和改進!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章