十年學會編程

簡評:本文作者 Peter Norvig,人工智慧專家,現任職 Google 研發部總監,之前就職於 NASA。 本文寫於 1998 年,經典的東西永不過時。

推薦各位認真讀一下,字裡行間透露著踏實感,和現在的浮躁之風一比,絕對的清流。

為何人人都這麼著急?

信步走進任何一家書店,你會看到名為《如何在 7 天內學會 Java》的書,還有各種各樣類似的書:在幾天內或幾小時內學會 Visual Basic, Windows, Internet 等等,一眼望不到盡頭。我在 Amazon 上做了如下的檢索 :

pubdate: after 1992 and title: days and (title: learn or title: teach yourself)

得到了 248 個結果。前 78 個都是計算機類書籍(第 79 個是「30 天學會孟加拉語」 Learn Bengali in 30 days)。我用「hours」替換「days」,得到了類似的結果: 更多的 253 書。前 77 本是計算機類書籍,第 78 本是「24 小時內自學語法和風格」Teach Yourself Grammar and Style in 24 Hours在前 200 本書中,有 96% 是計算機類書籍。

結論是:要麼人們都在急急忙忙地學習計算機,要麼計算機比其它任何東西都容易學。沒有書籍教你在幾天內學會古典音樂、量子物理,或者是養狗。

讓我們分析一下,象一本名為《三天內學會 Pascal》的書意味著什麼:

  • 學習: 在三天里,你沒有時間寫一些重大的程序,並從成功或失敗中有所收穫。你沒有時間與有經驗的程序員合作,並理解在那樣的環境下工作是怎麼回 事。一句話,你不會有時間學到太多東西。因此他們只能談論一些膚淺的東西,而不是深入的理解。正如亞力山大教皇所說,淺嘗輒止是危險的事情。
  • Pascal: 在三天時間裡,你可能學會 Pascal 的語法(如果你已經學過類似的語言),但你學不到更多的如何使用這些語法的知識。也就是說, 假如你曾是個 BASIC 程序員,你可以學著用 Pascal 語法寫出 BASIC 風格的程序,但你不可能了解 Pascal 真正的好處(和壞處)。那麼關鍵是什麼? Alan Perlis 說過:「一種不改變你編程的思維方式的語言,不值得去學。」 一種可能的情況是:你必須學一點兒 Pascal (或可能性更大的象Visual Basic 或 JavaScript之類),因為你為了完成某種特定的任務,需要與一個現存的工具建立介面。不過那不是學習如何編程,而是在學習如何完成那個任務。
  • 三天內: 很不幸,這不夠,原因由下一節告訴我們。

在十年里學會編程

研究表明 (Hayes,Bloom)在任何一種領域內,象下棋、作曲、繪畫、鋼琴演奏、游泳、網球、以及原子物理學和拓撲學,等等,要達到專家水平大約都要化十年時間。沒有真正的捷徑:即使是莫扎 特,4 歲時就是音樂神童,13 年後才開始寫出世界級的作品。在另一方面,披頭士似乎在 1964 年的 Ed Sullivan 表演上一炮走紅。但他們從 1957 年就開始表演,在獲得大眾青睞後,他們的第一個重大成功,Sgt. Peppers,是 1967 年發 行的。Samuel Johnson (塞繆爾·約翰遜,英國辭典編纂家及作家)認為要花比十年更長的時間:「在任何領域中出類拔萃都 要用畢生的勞作來取得;它不可能用較低的代價獲得。」而 Chaucer(喬叟,英國詩人)感嘆到:「人生短暫,學海無涯。」

這是我為編程成功開出的方子:

  • 設法對編程感興趣,並且因為它有趣而編一些程序。確保編程一直充滿足夠樂趣,這樣你才願意投入十年寶貴時間。
  • 與其他程序員交流閱讀其它程序。這比任何書本或訓練課程都重要。
  • 寫程序。 最好的學習方式是從實踐中學習。 用更技術性的話說,「在一個給定的領域內,個人的最大能力不是自動地由擴展了的經驗取得的,但即使是高度有經驗的人也可以通過有意識的努力來提高自己的能力」 (p. 366) 和 「最有效的學習需要因人而異的適當難度,目標明確的任務,豐富的信息反饋,以及重複的機會和錯誤修正。」 (p. 20-21) 此書 Cognition in Practice: Mind,Mathematics,and Culture in Everyday Life 是闡明此觀點的令人感興趣的參考文獻。
  • 如果願意,在大學裡呆上 4 年或更長(在研究生院里)。你會接觸到一些需要學歷證明的工作,你會對此領域有更深的理解。如果你不喜歡學校, 你可以(通過一 些貢獻)在工作中獲得相似的經驗。在任何情況下,光啃書本是不夠的。Eric Raymond,The New Hackers Dictionary 一書的作者,說過,「計算機科學不能把任何人變成編程專家,就象光研究刷子和顏料不會使人變成畫家一樣。」我僱傭過的最好的程序員之一僅有高中程度;他做出了許多優秀的軟體,有他自己的新聞組, 而且通過股票期權,他無疑比我富有的多。
  • 和其他程序員一起做項目。在其中的一些項目中作為最好的程序員; 而在另一些項目中是最差的。當你是最好的,你能測試領導項目的能力,用你的觀點激發別人。當你是最差的,你學習傑出者是怎麼做的,了解他們不喜歡做 什麼(因為他們吩咐你做事)。
  • 在其他程序員之後接手項目。使自己理解別人寫的程序。 當程序的原作者不在的時候,研究什麼需要理解並且修改它。思考如何設計你的程序以便後來者的維護。
  • 學習至少半打的編程語言。包括一種支持類抽象的語言(象 Java 或 C++),一種支持函數化抽象的語言(象 Lisp 或 ML),一種支持語法抽象的語 言(象 Lisp),一種支持聲明規格說明的語言(象 Prolog 或 C++ 的模板),一種支持共行程序(coroutine)的語言(象 Icon 或 Scheme),一種支持並行的語言(象 Sisal)。
  • 請記住「計算機科學」中有「計算機」一詞。了解你的計算機要花多長時間執行一條指令,從內存中取一個字(有cache),從磁碟中讀取連續的字, 和在磁碟中找到新的位置。(答案)
  • 參與一種語言標準化的工作。它可以是 ANSI C++ 委員會, 也可以是決定你周圍小範圍內的編程風格是應該兩個還是四個空格縮進。通過任何一種方式,你了解到其他人在某種語言中的想法,他們的理解深度,甚至一 些他們這樣想的原因。
  • 找到適當的理由儘快地從語言標準化的努力中脫身。

明白了這些,僅從書本中你能得到多少就成了一個問題。在我第一個孩子出生前, 我讀了所有的(關於育兒的)How to 書籍,仍然感覺是個手足無措的新手。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 PC 的各種操作要花的時間:

  • 執行一條指令1 nsec = (1/1,000,000,000) sec
  • 從L1 cache memory 中取一個字2 nsec從內存中取一個字10 nsec
  • 從磁碟的連續位置取一個字200 nsec
  • 從磁碟的新位置取一個字(seek)8,000,000nsec = 8msec

附錄:語言的選擇

不少人問我,他們首先該學哪種編程語言。沒有絕對的答案,不過請考慮以下幾 點:

  • 用你的朋友的。當被問起「我該用哪種操作系統,Windows,Unix, 還是Mac?」,我總是回答:「你朋友用什麼,你就用什麼。」你從朋友那能學 到知識,這種優勢可以抵銷不同操作系統或語言之間本質的差異。也考慮你將來 的朋友:程序員社區 — 你將成為它的一部分如果你繼續往前走的話。你選擇的 語言是否有一個成長中的社區,還是人數不多、即將消亡? 有沒有書籍、網站、 在線論壇回答你的問題? 你喜歡論壇里的那些人嗎?
  • Keep it simple, stupid. 象C++和Java這樣的語言是為經驗豐富的 程序員組成的團隊進行專業開發而設計的,他們專註於代碼運行時的效率。因此, 這些語言有些部分非常複雜。 而你關注的是如何編程,不需要那些複雜性。你 需要的是這樣的語言: 對單個的編程新手來說,它易學易記。
  • 練習。你偏愛哪種學彈鋼琴的方式:通常的互動式的方式,你一 按下琴鍵就能聽到音符;還是「批量」模式,你只有彈完整首曲子才能聽到音符? 顯然,用交互模式學習彈鋼琴更容易些,編程也一樣。堅持用交互模式學習並使 用一種語言。

有了上面的準則,我推薦的第一個編程語言是 Python 或 Scheme。因人而異,還有其它好的選擇。如果你的年紀是 10 歲以下,你可能更喜歡 Alice。關鍵是你要選擇並開始實踐。

附錄:書籍和其它資源

不少人問我,他們該從什麼書籍或網頁開始學起。我重申「僅從書本里學習是不夠的。」 但我還是推薦:

  • 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的語言,不太知名,卻可以作為學習其它語言的基礎。

原文:Peter Norvig(Copyright 2001)

中文版:Dai Yuwen


園長:總結一下

  • 書店裡各種的編程書籍,因為計算機火(1998 如此,現在也是如此);
  • 一種編程語言能夠改變你的思維方式,那就值得學;
  • 對編程有興趣是第一誘因;
  • 看再多書也不如實踐來的真切;
  • 推薦的第一個編程語言是 Python 或者 Scheme(10 歲以下可以學 Alice);
  • 踏實一點。

極光日報,極光開發者旗下媒體。

每天導讀三篇英文技術文章。


推薦閱讀:

從零開始手敲次世代遊戲引擎(四十三)
我不敢休息,因為我沒有存款!(感人至深)
A Discipline of Programming 筆記,1-4章
跨平台通用賬號系統設計規則是什麼?

TAG:編程 | 軟體開發 | 互聯網 |