程序員之路:十年磨一劍
轉載者注:本文為經典的關於學習編程的文章,銘此以自勉。
英文原文:Teach Yourself Programming in Ten Years (By Peter Norvig)
你們著什麼急?
隨意步入一家書店,滿目都是《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天是遠遠不夠的,往下看你就知道了。
十年磨一劍
研究人員(Bloom (1985)、Bryan & Harter、Hayes (1989)、Simmon & Chase的一係列調查研究顯示,在各個領域內,要想獲得專業級別的水平,大約需要 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 語言(很多成年的初學者也認為他們很有趣)。當然,做出選擇並開始行動,這個最重要。
附錄:書籍和其他資源
模式編程:《Structure and Interpretation of Computer Programs (Abelson & Sussman) 計算機程序的構造和解釋》 這本書或許是計算機科學最好的入門書籍,本書從計算機科學的角度入手,教你如何進行編程。你可以在 online videos of lectures 觀看本書的在線視頻教程,以及 complete text online 的在線文字版。 學習本書是需要一些挑戰的,相信該書會讓一部分人望而卻步的。
模式編程:《How to Design Programs (Felleisen et al.) 程序設計方法》是一本好書,該書介紹了如何用優雅並且有效的方式進行程序設
Python: Python Programming: An Intro to CS (Zelle) 是一本介紹 Python 的好書
Python: Python.org 官方網站上提供了一些在線教程 tutorials.
Oz: Concepts, Techniques, and Models of Computer Programming (Van Roy & Haridi) 被看做是 Abelson & Sussman(經典計算機教程《計算機程序的構造和解釋》 的作者——譯者注)的當代傳承者。該書繪製了一幅關於計算機編程的宏觀藍圖,它囊括了比 Abelson & Sussman 的經典教材更廣泛的知識領域,也更加通俗易懂。此書中使用了一種編程語言,Oz, 這種語言在工業領域內幾乎不被使用,其主要目的就是針對於教學
備注
T. Capey 指出,Amazon 網頁上那個 Complete Problem Solver 頁麵把《21天搞定孟加拉語》以及《21天學會語法》這兩本書移到了“購買此書的用戶還購買過這些產品”這個區域內。我估計大部分人就是從這個區域看到這本書的。感謝 Ross Cohen 的幫助。
最後更新:2017-04-03 05:39:54