Peter Norvig:自學程式設計,十年磨一劍

贊 回覆發表於2012-08-31

| 2012-08-31 08:00   評論: 1 收藏: 6    

  黃小非譯註:本文作者Peter Norvig目前任職於Google,其職位是研究主管(Director of  Research). Peter Norvig是享譽世界的電腦科學家和人工智慧專家。他是 AAAI  和  ACM 的會員,是業界內經典書籍《Artificial Intelligence: A Modern Approach | 人工智慧:一種現代方法》的作者之一。在加入Google之前,他曾經是NASA(美國航空航天局)計算科學部門的主要負責人,並在南加州大學以及伯克利大學任教。以下為譯文。

你們著什麼急?

  隨意步入一家書店,滿目都是《7天搞定Java程式設計》這種速成書目,同樣的書籍還包括Visual Basic、Window系統、Internet網際網路等等,它們都承諾在幾天,甚至幾小時之內就讓你能夠學會相關技術。我在亞馬遜網站上做了如下的條件檢索:

pubdate: after 1992 and title: days and

(title: learn or title: teach yourself)

出版日期:1992年以後,題目關鍵字:“天”,“學會”或者“自學”

  然後得到了248條搜尋結果。頭78條都是計算機類書籍(第79條記錄是《30天學會孟加拉語》)。我將“天”關鍵字換成了“小時”,不出意外地搜 索到了253條記錄,其中頭77條記錄是計算機書籍,第78條的搜尋記錄是《24小時語法和樣式自學手冊》。在總共搜尋到的頭200條記錄中,有96%是 計算機書籍。

  從上面的搜尋結果可以看出來,要麼就是人們對計算機技術的學習如飢似渴,要麼就是計算機技術實在太簡單,不費吹灰之力就能學會。相比於計算機技術書 籍的如此“速成”,在其他領域的書籍裡,你卻很難找到諸如:“三天學會貝多芬”,或者“五天搞定量子力學”,這種速成教材,甚至連《狗狗餵養手冊》這種寵 物指南,都鮮有“幾天搞定”的說法。Felleisen et al.在他們的著作《如何設計程式》一書中明確指出了這種“速成”的趨勢,並評論到:“垃圾的程式設計技術當然非常容易,傻子都能在21天之內學會,哪怕他天生就是個白痴。”

  讓我們來仔細看看《3天學會C++》這種速成教材實際上意味著什麼:

  • 學會:在3天時間裡你幾乎沒有時間去寫任何有意義的程式,就更不要談什麼從程式設計中獲得經驗和教訓這種事情了。你也不可能有時間和有經驗的程式設計師一起工作和交流,也不會體驗到在真正的C++環境下工作是什麼感覺。長話短說吧,你就是沒時間,也學不到什麼。所以這種書籍最多也就讓你有個粗淺的印象,但是絕對不可能有深入的理解。就像亞歷山大教皇說的那樣,“淺嘗輒止是很危險的”。
  • C++: 如果你有其他程式語言的基礎,那3 天之內你也許可以學到C++的一些語法,但即使是這樣,你還是無法瞭解如何使用該語言程式設計。簡言之,如果你之前是一個Basic程式設計師,那麼經過3天的學 習,你會成為一個“能使用C++語法編寫Basic風格程式的程式設計師”,不過這樣是沒法發揮出C++語言本身的優勢的(說句不好聽的,你連怎麼犯C++的 典型錯誤都不會)。僅僅知道一點語法意味著什麼呢?Allan Perlis曾經說過:“一個無法改變你思維方式的程式語言是不值得學習的。”;另一種可能性是,你可以只學一點點C++知識(類似的,或者一點點 JavaScript,或者一點點Flex Script),然後就可以利用現有的工具製作應用介面,完成特定的程式設計任務了。但是這樣的行為並不意味著你“會”程式設計了,你只是會使用這個工具完成任務 而已。
  • 3天:很不幸,3天是遠遠不夠的,往下看你就知道了。

peter norvig

peter norvig

  研究人員(Bloom (1985)、 Bryan & Harter (1899,見文後參考書目)、Hayes (1989)、Simmon & Chase (1973,見文後參考書目) 的一系列調查研究顯示,在各個領域內,要想獲得專業級別的水平,大約需要10年時間的努力。參與此項調查的領域包括:國際象棋,作曲,發報,繪畫,鋼琴演 奏,游泳,網球等。科學家們從神經心理學和拓撲學的角度對這些領域進行研究,並得出結論。若要在某一領域內達到專家級的水平,其關鍵在於“審慎地重複”, 也就是說,並非是機械地,一遍又一遍地練習,而是要不斷地挑戰自我,試圖超越自身當前的水平,透過不斷的嘗試挑戰,並在嘗試的過程中和嘗試之後對自身的表 現進行分析和總結,吸取經驗,糾正之前犯過的各種錯誤。把這一“審慎”的過程不斷重複,才能取得成功。

  所謂的“捷徑”是不存在的,即使對於莫扎特這種天才來說,也沒有捷徑可走,儘管4歲就開始作曲,可是他也花了13年的時間,才真正地寫出了世界級的 作品。再舉一個例子,甲殼蟲樂隊(The Beatles),他們似乎在1964年憑藉一系列熱門單曲和其在艾德沙利文秀(The Ed Sullivan show)上的演出一炮而紅,但是你也許不知道,他們早在1957年就在利物浦和漢堡兩地進行小規模演出了,而在此之前的非正式演出更是不計其數。甲殼蟲 樂隊的主要成名曲《Sgt. Peppers》,則是1967年才發行的。Malcolm Gladwell公佈了他對柏林音樂學院所作的一項研究的報告,該研究對比了一個班裡的學習成績為上、中下三個檔次的學生,並逐一詢問他們進行音樂練習的時間。

  這三個檔次中的所有人,大約都是在5歲的時候開始練習音樂的,一開始的時候大家練習音樂的時間都差不多,大約一週2到3小時。但是到了八歲左右,大 家的區別就開始體現了。後來成為班裡最好的那一部分學生開始比別的學生練習得更多,大概每週6到9小時,12歲的時候每週8小時,14歲的時候每週16小 時,往後則越來越多,直到20歲左右,他們每週練習音樂的時間已經超過30小時了。在20歲的年紀,那些精英級別的演奏家們都有累計超過10000小時的 音樂練習時間。相比之下,僅有部分優等生能達到8000小時的累計練習時間,而那些音樂教師級別的學生,他們的累計練習時間只有4000小時左右。

  所以,也許這個讓你能達到專業等級的神奇時間應該是10000小時,而不是10年。(Henri Cartier-Bresson (1908-2004)說過,“(作為攝影師),你所拍攝的頭10000張照片都是垃圾”,但即使是垃圾作品,他拍一張照片也要花接近一小 時。)Samuel Johnson (1709-1784)認為這個時間應該更長:“在任何一個領域要想做到極好,勢必窮盡一生的精力,否則根本無法企及。” Chaucer (1340-1400)也發出過“生命如此短暫,技能如此高深”的感嘆。Hippocrates (c. 400BC)因寫下了如下的句子而被人稱頌:“ars longa, vita brevis”,該句是來自於一個更長的引用:”Ars longa, vita brevis, occasio praeceps, experimentum periculosum, iudicium difficile”, 這段話翻譯成英語就是:“生命很短暫,但是技藝卻很高深,機遇轉瞬即逝,探索難以捉摸,抉擇困難重重”。這段話是用拉丁文寫的。在拉丁文裡,ars可以翻 譯為“技藝”或者“藝術”,但是在古希臘文裡,ars只能做“技能”的意思,而沒有“藝術”的意思。

你想當程式設計師麼?

  下面是我列舉的程式設計師成功“食譜”

  • 沉醉於程式設計,程式設計是為了興趣。保持這種充滿興趣的感覺,以便於你能將其投入到你的10年/10000小時的程式設計時間中。
  • 程式. 最好的學習方式是“在實踐中學習”。更技術一些地說:“一個人在某個專業領域方面能夠達到最高水平,並不是因為這個人經驗增長了以後而自動獲得的,而是這個人為了進步所做出了專門的努力之後產生的結果。”(p. 366)“最有效的學習包括如下幾個要素:明確並且難度適當的任務,適應學習者個人情況,及時的資訊反饋,有重新開始和改正錯誤的機會)(p. 20-21) 《Cognition in Practice: Mind, Mathematics, and Culture in Everyday Life》這本書提供了上述有趣的觀點
  • 同其他程式設計師交流,多閱讀其他人寫的程式。這些遠比你看書或者上培訓班重要
  • 如果你願意的話,就選擇去讀一個電腦科學專業吧(當然你還可以去唸這個專業的研究生)。如果你能做到這點, 那麼你就有機會找到一些需要計算機學位認證的工作,也會讓你對這個行業有更深的理解。不過,如果你不是上學的料,那麼你可以(當然需要有足夠的毅力)靠自 己學習,或者透過工作來積累經驗。無論你採用哪種途徑,光依靠書本是遠遠不夠的。“如果說僅僅靠學習油畫和調色技術無法創造出頂尖的畫家的話,那麼光學習 電腦科學課程更不能造就頂尖的程式設計師。”,Eric Raymond這樣說過,他著有《新駭客字典》一書。我所聘用過的最好的程式設計師僅僅只有高中文憑; 他寫了很多偉大的軟體,他有他自己的新聞組,並且透過股權賺夠了錢,還開了家屬於自己的夜店。(作者說的這個人是Jamie Zawinski,他是網景瀏覽器(Netscape)的早期開發這者之一,也是開源專案Mozilla和XEmacs的主要貢獻者,他開了一家叫做DNA_lounge的夜店,位於舊金山的SoMa區——譯者注)
  • 與其他程式設計師一起做專案。在某些專案中要儘量做到最好,在某些專案中卻別做那麼好。當你是最好的時候,你的領導能力就會得到鍛鍊,並激發你高瞻遠矚的視野。當你做得不好的時候,你就能知道你的領導怎麼做事,以及他們不喜歡哪些事(因為領導總是把那些他們不愛做的雜事丟給他們認為不得力的人去做)
  • 嘗試跟隨其他程式設計師一起做專案。嘗試去理解其他人所寫的程式碼。看看如果你無法找到程式碼的作者本人的情況下,理解和修正他寫的程式碼需要花費什麼樣的代價。同時也思考,如何規劃你自己的程式程式碼,讓它們更容易被其他人理解和維護。
  • 至少學習半打程式語言。包括一種支援類抽象的語言(例如Java或者 C++),一種支援函式抽象的語言(例如Lisp或者ML),一種支援語法抽象的語言(例如Lisp),一種支援宣告式程式設計的語言(例如Prolog或者 C++模板),一種支援協同程式的語言(例如Icon或者Scheme),一種支援平行併發程式設計的語言(例如Sial)
  • 牢記“電腦科學”中包含著“計算機”這個詞。瞭解計算機需要花多長的時間執行一條指令,花多長時間從記憶體中獲取一個字(word)(包括快取命中和不命中兩種情況),如果連續從磁碟中獲取資料,時間消耗如何?以及需要花多少時間才能再磁碟上定位一個新的位置?
  • 儘量參與語言的標準化過程。往大了說,你可以試著加入ANSI C++委員會這樣的專業組織,往小了講,你也可以從自己的程式碼規範入手,限定程式碼縮排是需要2個空格寬還是4個空格寬。無論採用哪種方式,你都需要了解其 他人對於語言的喜好,以及他們的喜好的程度,甚至你要知道他們為什麼產生這樣的喜好的原因。
  • 有良好的意識,能儘快適應語言標準化的成果。

  要掌握上面所說的所有內容,光靠看書學習應該是很難做到的。當我的第一個孩子出生的時候,我幾乎閱讀了市面上所有的《如何…》指南書籍,但是我讀完 了以後還是覺得自己是個菜鳥。30個月以後,我的第二個孩子快出生時,我難道還要做一個書蟲麼?不!相反,我此時更依賴我的個人經驗,這些經驗相比於那些 上千頁的書籍,則更加有效和讓我放心。

  Fred Brooks所著的著名的論文《No Silver Bullets沒有銀彈》裡向我們揭示了發現和培養軟體設計人才的三步驟:

  1. 有組織地辨認頂尖的軟體設計人才,越早越好
  2. 安排一個職業導師,為其職業前景指點迷津,並謹慎對待自己的職業履歷
  3. 為成長中的設計師們提供機會,讓他們能夠互相激發促進。

  即使一部分人已經具備了成為優秀軟體設計人員的潛質,也需要經歷工作的慢慢琢磨,方可展現才華。Alan Perlis則 說得更加直接:“任何人都可以被‘教’成一個雕塑匠,但米開朗基羅則被‘教’如何不要成為一個雕塑匠,因為他要做的是雕塑大師,。這個道理放到程式設計大師身上同樣管用。”Perlis認為,偉大的軟體開發人員都有一種內在的特質,這種特質往往比他們所接受的訓練更重要。但是這些特質是從哪裡來的呢?是與生俱 來的?還是透過後天勤奮而來?正如Auguste Gusteau(動畫電影《料理鼠王》裡的幻象大廚)所說,“誰都能做飯,但只有那些無所畏懼的人才能成為大廚!”我很情願地說,將你生命中的大部分時間花在審慎地練習和提高上,這很重要!但是“無所畏懼”的精神,才是將促使這些練習成果凝聚成形的途徑。或者,就像是《料理鼠王》裡那個與Gusteau作 對的刻薄的美食評論家Anton Ego說的那樣:“不是任何人都能成為偉大的藝術家,不過,偉大的藝術家在成名前可能是任何人。”

  所以儘管去書店大買Java/Ruby/Javascript/PHP書籍吧;你也許會發現他們真的挺管用。但是這樣做不會改變你的人生,也不會讓你在整體經驗上有什麼提高。24小時,幾天,幾周,做一個真正的程式設計師?光靠讀書可讀不出來。你嘗試過連續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, W.L. & Harter, N. “Studies on the telegraphic language: The acquisition of a hierarchy of habits. Psychology Review, 1899, 8, 345-375

Hayes, John R., The 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系統各種操作指令的大概時間

execute typical instruction

執行基本指令

1/1,000,000,000 sec = 1 nanosec

fetch from L1 cache memory

從一級快取中讀取資料

0.5 nanosec

branch misprediction

分支誤預測

5 nanosec

fetch from L2 cache memory

從二級快取獲取資料

7 nanosec

Mutex lock/unlock

互斥加鎖/解鎖

25 nanosec

fetch from main memory

從主記憶體獲取資料

100 nanosec

send 2K bytes over 1Gbps network

透過1G bps 的網路傳送2K位元組

20,000 nanosec

read 1MB sequentially from memory

從記憶體中順序讀取1MB資料

250,000 nanosec

fetch from new disk location (seek)

從新的磁碟位置獲取資料(隨機讀取)

8,000,000 nanosec

read 1MB sequentially from disk

從磁碟中順序讀取1MB資料

20,000,000 nanosec

send packet US to Europe and back

從美國傳送一個報文包到歐洲再返回

150 milliseconds = 150,000,000 nanosec


附錄:如何選擇語言

  很多人曾經問過我,他們應該選擇什麼程式語言作為入門之用?我想這個問題很難有一個確切的答案,但是下面幾點可以用來作為選擇的參考。

  • 隨大流。當被問到“我應該使用什麼系統呢?Windows, Unix還是Mac?”,我的回答通常是:“看你的朋友們用什麼你就用什麼。”這麼做的好處是,有了你朋友的幫助,你就能有效地迴避作業系統固有的一些差 異,對於選擇程式語言來說,也是同樣道理。同時,你還要有點兒戰略眼光:如果選擇了一種程式語言,併成為其程式設計社群的一員,那麼你選擇的語言和社群是正在 不斷壯大?還是奄奄一息?如果你有程式設計方面的問題,能不能從相關的書籍,網站以及線上論壇中得到解答?你是不是跟論壇裡的人合得來?這些都是要考慮的。
  • 簡單實用。諸如C++以及Java這樣的程式語言都是非常專業的開發語言,適用於有經驗的大型團隊進行開 發,需要時常考慮程式碼的執行效率。所以,這類的程式語言就適合於那樣(複雜)的程式設計環境。如果你是一個初學者,那麼就不要搞那麼複雜。你所需要的是一種簡 單易學的程式語言,你靠你自己就可以搞定的語言。
  • 互動。給你兩種選擇去學鋼琴:第一種,常規做法,也是互動的做法,也就是你每敲一下琴鍵就能聽到琴音;第二 種,批次模式,等你把所有該按的琴鍵都按了一遍,然後再一次性放給你聽。你選擇哪一個呢?顯然,互動式的方式對於鋼琴學習來說更容易,對於程式設計學習也是如 此。那麼就堅持使用互動式模式學習程式設計吧。

  基於上述的觀點,我所推薦的程式設計入門語言應該是Phyton或者Scheme.但是讀者自身的環境是非常複雜多變的,所以你們也許會其他更好的選 擇。如果你的年齡還不到兩位數,那麼你們應該考慮Alice語言或者Squeak語言(很多成年的初學者也認為他們很有趣)。當然,做出選擇並開始行動, 這個最重要。


附錄:書籍和其他資源


備註

  T. Capey指出,Amazon網頁上那個Complete Problem Solver頁面把《21天搞定孟加拉語》以及《21天學會語法》這兩本書移到了“購買此書的使用者還購買過這些產品”這個區域內。我估計大部分人就是從這個區域看到這本書的。感謝Ross Cohen的幫助。

英文原文:Peter Norvig    編譯:伯樂線上 – 黃小非

Peter Norvig:自學程式設計,十年磨一劍

相關文章