程序員必讀經典長文:用十年時間自學編程
相信很多做技術的同學都自學過,也看過“Teach Yourself Programming in Ten Years”這篇文章。雖然離初次發表已經好幾年了,但所有試圖自學編程的人都應該發自內心的同意它的說法(除去少數過時的具體技術部分)。直到今天,這篇經典的文章依然很有借鑒意義。以下是這篇文章的中文版。
為什麼每個人都這麼匆忙?
走進任何書店,你都會看到如何在24 小時內自學Java,同時你還可以看到很多在幾天或幾小時內學會C、SQL、Ruby、算法等等的書籍。在亞馬遜使用“title: teach, yourself, hours, since: 2000”進行高級搜索,我發現了512 本這樣的書。在排在前十名的書籍中,有九本是編程書籍,剩下一本是關於財務管理的。用“teach yourself”代替“learn”,或者用“day”代替“hours”產生的結果類似。
結論是,要么人們急於學習編程,要么編程比其他任何東西都更容易學習。Felleisen 等人在他們的書《How to Design Programs》中提到,“糟糕的編程很容易,即便是白痴都可以在21 天內學會”時,請對這一觀點表示贊同。
讓我們來分析一下在24 小時內學會C++意味著什麼:
- 自學:24小時內,你將沒有時間寫幾個重要的程序,並從成功和失敗中吸取教訓。你將沒有時間和一個有經驗的程序員一起工作,並理解在C++環境中編程會是什麼樣子。簡而言之,你將沒有時間去學習多少東西。所以這本書只能說是膚淺的熟悉,而不是深刻的理解。正如Alexander Pope所說,只學會一點點點東西是危險的
- C++:在24小時內,你也許能夠學習C++的一些語法(前提是你已經知道了另一種語言),但是你不能學到多少關於如何使用這門語言的知識。簡而言之,如果你是一個基層的程序員,你可以學習用C++語法編寫BASIC程序,但是你不能學習到C++真正的優缺點。那又有什麼意義呢?Alan Perlis曾經說過:“一種不影響你編程思維方式的語言,是不值得學習的。”有一種可能是,你必須學習一點C++(或者是JavaScript之類的東西),因為你需要用現有的工具接口來完成特定的任務。但這種情況下,你不是在學習如何編程,而是在學習如何完成這項任務。
- 在24小時內:不幸的是,這根本不夠,正如下面所說的那樣。
用十年時間自學編程
很多研究人員發現,在各種領域要成為專家大約需要十年時間,這些領域包括國際象棋、音樂創作、電報、繪畫、鋼琴演奏、游泳、網球和科學研究、神經心理學和拓撲學等等。成功的關鍵是不斷的實踐:不只是一次又一次地做,而是每次都用一個超出你目前能力的任務挑戰你自己,嘗試去解決它,在做它的同時和之後分析你的表現,糾正錯誤,然後重複這個循環。人和事情都沒有真正的捷徑:即便對莫扎特來說也是如此。4 歲就被稱為音樂天才的他,在開始創作世界級的音樂之前又花了13 年時間來打磨自己。另一個例子是披頭士樂隊。披頭士樂隊似乎以一系列的熱門歌曲和1964 年在艾德沙利文秀上的亮相而一夜成名。但實際上自從1957 年以來,他們一直在Liverpool 和Hamburg 的小酒吧里面演出,雖然很早以前他們就受到大眾的歡迎,但他們第一次取得重大成功的專輯“Sgt. Peppers”是在1967 年發布的。
Malcolm Gladwell 已經普及了這個想法,儘管他的觀點是10000 小時專注的努力,而不是10 年。Henri Cartier-Bresson (1908-2004) 有一句名言:“你的前10000 張照片是你最差的作品。”(他沒有預料到使用數碼相機,有些人可以在一周內就拍完10000 張照片。 )真正成為專家可能需要一輩子:Samuel Johnson(1709-1784)說:“成為任何領域的卓越人士都需要畢生的努力,投機取巧並不可行”。Chaucer (1340-1400) 抱怨說:“人生太短暫了,而知識是無窮的”。Hippocrates (約公元前400 年) 因為那句名言“ars longa, vita brevis”而被人稱頌,這句話的原文是“Ars longa, vita brevis, occasio praeceps, experimentum periculosum, iudicium difficile”,意思是“生命很短暫,但是技藝卻很高深,機遇轉瞬即逝,探索難以捉摸,抉擇困難重重”。
當然,沒有一個數字可以作為最終的答案,假定所有的技能(如編程、下棋、跳棋和音樂演奏)都需要完全相同的時間來掌握,或者所有人都需要完全相同的時間是不合理的。正如K. Anders Ericsson 教授所說,“在大多數領域,即使是最有才華的人也需要很多時間才能達到最高水平,這是非常值得注意的。10000 小時這個數字讓你感覺到,我們說的是一周10 到20 個小時。”
你想成為一名程序員
以下是我的編程秘訣:
- 對編程感興趣,因為興趣而編程。請保持足夠的興趣,以便你願意投入你的10 年或者10000 小時。
- 編碼。最好的學習方式是實踐。更嚴格地說,“在特定領域中,一個人的最高水平不是由於經驗的積累自動獲得的,而是經過深思熟慮的改進,經驗豐富的人也可以提高水平。”,“最有效的學習需要有一個明確的任務,對特定的人來說難度適中,還要有信息反饋以及重複試錯和糾正錯誤的機會。”“Cognition in Practice: Mind, Mathematics, and Culture in Everyday Life”這本書正是這一觀點的有趣參考。
- 與其他程序員交談;閱讀其他程序。這比任何書籍或培訓課程都重要。
- 如果你願意,可以在大學(或研究生院)呆四年。這將使你有機會獲得一份需要證書的工作,讓你對這個領域有更深的了解,但如果你不喜歡學校,你可以自學或在工作中獲得類似的經驗。無論如何,光靠書本知識是遠遠不夠的。“The New Hacker’s Dictionary”的作者Eric Raymond說:“計算機科學教育不能使任何人成為一個專業的程序員,就像學習刷子和顏料不可以使某人成為一個專業的畫家一樣。”我僱用過的最好的程序員之一隻有高中學歷,他開發了許多優秀的軟件,擁有自己的團隊,並且擁有足夠買下一個夜店的股票期權。
- 與其他程序員一起做項目。在某些項目上你是最好的程序員,而在某些項目上你是最差的程序員。當你是最好的時候,你可以鍛煉主導一個項目的能力,並用你的遠見激勵別人。當你是最壞的時候,你可以學習大師們做什麼,觀察他們不喜歡做什麼(因為他們會讓你為他們做自己不喜歡的事情)。
- 接手其他程序員的項目,理解別人寫的程序。當原來的程序員不在時,學習需要怎樣理解和修復程序。想想如何設計你的程序,讓那些在你之後的人維護它們更容易些。
- 學習至少六種編程語言。包括一種強調類抽象的語言(如Java 或C++),它強調函數抽象的語言(如Lisp 或ML 或Haskell),一種支持句法抽象的語言(如Lisp),一種支持聲明性規範的語言(如Prolog 或C++模板),一種強調並發性的語言(像Clojure 或Go)。
- 記住“computer science”中有一個“computer”。知道計算機執行一條指令、從內存中提取一個字符(有或沒有緩存)、從磁盤中讀取連續的字符以及在磁盤上尋找新的位置需要多長時間。
- 參與語言標準化工作。它可能是ANSI C++委員會,也可以是決定你自己的本地編碼風格是有2 個或者4 個空間縮進。無論哪種方式,你都可以了解到其他人對一種語言的喜好,他們的感受有多深,甚至可能了解他們的感受。
- 有很好的判斷力,盡快適應語言的標準化
考慮到這一切,僅僅通過書本學習你能走多遠是個值得懷疑的問題。在我的第一個孩子出生之前,我讀完了所有的“How To”類型的書,但仍然覺得自己像個笨手笨腳的新手。30 個月後,當我的第二個孩子出生時,我重新學習了那些書本知識嗎?不,相反,我依靠的是我的個人經驗,這比專家們寫的幾千頁書更有用,更讓我放心。
Fred Brooks 在他的論文《No Silver Bullet》中指出了尋找優秀軟件設計師的三個步驟:
- 儘早系統地發掘頂級程序員。
- 指派一名職業導師負責指導他,並謹慎對待履歷。
- 為成長中的程序員提供相互交流和互相激勵的機會。
這假設一些人已經具備成為一個偉大的程序師所必需的素質,那麼你的工作就是適當地哄騙他們。Alan Perlis 的說法更加簡潔:“每個人都可以學會雕刻,但Michelangelo 必須學會如何不雕刻。對偉大的程序員來說也是如此。”Perlis 認為,偉人有一些超越訓練的內在品質。但是這些品質是從哪裡來的呢?是先天的嗎?或者他們是通過勤奮養成的?正如Auguste Gusteau 所說:“任何人都能學會做飯,但只有無畏的人才是偉大的。”我認為這更像是願意將一生中大部分時間投入到某種實踐中,但也許無畏是總結這一點的一種方式。或者,正如Gusteau 的批評家Anton Ego 所說:“不是每個人都能成為偉大的藝術家,但偉大的藝術家可以來自任何地方。”
所以繼續購買Java/Ruby /JavaScript /P HP書籍吧,你可能會從中得到一些有用的東西。但是它們不會在24小時或21天內改變你的生活,也不會教會你作為一個程序員所需要的所有專業知識。何不努力工作,在接下來的24個月內不斷改進?
參考書籍
- Bloom, Benjamin (ed.)《Developing Talent in Young People》, Ballantine, 1985.
- Brooks, Fred,《No Silver Bullets》, IEEE Computer, vol. 20, no. 4, 1987, p. 10-19.
- Bryan, WL & Harter, N.《Studies on the telegraphic language: The acquisition of a hierarchy of habits》. Psychology Review, 1899, 8, 345-375
- Hayes, John R.,《Complete Problem Solver》Lawrence Erlbaum, 1989.
- Chase, William G. & Simon, Herbert A.《Perception in Chess》,Cognitive Psychology, 1973, 4, 55-81.
- Lave, Jean,《Cognition in Practice: Mind, Mathematics, and Culture in Everyday Life》, Cambridge University Press, 1988.
前面問題的答案
典型PC 上各種操作所需要的大致時間:
- 執行典型指令:1/100000000 秒,即1 納秒
- 從一級緩存中提取:0.5 納秒
- 分支預測失誤:5 納秒
- 從二級緩存獲取:7 納秒
- 互斥鎖/解鎖:25 納秒
- 從主存儲器提取:100 納秒
- 通過1Gbps 網絡發送2K 字節:20000 納秒
- 從內存中按順序讀取1MB :250000 納秒
- 從新磁盤位置(SEEK)獲取:8000000 納秒
- 從磁盤中按順序讀取1MB:20000000 納秒
- 將數據包發送到歐洲並返回:150 毫秒,即150000000 納秒
附:語言選擇
有人會問,他們應該先學什麼編程語言。這裡沒有標準答案,但請考慮以下幾點:
- 參考你的朋友。當被問到“我應該使用什麼操作系統,Windows、Unix或Mac?”我的回答通常是:“使用你的朋友使用的任何東西。”你從朋友那裡學到的優勢將抵消操作系統或編程語言之間的任何內在差異。還要考慮你未來的朋友:程序員社區的人,如果你繼續的話,你將成為其中的一員。你所選擇的語言有一個大的正在成長的群體還是一個小的正在消亡的群體?有書、網站和在線論壇可以得到答案嗎?你喜歡那些論壇裡的人嗎?
- 簡單實用。諸如C++和Java 這樣的編程語言是由有經驗的程序員團隊設計的,這些程序員關心他們代碼的運行時效率。因此,為了應對這些情況,這些語言有些地方是很複雜的。你關心的是學習編程。你不需要那麼複雜。你需要的是一種語言,它對於新手程序員來說也可以可以很容易地學習和記憶。
- 互動。你更願意用哪種方式學彈鋼琴:普通的,互動的方式,你一按一個鍵就听到一個音符;或者“批量”模式,在這種模式下,你只在完成一整首歌后才聽到音符?顯然,互動模式使鋼琴學習和更容易。對編程來說也是如此,堅持使用互動模式的語言並使用它。
考慮到這些標準,對於要學習的第一種編程語言我的建議是Python或Scheme。另一個選擇是JavaScript,這不是因為它是為初學者精心設計的,而是因為它有很多在線教程,比如Khan Academy的教程。但每個人的情況都略有不同,還有一些其他的好選擇。如果你還是隔小孩,你可能更喜歡Alice或Squeak或Blockly(年長的學習者也可能喜歡這些)。這些都沒關係,重要的是你要選擇並開始。
附錄:書籍和其他資源
有人問他們應該從哪些書和網頁上學習。我再重複一遍:僅僅看書是不夠的。但我可以推薦以下資源:
- Scheme:“Structure and Interpretation of Computer Programs (Abelson & Sussman)”可能是計算機科學最好的導論書籍,它也確實將教授編程作為理解計算機科學的一種方式。你可以在網上看到關於這本書的講座視頻,以及完整的文本。這本書讀起來具有挑戰性,將淘汰一些可能通過這種方法獲得成功的人。
- Scheme:“How to Design Programs (Felleisen et al.)”是關於在實踐中如何以優雅和實用的方式設計程序的最佳書籍之一。
- Python:“Python Programming: An Intro to CS (Zelle)”很好地介紹瞭如何使用Python。
- Python:Python.org 上有一些在線教程。
- Oz:“Concepts, Techniques, and Models of Computer Programming (Van Roy & Haridi)”被一些人視為Abelson 和Sussman 的現代繼承人。讀這本書會讓你理解編程思想,它的涵蓋範圍比Abelson 和Sussman 更廣泛,同時可能更容易閱讀和理解。它使用的語言是Oz,這種語言並不廣為人知,但它卻是學習其他語言的基礎。
備註
T. Capey 指出,Amazon 網頁上那個“Complete Problem Solver”頁面把《Teach Yourself Bengali in 21 days》以及《Teach Yourself Grammar and Style》這兩本書移到了“購買此書的用戶還購買過這些產品”這個區域內。我估計大部分人就是從這個區域看到這本書的。感謝Ross Cohen 的幫助。