Java語言學校的危險性(譯文)

下面的文章是More Joel on Software一書的第8篇。
我以爲翻譯難度很大,整整兩個工做日,天天8小時以上,才譯出了5000字。除了Joel大量使用俚語,另外一個緣由是原文涉及"編程原理",好多東西我根本不懂。但願懂的朋友幫我看看,譯文有沒有錯誤,包括我寫的註解。
====================
JAVA語言學校的危險性
做者:Joel Spolsky
譯者:阮一峯
原文: http://www.joelonsoftware.com/articles/ThePerilsofJavaSchools.html
發表日期 2005年12月29日,星期四


現在的孩子變懶了。 多吃一點苦,又會怎麼樣呢? 我必定是變老了,纔會這樣喋喋不休地抱怨和感嘆"現在的孩子"。爲何他們再也不願意、或者說再也不可以作艱苦的工做呢。 當我仍是孩子的時候,學習編程須要用到穿孔卡片(punched cards)。那時可沒有任何相似"退格"鍵(Backspace key)這樣的現代化功能,若是你出錯了,就沒有辦法更正,只好扔掉出錯的卡片,從頭再來。 回想1991年,我開始面試程序員的時候。我通常會出一些編程題,容許用任何編程語言解題。在99%的狀況下,面試者選擇C語言。 現在,面試者通常會選擇Java語言。 說到這裏,不要誤會個人意思。Java語言自己做爲一種開發工具,並無什麼錯。 等一等,我要作個更正。我只是在本篇特定的文章中,不會提到Java語言做爲一種開發工具,有什麼很差的地方。事實上,它有許許多多很差的地方,不過這些只有另找時間來談了。 我在這篇文章中,真正想要說的是,總的來看,Java不是一種很是難的編程語言,沒法用來區分優秀程序員和普通程序員。它可能很適合用來完成工做,可是這個不是今天的主題。我甚至想說,Java語言不夠難,實際上是它的特點,不能算缺點。可是無論怎樣,它就是有這個問題。 若是我聽上去像是妄下論斷,那麼我想說一點我本身的微不足道的經歷。大學計算機系的課程裏,傳統上有兩個知識點,許多人歷來都沒有真正搞懂過的,那就是指針(pointers)和遞歸(recursion)。 你進大學後,一開始總要上一門"數據結構"課(data structure), 而後會有線性鏈表(linked list)、哈希表(hash table),以及其餘諸如此類的課程。這些課會大量使用"指針"。它們常常起到一種優勝劣汰的做用。由於這些課程很是難,那些學不會的人,就代表他們的能力不足以達到計算機科學學士學位的要求,只能選擇放棄這個專業。這是一件好事,由於若是你連指針很以爲很難,那麼等學到後面,要你證實不動點定理(fixed point theory)的時候,你該怎麼辦呢? 有些孩子讀高中的時候,就能用BASIC語言在Apple II型我的電腦上,寫出漂亮的乒乓球遊戲。等他們進了大學,都會去選修計算機科學101課程,那門課講的就是數據結構。當他們接觸到指針那些玩意之後,就一會兒徹底傻眼了,後面的事情你均可以想像,他們就去改學政治學,由於看上去法學院是一個更好的出路[1]。關於計算機系的淘汰率,我見過各式各樣的數字,一般在40%到70%之間。校方通常會以爲,學生拿不到學位很惋惜,我則視其爲必要的篩選,淘汰那些沒有興趣編程或者沒有能力編程的人。 對於許多計算機系的青年學生來講,另外一門有難度的課程是有關函數式編程(functional programming)的課程,其中就包括遞歸程序設計(recursive programming)。MIT將這些課程的標準提得很高,還專門設立了一門必修課(課程代號6.001[2]),它的教材(Structure and Interpretation of Computer Programs,做者爲Harold Abelson和Gerald Jay Sussman Abelson,MIT出版社1996年版)被幾十所、甚至幾百所著名高校的計算系機採用,充當事實上的計算機科學導論課程。(你能在網上找到這本教材的舊版本,應該讀一下。) 這些課程可貴驚人。在第一堂課,你就要學完Scheme語言[3]的幾乎全部內容,你還會遇到一個不動點函數(fixed-point function),它的自變量自己就是另外一個函數。我讀的這門導論課,是賓夕法尼亞大學的CSE 121課程,真是讀得苦不堪言。我注意到不少學生,也許是大部分的學生,都沒法完成這門課。課程的內容實在太難了。我給教授寫了一封長長的痛哭流涕的Email,控訴這門課不是給人學的。賓夕法尼亞大學裏必定有人聽到了個人呼聲(或者聽到了其餘抱怨者的呼聲),由於現在這門課講授的計算機語言是Java。 我如今以爲,他們還不如沒有聽見呢。 這就是爭議所在。許多年來,像當年的我同樣懶惰的計算機系本科生不停地抱怨,再加上計算機業界也在抱怨畢業生不夠用,這一切終於形成了重大惡果。過去十年中,大量原本堪稱完美的好學校,都百分之百轉向了Java語言的懷抱。這真是好得沒話說了,那些用"grep"命令[4]過濾簡歷的企業招聘主管,大概會很喜歡這樣。最妙趣橫生的是,Java語言中沒有什麼太難的地方,不會真的淘汰什麼人,你搞不懂指針或者遞歸也不要緊。因此,計算系的淘汰率就下降了,學生人數上升了,經費預算變大了,可謂皆大歡喜。 學習Java語言的孩子是幸運的,由於當他們用到以指針爲基礎的哈希表時,他們永遠也不會遇到古怪的"段錯誤"[5](segfault)。他們永遠不會由於沒法將數據塞進有限的內存空間,而急得發瘋。他們也永遠不用苦苦思索,爲何在一個純函數的程序中,一個變量的值一會保持不變,一會又變個不停!多麼自相矛盾啊! 他們不須要怎麼動腦筋,就能夠在專業上獲得4.0的績點。 我是否是有點太苛刻了?就像電視裏的"四個約克郡男人"[6](Four Yorkshiremen)那樣,成了老古板?就在這裏吹噓我是多麼刻苦,完成了全部那些高難度的課程? 我再告訴你一件事。1900年的時候,拉丁語和希臘語都是大學裏的必修課,緣由不是由於它們有什麼特別的做用,而是由於它們有點被當作是受太高等教育的人士的標誌。在某種程度上,個人觀點同拉丁語支持者的觀點沒有不一樣(下面的四點理由都是如此):"(拉丁語)訓練你的思惟,鍛鍊你的記憶。分析拉丁語的句法結構,是思考能力的最佳練習,是真正對智力的挑戰,可以很好地培養邏輯能力。"以上出自Scott Barker之口(http://www.promotelatin.org/whylatin.htm)。可是,今天我找不到一所大學,還把拉丁語做爲必修課。指針和遞歸不正像計算機科學中的拉丁語和希臘語嗎? 說到這裏,我坦率地認可,當今的軟件代碼中90%都不須要使用指針。事實上,若是在正式產品中使用指針,這將是十分危險的。好的,這一點沒有異議。與此同時,函數式編程在實際開發中用到的也很少。這一點我也贊成。 可是,對於某些最激動人心的編程任務來講,指針仍然是很是重要的。好比說,若是不用指針,你根本沒辦法開發Linux的內核。若是你不是真正地理解了指針,你連一行Linux的代碼也看不懂,說實話,任何操做系統的代碼你都看不懂。 若是你不懂函數式編程,你就沒法創造出MapReduce[7],正是這種算法使得Google的可擴展性(scalable)達到如此巨大的規模。單詞"Map"(映射)和"Reduce"(化簡)分別來自Lisp語言和函數式編程。回想起來,在相似6.001這樣的編程課程中,都有提到純粹的函數式編程沒有反作用,所以能夠直接用於並行計算(parallelizable)。任何人只要還記得這些內容,那麼MapRuduce對他來講就是顯而易見的。發明MapReduce的公司是Google,而不是微軟,這個簡單的事實說出了緣由,爲何微軟至今還在追趕,還在試圖提供最基本的搜索服務,而Google已經轉向了下一個階段,開發世界上最大的並行式超級計算機----Skynet[8]的H次方的H次方的H次方的H次方的H次方的H次方。我以爲,微軟並無徹底明白,在這一波競爭中它落後多遠。 除了上面那些直接就能想到的重要性,指針和遞歸的真正價值,在於那種你在學習它們的過程當中,所獲得的思惟深度,以及你由於懼怕在這些課程中被淘汰,所產生的心理抗壓能力,它們都是在建造大型系統的過程當中必不可少的。指針和遞歸要求必定水平的推理能力、抽象思考能力,以及最重要的,在若干個不一樣的抽象層次上,同時審視同一個問題的能力。所以,是否真正理解指針和遞歸,與是不是一個優秀程序員直接相關。 若是計算機系的課程都與Java語言有關,那麼對於那些在智力上沒法應付複雜概念的學生,就沒有東西能夠真的淘汰他們。做爲一個僱主,我發現那些100%Java教學的計算機系,已經培養出了至關一大批畢業生,這些學生只能勉強完成難度日益下降的課程做業,只會用Java語言編寫簡單的記帳程序,若是你讓他們編寫一個更難的東西,他們就一籌莫展了。他們的智力不足以成爲程序員。這些學生永遠也通不過MIT的6.001課程,或者耶魯大學的CS 323課程。坦率地說,爲何在一個僱主的心目中,MIT或者耶魯大學計算機系的學位的分量,要重於杜克大學,這就是緣由之一。由於杜克大學最近已經所有轉爲用Java語言教學。賓夕法尼亞大學的狀況也很相似,當初CSE 121課程中的Scheme語言和ML語言,幾乎將我和個人同窗折磨至死,現在已經所有被Java語言替代。個人意思不是說,我不想僱傭來自杜克大學或者賓夕法尼亞大學的聰明學生,我真的願意僱傭他們,只是對於我來講,肯定他們是否真的聰明,現在變得難多了。之前,我可以分辨出誰是聰明學生,由於他們能夠在一分鐘內看懂一個遞歸算法,或者能夠迅速在計算機上實現一個線性鏈表操做函數,所用的時間同黑板上寫一遍差很少。可是對於Java語言學校的畢業生,看着他們面對上述問題苦苦思索、作不出來的樣子,我分辨不出這究竟是由於學校裏沒教,仍是由於他們不具有編寫優秀軟件做品的素質。Paul Graham將這一類程序員稱爲"Blub程序員"[9](www.paulgraham.com/avg.html)。 Java語言學校沒法淘汰那些永遠也成不了優秀程序員的學生,這已是很糟糕的事情了。可是,學校能夠無可厚非地辯解,這不是校方的錯。整個軟件行業,或者說至少是其中那些使用grep命令過濾簡歷的招聘經理,確實是在一直叫嚷,要求學校使用Java語言教學。 可是,即便如此,Java語言學校的教學也仍是失敗的,由於學校沒有成功訓練好學生的頭腦,沒有使他們變得足夠熟練、敏捷、靈活,可以作出高質量的軟件設計(我不是指面向對象式的"設計",那種編程只不過是要求你花上無數個小時,重寫你的代碼,使它們可以知足面向對象編程的等級制繼承式結構,或者說要求你思考到底對象之間是"has-a"從屬關係,仍是"is-a"繼承關係,這種"僞問題"將你搞得煩躁不安)。你須要的是那種可以在多個抽象層次上,同時思考問題的訓練。這種思考能力正是設計出優秀軟件架構所必需的。 你也許想知道,在教學中,面向對象編程(object-oriented programming,縮寫OOP)是不是指針和遞歸的優質替代品,是否是也能起到淘汰做用。簡單的回答是:"不"。我在這裏不討論OOP的優勢,我只指出OOP不夠難,沒法淘汰平庸的程序員。大多數時候,OOP教學的主要內容就是記住一堆專有名詞,好比"封裝"(encapsulation)和"繼承"(inheritance)",而後再作一堆多選題小測驗,考你是否是明白"多態"(polymorphism)和"重載"(overloading)的區別。這同歷史課上,要求你記住重要的日期和人名,難度差很少。OOP不構成對智力的太大挑戰,嚇不跑一年級新生。聽說,若是你沒學好OOP,你的程序依然能夠運行,只是維護起來有點難。可是若是你沒學好指針,你的程序就會輸出一行段錯誤信息,並且你對什麼地方出錯了毫無想法,而後你只好停下來,深吸一口氣,真正開始努力在兩個不一樣的抽象層次上,同時思考你的程序是如何運行的。 順便說一句,我有充分理由在這裏說,那些使用grep命令過濾簡歷的招聘經理真是荒謬好笑。我歷來沒有見過哪一個能用Scheme語言、Haskell語言和C語言中的指針編程的人,居然不能在二天裏面學會Java語言,而且寫出的Java程序,質量居然不能賽過那些有5年Java編程經驗的人士。不過,人力資源部裏那些平庸的懶漢,是沒法期望他們聽進去這些話的。 再說,計算機系承擔的發揚光大計算機科學的使命該怎麼辦呢?計算機系畢竟不是職業學校啊!訓練學生如何在這個行業裏工做,不該該是計算機系的任務。這應該是社區高校和政府就業培訓計劃的任務,那些地方會教給你工做技能。計算機系給予學生的,理應是他們往後生活所須要的基礎知識,而不是爲學生第一週上班作準備。對不對? 還有,計算機科學是由證實(遞歸)、算法(遞歸)、語言(λ演算[10])、操做系統(指針)、編譯器(λ演算)所組成的。因此,這就是說那些不教C語言、不教Scheme語言、只教Java語言的學校,實際上根本不是在教授計算機科學。雖然對於真實世界來講,有些概念可能毫無用處,好比函數的科裏化(function currying)[11],可是這些知識顯然是進入計算機科學研究生院的前提。我不明白,計算機系課程設置委員會中的教授爲何會贊成,將課程的難度降低到如此低的地步,以致於他們既沒法培養出合格的程序員,甚至也沒法培養出合格的可以獲得哲學博士PhD學位[12]、進而可以申請教職、與他們競爭工做崗位的研究生。噢,且慢,我說錯了。也許我明白緣由了。 實際上,若是你回顧和研究學術界在"Java大遷移"(Great Java Shift)中的爭論,你會注意到,最大的議題是Java語言是否還不夠簡單,不適合做爲一種教學語言。 個人老天啊,我內心說,他們還在設法讓課程變得更簡單。爲何不用匙子,乾脆把全部東西一勺勺都喂到學生嘴裏呢?讓咱們再請助教幫他們接管考試,這樣一來就沒有學生會改學"美國研究"[13](American studies)了。若是課程被精心設計,使得全部內容都比原有內容更容易,那麼怎麼可能指望任何人從這個地方學到任何東西呢?看上去彷佛有一個工做小組(Java task force)正在開展工做,創造出一個簡化的Java的子集,以便在課堂上教學[14]。這些人的目標是生成一個簡化的文檔,當心地不讓學生纖弱的思想,接觸到任何EJB/J2EE的髒東西[15]。這樣一來,學生的小腦殼就不會由於遇到有點難度的課程,而感到煩惱了,除非那門課裏只要求作一些空前簡單的計算機習題。 計算機系如此積極地下降課程難度,有一個理由能夠獲得最多的贊同,那就是節省出更多的時間,教授真正的屬於計算機科學的概念。可是,前提是不能花費整整兩節課,向學生講解諸如Java語言中int和Integer有何區別[16]。好的,若是真是這樣,課程6.001就是你的完美選擇。你能夠先講Scheme語言,這種教學語言簡單到聰明學生大約只用10分鐘,就能所有學會。而後,你將這個學期剩下的時間,都用來說解不動點。 唉。 說了半天,我仍是在說要學1和0。 (你學到了1?真幸運啊!咱們那時全部人學到的都是0。) ================ 註解: [1] 在美國,法學院的入學者都必須具備本科學位。一般來講,主修政治學的學生升入法學院的機會最大。 [2] 在麻省理工學院,計算機系的課程代碼都是以6開頭的,6.001代表這是計算機系的最基礎課程。 [3] Scheme語言是LISP語言的一個變種,誕生於1975年的MIT,以其對函數式編程的支持而聞名。這種語言在商業領域的應用不多,可是在計算機教育領域內有着普遍影響。 [4] grep是Unix/Linux環境中用於搜索或者過濾內容的命令。這裏指的是,某些招聘人員僅僅根據一些關鍵詞來過濾簡歷,好比本文中的Java。 [5] 段錯誤(segfault)是segmentation fault的縮寫,指的是軟件中的一類特定的錯誤,一般發生在程序試圖讀取不容許讀取的內存地址、或者以非法方式讀取內存的時候。 [6] 《四個約克郡男人》(Four Yorkshiremen),是英國電視系列喜劇At Last the 1948 Show中的一部,與上個世紀70年代問世。內容是四個約克郡男人競相吹噓,各自的童年是多麼困苦,因爲內容太誇張,因此顯得很是好笑。 [7] MapReduce是一種由Google引入使用的軟件框架,用於支持計算機集羣環境下,海量數據(PB級別)的並行計算。 [8] Skynet是美國系列電影《終結者》(Terminator)中一個控制一切、與人類爲敵的超級計算機系統的名稱,一般將其看做虛構的人工智能的表明。 [9] Blub程序員(Blub programmers)指的是那些企圖用一種語言,解決全部問題的程序員。Blub是Paul Graham假設的一種高級編程語言。 [10] λ演算(lambda calculus)是一套用於研究函數定義、函數應用和遞歸的形式系統,在遞歸理論和函數式編程中有着普遍的應用。 [11] 函數的科裏化(function currying)指的是一種多元函數的消元技巧,將其變爲一系列只有一元的鏈式函數。它最先是由美國數學家哈斯格爾·科裏(Haskell Curry)提出的,所以而得名。 [12] 在美國,全部基礎理論的學科,一概授予的都是哲學博士學位(Doctor of Philosophy),計算機科學系亦是如此。 [13] 美國研究(American studies)是對美國社會的經濟、歷史、文化等各個方面進行研究的一門學科。這裏指的是,計算機系學生不會由於課程太難被淘汰,因此就不用改學相對容易的"美國研究"。 [14] 參見http://www.sigcse.org/topics/javataskforce/java-task-force.pdf。 [15] J2EE是Java2平臺企業版(Java 2 Platform,Enterprise Edition),指的是一整套企業級開發架構。EJB(Enterprise JavaBean)屬於J2EE的一部分,是一個基於組件的企業級開發規範。它們一般被認爲是Java中相對較難的部分。 [16] 在Java語言中,int是一種數據類型,表示整數,而Integer是一個適用於面向對象編程的類,表示整數對象。二者的涵義和性質都不同。 (完)
相關文章
相關標籤/搜索