1. 程式人生 > 實用技巧 >推薦一篇程式設計屆的經典文章『十年學會程式設計』,希望給你不一樣的啟發

推薦一篇程式設計屆的經典文章『十年學會程式設計』,希望給你不一樣的啟發

文章原名為「Teach Yourself Programming in Ten Years」,本文為譯文。

文章作者 Peter Norvig目前就職於 Google,擔任研發主管(Director of Research)一職,之前他曾指導谷歌的核心搜尋演算法小組,他還是 AI 領域內領先教科書「人工智慧:一種現代方法」一書的合作者,同時還是 Udacity 的人工智慧課程的合作教師,其中學生超過1w6千名。這位大佬同時還是 AAAIACM,以及加州科學院和美國藝術與科學學院的一員。附上一張大佬的照片,大家膜拜一下 。

正文開始

為何人人如此著急?

隨意步入一家書店,鋪天蓋地的「24小時搞定 Java 程式設計」,還有琳琅滿目的包括但不限於 C

SQLRuby,演算法等書籍,它們同樣都承諾在幾天,甚至幾小時以內讓你學會相關技術。我在亞馬遜網站高階搜尋輸入幾個關鍵詞查詢:自學,小時,從2000年以後,然後發現了512種類似書籍。前十名中,有9本是程式設計書籍(另一本是關於記賬的)。將自學替換為學習或者將小時替換為,同樣會得到類似的結果。

我們從上面可以得出什麼結論呢?結論就是要麼人們普遍急於學習程式設計,要麼程式設計在某種程度上比其他任何東西更容易學習。 Felleisen et al. 在他們的著作「如何設計程式」中明確指出了這種趨勢,並且評論說:“垃圾的程式非常容易,傻子也能在21天學會,即使他們天生就是個白痴。” The Abtruse Goose 漫畫同樣也有他們的

看法。(筆者注:是一個漫畫網站,下圖就是網站的關於這個觀點的漫畫)

讓我們看一下「24小時學會 C++」這種速成教材實際上意味著什麼:

  • 學會:24小時內你不會有時間寫任何有意義的程式,就更別說從程式設計中獲得經驗和教訓了。你甚至都沒有和有經驗的程式設計師一起工作交流,也就別提在真實的 C++環境中工作是什麼感覺了。總之,你不會有時間收穫太多。所以這種書籍最多也就讓你有個粗淺的印象,但是絕對不可能有深入的理解。就像亞歷山大教皇說的那樣,“淺嘗輒止是很危險的”。
  • C++:如果你有其他程式語言的基礎,24小時你可能學會 C++的語法,但是(凡事就怕但是)你還是無法理解如何使用該語言。簡而言之,如果你之前是一個 Basic 程式設計師,你可能變成一個會使用 C++
    語法寫出 Basic 風格的語言,不過這樣是無法發揮出 C++本身語言的優勢的。那這有什麼意義呢? Alan Perlis (筆者注:另外一位大佬,連結是他寫的程式設計警句文章, 值得謹記,後面有機會翻譯出來給大家)曾經說過:“一個無法改變你思維方式的程式語言是不值得學習的。”另一種可能性是,你可以只學一點點C++知識(類似的,或者一點點JavaScript),然後就可以利用現有的工具製作應用介面,完成特定的程式設計任務了。但是這樣的行為並不意味著你“會”程式設計了,你只是會使用這個工具完成任務而已。
  • 24小時:很不幸,24小時是遠遠不夠的,往下看你就知道了。

十年學會程式設計

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

所謂的“捷徑”是不存在的,即使對於莫扎特來說,也沒有。儘管他4歲就開始作曲,但也花了13多年的時間,才寫出了世界級的作品。同樣另外一個例子,甲殼蟲樂隊(The Beatles),他們似乎在1964年憑藉一系列熱門單曲和其在艾德沙利文秀(The Ed Sullivan show)上的演出一炮而紅,但是你也許不知道,他們早在1957年就在利物浦和漢堡兩地進行小規模演出了,而在此之前的非正式演出更是不計其數。甲殼蟲樂隊的主要成名曲《Sgt. Peppers》,則是1967年才發行的。

Malcolm Gladwell 推廣了這一想法,儘管他關注的是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”, 這段話翻譯成英語就是:“生命很短暫,但是技藝卻很高深,機遇轉瞬即逝,探索難以捉摸,抉擇困難重重”。

當然,沒有最終答案,假設所有的技能(例如程式設計,國際象棋,跳棋和作曲)對所有人來說,需要完全掌握都需要相同的學習時間,這種說法是不合理的。正如 K.Anders Ericsson 所說,在大多數領域,即使最有才能的人想要達到技藝的最高水平,仍然需要10000小時左右的時間。

你想當程式設計師嗎?

下面是我程式設計成功的祕訣:

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

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

Fred Brooks 所著的著名的論文 href="https://en.wikipedia.org/wiki/No_Silver_Bullet">「 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., 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/1,000,000,000 sec = 1 nanosec

從一級快取中讀取資料 0.5 nanosec

分支誤預測 5 nanosec

從二級快取中讀取資料 7 nanosec

互斥加鎖/解鎖 25 nanosec

從主記憶體中獲取資料 100 nanosec

通過1G bps 的網路傳送2K 位元組 20,000 nanosec

從記憶體中順序讀取1MB資料 250,000 nanosec

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

從磁碟中順序讀取1MB 資料 20,000,000 nanosec

從美國發送一個報文包到歐洲再返回 150 milliseconds = 150,000,000 nanosec

附錄:如何選擇語言

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

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

基於上述的觀點,我所推薦的程式設計入門語言應該是Phyton或者Scheme, 另外一個選擇就是 Javascript, 並不是它對初學者很友好,而是因為網上有很多的線上教程以及解答,例如Khan Academy's tutorial. 但是你自身的環境是非常複雜多變的,所以你們也許會其他更好的選擇。如果你的年齡還不到兩位數,那麼你們應該考慮Alice語言或者Squeak語言或者 Blockly(很多成年的初學者也認為他們很有趣)。當然,做出選擇並開始行動,這個最重要。

附錄:書籍和其他資源