十年學會程序設計
這里分享一篇 Peter Norvig的 《十年學會程序設計》 (Peter Norvig 系Google研究院主任、美國計算機協會(ACM)資深會員(Fellow))。全文如下:
十年學會程序設計
為何大家如此匆忙?
走進任何一家書店,你會看到書架上一排不見盡頭的放著如 <7天自學Java語言> 以及幾天或者幾小時學會Windows,因特網或者Visual Basic 這類書。我在Amazon 網上書店用一下的方式進行高級搜索:
出版年份: 1992以后 書名包括:“天” 和 “學習” 或 “自學”
得到了268條搜索結果,其中前78條都是計算機書(第79條是 30天學會孟加拉語)。 我用 “小時” 代替“天” 作為關鍵字,得到了神奇般類似的結果:這次有253本書,前77本是計算機書, 第78本是 24小時自學語法和寫作風格。排名前200的書中有96%是計算機書。
由此可見,人們要不就是急著想學會計算機,要不就是計算機相比于其他事情太容易學會了。比如說把,沒有書是寫在幾天彈奏貝多芬或幾天學會量子物理,甚至也沒有幾天學會幫小狗打扮這樣的書。
讓我們分析一下 三天學會Pascal語言 [英文網頁] 這樣的標題表達了什么意思:
- 學會:在三天內,你沒有時間去寫幾個有意義的程序,或者從成功和失敗中學到東西。你也沒時間跟有經驗的程序員一起工作,所以也無法了解在真正編程是什么樣子。簡短的說,就學會而言,時間顯然不夠。所以這些書只是浮于表面的熟悉,而不是深刻的理解。如同Alexander Pope 所說,一知半解是危險的。
- Pascal 語言:三天內你可能學會Pasacl語言的語法(如果你已經掌握一個類似的編程語言),但你無法學會如何合理運用這些語法。簡言之,如果你是個Basic 程序員,你可以用Pascal 語言寫出類似Basic風格的程序,但你學不到Pascal語言的優點(還有缺點)到底在哪。重點是什么呢? Alan Perlis 曾說: “如果編程語言不能影響你的編程思維,那就不值得去學.” 另一個可能是,你必須學會一點點Pascal語言(或是像VB語言、Javascript等),因為你需要跟現成的工具組合完成特定的工作。不過這個時候,你實際上學的不是怎么寫程序,而是要學著如何完成工作。
- 三天:不幸的是三天根本不夠;下面的章節會告訴你為什么
十年學會程序設計
研究者 Hayes, Bloom 的研究表明,在幾乎所有的各種領域,大約要十年才能培養出專業技能。這些領域包括下西洋棋、音樂作曲、繪畫、鋼琴、游泳、網球,及神經心理學和數學拓撲學。似乎沒有真正的捷徑--即便是莫扎特在四歲就展露出音樂天才,在他寫出世界級的音樂之前仍然用了超過十三年的時間。
再看另一種類型的領域。披頭士樂團似乎是在1964年的Ed Sullivan 劇場表演突然地火起來并成為第一樂隊的。但其實他們從 1957 年開始,就在利物浦、漢堡等地的小型俱樂部表演。雖然他們很早就顯現強大的吸引力,但他們決定性的成功作品 Sgt Pepper 也到1967年才發行。Samuel Johnson 則認為或許還不止十年才行,他說:任何領域的卓越成就都必須用一生的努力才能取得;稍微低一點的代價都是換不到的。Chaucer 則感嘆道: “生命如此短促,學習技藝卻要這么地長。”
以下是我在編程上成功的秘訣:
- 對編程產生感興趣并因為樂趣而寫程序。確信你自始至終都能樂在其中,這樣你才愿意將十年光陰投入編程事業。
- 與其他程序員交流;閱讀別人的代碼。這比任何書任何培訓都重要。
- 不斷地編寫。最好的學習方法是在實踐中學習。從技術角度說,“在特定領域的個人最高效率并不因為經驗夠多就會自動獲得;但若有意識的通過努力去提升經驗,個人效率會變高”(第336頁)而 “高效的學習一般需要明確的任務和因人而異的適當難度,以及及時的反饋和重復或者修正錯誤的機會”(20~21頁)Cognition in Practice: Mind, Mathematics, and Culture in Everyday Life (實踐中認知:心智、數學與日常文化) 是這個觀點的一本有趣參考書籍。
- 如果你愿意,你可以去讀四年大學(或再讀研究生)。這可以讓你滿足一些工作的學歷要求,同時也可讓你對這個領域有更深的認識。但如你不喜歡上學,你也能(得有犧牲)通過工作獲得類似的經驗。無論如何,只讀書是不夠的。《New Hacker’s Dictionary》的作者Eric Raymond 曾經說過:“計算機的教育無法讓人成為編程的專家,正如研究畫筆與顏料不能讓人成為專業畫家一樣。” 一個在我所有招聘過的人中屬于最優秀之一的程序員只有高中畢業,但他寫出很多很棒的程序,他甚至有自己的新聞組。他獲得的股票期權使得他可以擁有自己的午夜酒吧。
- 跟其他程序員一起完成項目。在一些項目中成為最好的程序員;在一些中則充當最差的一個。當你是最佳的,你要測試自己領導項目的能力,并以你的能力鼓勵他人。當你是最差的,要看看高手做些什么,他們不喜歡做什么 (因為他們會叫你去幫他們做)。
- 接手別的程序員完成項目。全心投入并理解別人的程序。當原作者不在的時候,看看在理解與修改時有什么要注意的。想想如何設計你的程序使得后來維護的人容易上手。
- 至少學會六門編程語言。一種要支持類/對象(class abstractions)的語言,如Java或C++;一種函數式(functional abstraction)語言,如 LISP 或 ML;一種支持語法抽象(syntactic abstraction) 的語言如 LISP;一種聲明式語言, 如Prolog或 C++模版;一種支持協同式(coroutines)編程,如 Icon 或 Scheme;還有一種支持并行(parallelism)的語言,如 Sisal。
- 記住在“計算機科學” 中包括”計算機” 這個詞。要知道你的計算機執行一條指令需要多久,到內存中取一個字需要多久(緩存是否擊中),到磁盤讀取連續的字需要多久,而磁盤的定位又需要多久。(解答見文末)
- 進行語言標準化的工作。可以像是由ANSI C++ 委員會,或由你自己的團隊,來決定你們的編碼風格,譬如說縮排是2或4個空格。不管怎樣,你都能學到別人到底喜歡什么,對語言的感受有多深,甚至能了解到一點他們為什么有這樣的感覺。
- 并具備良好的判斷力,也別老糾纏在語言標準化上。
談了上面所有的想法后,我不禁要問究竟能從書上學到多少。在第一個孩子出生前,我讀完了所有的 “怎樣…” 的書,仍覺得自己是個一無所知的(照顧孩子的)菜鳥。30個月后,第二個孩子出世,我要重回這些書好好復習么? 不!取而代之的是,我開始相信自己的個人經驗。這些難得的經驗,比專家寫的幾千頁手冊還要有用,而且讓我重新找到了自信。
Fred Brooks (譯注: <人月神話>作者) 在他的文章 沒有銀彈 中指出,發掘卓越軟體設計者的三部曲:
1. 盡早盡可能地以系統化的方式發掘最佳設計人員。
2. 給有潛力者指派生涯規劃師,并謹慎地規劃他們的職業生涯。
3. 提供機會給正在成長的程序員,讓他們能相互影響,彼此激勵。
這里假定了某些人已具備成為卓越設計師的必要潛能;工作只是誘導他們前進。Alan Perlis 說得更簡潔了,你可以教任何人學雕塑,但對米開朗基羅而言,要教他的反倒是有哪些事不要做,卓越的程序員也一樣。
所以,盡管買那些 Java 書吧!你或許能從中找到點有用的,但是在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.
· Hayes, John R., Complete Problem Solver Lawrence Erlbaum, 1989.
· Lave, Jean, Cognition in Practice: Mind, Mathematics, and Culture in Everyday Life, Cambridge University Press, 1988.
________________________________
解答:
各種操作的時間,以2001年夏季,典型配置的 1GHz 個人計算機為標準:
執行單一指令 | 1 納秒 |
從L1 高速緩存取一個字 | 2 納秒 |
從內存取一個字 | 10 納秒 |
從磁盤取連續存放的一個字 | 200 納秒 |
磁盤尋址并取字 | 8 毫秒 |
________________________________
附錄 I: 語言的選擇
好幾個人問過我一開始應該先學哪個計算機編程語言,這個問題沒有唯一的答案,不過選擇的時候可以從以下的幾個方面考慮:
- 朋友在用的。當人們問我:”我該用什么操作系統的時候”, 我通常的回答是:“用你朋友用的”。這樣的好處是從朋友那兒學習可以彌補復雜的操作系統差異或者編程語言差異(給你造成的困惑)。這里也要考慮你未來的朋友:如果你一直使用的話,開發社區會是你的朋友。你選擇了一個具有有巨大的增長的開發社區還是一個小的快消失的開發社區的語言?它有相關的書,網站和論壇可以獲取解答么? 你喜歡那些論壇上的人么?
- 保持簡單。諸如C++和Java 是為那些關心代碼執行效率的有經驗的大型團隊的開發人員設計的。因此這些語言中有些為這些特殊場合設計的部件。你只是關心編程而不需要關心復雜情況。你需要一個為新學編程的人設計的容易學習和理解的語言。
- 實踐。什么是學習鋼琴的好方法呢?是一邊聽音一邊彈奏的“交互式” 的方法呢,還是全聽完整首歌然后再彈奏的那種“批處理”方式呢?很顯然,交互學習的方式能夠讓學鋼琴變得簡單–這也適用于編程。選取一種交互式的編程語言并且堅持使用。
基于以上的這些標準,我對于第一次接觸編程的人推薦 Python 或 Scheme。但是情況各有不同,或許也有其他的選擇。如果你不滿10歲,你可能會喜歡Alice或者Squeak(年齡大的人或許也喜歡這些)。重要的是在選擇后, 立即開始學習和使用。
附錄II:書和其他資源
很多人問我該從什么書或者什么網頁開始看起。我重申一句:“僅僅看書是不夠的”,不過我也推薦一下的一些:
- Scheme: 計算機程序的結構和釋義 (Abelson & Sussman) 可能是計算機科學最好的導論了,他還告訴程序員怎么理解計算機科學,你可以訪問這本書的 在線視頻講座 和 全文在線。這本書也很有挑戰性,可能會排除掉一些可能在其他領域成功的人。
- Scheme: 怎樣設計程序(Felleisen 等) 是講解怎樣設計優雅的函數式語言的最好的書之一。
- Python: Python 編程,面向計算機科學的導論 (Zelle) 是用Python 介紹計算機科學的好書。
- Python: 一些關于Python 的 入門教程 可以在 Python.org 上找到。
- Oz: 計算機編程的概念,技術和模型(Van Roy & Haridi) 可以視為第一本書的現代版. 他是關于編程的一些總攬,包含了比第一本書更加廣泛也更加容易閱讀和理解的領域。這本書使用了一個不太為人所知的編程語言叫 Oz,不過這個可以作為學習其他編程語言的一個基礎。
注: T. Capey 指出,在Amazon 的“問題徹底解決者”的頁面上購買了這本書的人還買了:《21天學孟加拉語》 和 《自學語法和寫作風格》這兩本書,我估計大部分是我這個頁面帶過去的用戶。
Eric You XU 翻譯,2007年4月