Java 學校的危害 The Perils of JavaSchools

作者:周思博 (Joel Spolsky)
Thursday, December 29, 2005
屬於 Joel on Software, https://www.joelonsoftware.com/2005/12/29/the-perils-of-javaschools-2/

懶惰的孩子。

辛勤工作這回事是怎麼了?

一直發牢騷抱怨「現在的小孩」,怪他們不願亦不能做較困難的事情,這顯然表示我已逐漸老朽了。

你們很幸福啦,以前我們在化糞池裡一個牛皮紙袋裡住了三個月,早晨六點就得起床把袋子清乾淨,吃一塊過期麵包皮就開始工作,日復一日每天工作十四小時,回到家後父親還會拿皮帶把我們轟去睡覺。

Monty Python的飛行馬戲團 Four Yorkshiremen

當我還是個孩子的時候,我使用打孔卡片來學習編寫程式,假若你出錯了,很抱歉,沒什麼時髦功能可以補救(比如按倒退鍵來修正),只能扔了這張卡片然後重新開始。

我在 1991 年開始面試程式員時,通常會讓他們自行選擇語言來解決我所出的編程問題。99% 的機會他們會選擇 C。

現在,他們傾向於選擇 Java。

不要誤解我:以實作語言而言,Java 並沒有任何問題。

等一下,我要修正一下。我並不是要在這篇文章中聲稱,Java 就實作語言而言沒有任何問題,事實上它不對的地方可多了,不過那得等我寫另外一篇文章來談了。

我真正要說的是,整體來看 Java 這種語言並不夠困難,無法區分偉大的程式員跟平庸的程式員。在工作上或許是個好語言,但這不是今天的重點。我甚至會進一步說,Java 不夠難這件事是個特色而非缺陷,可是它畢竟還是有這個問題。

這樣說可能很傲慢,不過就我卑微的經驗而言,指標跟遞迴是大學資訊科學傳統課程中,許多人永遠無法完全理解的兩件事。

大學課程通常由資料結構這門課開始,裡面有鏈結串列(linked lists)和雜湊表(hash tables)等等都廣泛的使用指標。這些課程常被用來作為淘汰課程:它們非常困難,會讓無法面對 CS(資訊科學,後面都簡稱 CS)學位心智挑戰的人選擇放棄。這是件好事,因為如果你認為指標很難,等到要證明不動點定理(fixed point theory)的題目時就知道什麼叫難了。

有些小孩高中就在自己的 Apple II 上,用 BASIC 寫出很棒的乒乓遊戲。當這些孩子上大學修 CompSci 101(一門資料結構的課程),接觸指標這玩意之後,轟!他們的大腦馬上被炸成一堆豆腐渣,接下來都跑去修政治學,因為法學院似乎是個更好的主意。我看過 CS 科系退學率的各種數字,通常介於 40% 到 70% 之間。大學當局通常認視之為浪費,我則認為這是必要的排除手段,讓那些往後無法樂於編程職業或因此成功的人及早出局。

對許多年輕的 CS 學生來說,另一個難題是教授 functional programming (包括遞迴編程在內)的課程。MIT 對這些課程的要求很高,不但創造了必修 課程(6.001),還編寫出一本教科書(Abelson & Sussman的 Structure and Interpretation of Computer Programs ),被數十甚至數百所一流 CS 學校拿來作為 CS 入門教材。(你可以也應該在 線上看看舊版的教材。)

這些課程的困難度極高。第一講就幾乎教完 Scheme 所有的內容(譯註:Scheme 是一種古老的程式語言,常見於 AI 領域),還介紹了把另一個函式當成輸入的固定點函式。在與這種課程(賓州大學的 CSE121)奮鬥之際,我注意到很多學生(可以說是大多數)都撐不過。教材實在是太艱澀了。我寫了一封聲淚俱下的長篇電郵給教授,控訴這門課實在是不人道!賓州大學一定有人聽到了我(或其他抱怨者)的心聲,因為這門課現在已經改用Java授課了。

我真希望他們沒有聽到這個心聲。

你認為自己搞懂了嗎?在這兒測測你自己

這就是爭議所在。像我這樣多年來發牢騷責怪懶惰的 CS 大學生,再加上業界抱怨主修 CS 的美國大學畢業生不足,已經對整體環境造成了極大的傷害。過去十年間大量原本很優秀的學校已經完全轉向 Java。這真是讚啊,用 grep 過濾履歷的徵才人員應該挺高興的(譯註:因為有一堆人可供他們選擇了);而且最棒的是,Java 裡沒有什麼很難的東西,不能真正淘汰掉那些沒有指標跟遞迴腦細胞的程式員,所以退學率降低,於是 CS 系所收的學生更多,預算也水漲船高,一切是如此的美好。

Java 學校教出出來的幸褔小孩不需要用指標實作雜湊表,因此從未遭遇 segfaults 這種錯誤。他們從不需要戰戰兢兢、發瘋似地試著把東西塞進極有限的空間中。他們也永遠不需要動腦想想,為何在純粹 functional 程式中,一個變數的值永不改變,但卻又隨時在變!一種自相矛盾的東西!

他們不需要可以讓他們在學位上獲得 4 分的那部分腦細胞。

我就是像 Four Yorkshiremen 那樣的老古板嗎?才會一直吹噓自己以前多麼堅韌,能安然渡過這麼困難的課程嗎?

嗨!在 1900 年,拉丁文跟希臘語是大學必修的課程。並不是因為它們能做什麼,而是它們多少被視為受過教育的人所必備的知識。在某些概念上,我的論點跟支持學拉丁文的人沒甚麼不同(以下四個理由都是):「(拉丁文)訓練你的心智。訓練你的記憶力。闡明一個拉丁文句子可鍛鍊思考能力,是一個真正智力上的考驗,並且對邏輯思考的良好起點」Scott Barker 如是。不過我現在已經找不到任何還要必修拉丁文的大學了。那麼指標跟遞迴算是 CS 的拉丁與希臘語嗎?

現在我要坦率地承認,如今寫的程式九成都不需要用到指標,而且事實上在產品程式上使用指標相當危險。是的,沒關係。而 functional programming 在實務上幾乎都沒人在用,這我也同意。

不過它在某些最刺激的編程作業上依然有其重要性。舉例來說,不用指標根本無法在 Linux 核心做事。假若你並不是真的完全瞭解指標,就無法理解任何一行 Linux (甚至是任何作業系統)的程式碼。

不瞭解 function programming,就無法發明 MapReduce 這個讓 Google 具備驚人擴充性的演算法。Map 跟 Reduce 是從 Lisp 和 function programming 來的。修過相當於 6.001 編程課程的人,如果還記得純 functional programs 沒有什麼副作用,不會影響並行的函式,因此可以輕易地平行化同步處理。在他們回想之際,MapReduce 實是是顯而易見的演算法。Google發明了MapReduce而微軟沒有,這個事實可以解釋為何當微軟仍在嘗試讓基本搜尋功能能運作時,Google 已經進到下個領域:建立 Skynet 這個世界上最大的平行處理超級電腦,我不認為微軟真正瞭解他們在這波競爭中落後了多少。

但是在這些表像的重要性背後,指標和遞迴有其真正的價值。在學習它們的過程中,能獲得建造大型系統所需的心智複雜度,以及免於被相關課程淘汰的特殊資質。必須具備某種能力,才能理解並以抽象的方式思考指標和遞迴,而最重要的就是同時從數個不同的抽象層次看待同一個問題。因此,瞭解指標跟遞迴的能力與成為偉大程式員的能力有著直接的關連。

在一個純 Java 的 CS 學位之中,沒有東西能淘汰缺乏處理這些概念的靈活心智的學生。身為一個雇主,我看到純 Java 學校已經開始量產出一些根本不夠聰明的 CS 畢業生,儘管他們可以勉強通過那些新簡化過的課程作業,卻不足以進行任何比「又一個 Java 會計管理程式」更複雜的工作。這些學生永遠無法通過麻省理工學院的 6.001 或耶魯的 CS 323 課程,坦白說,這就是雇主心目中,麻省理工學院或耶魯的 CS 學位比杜克大學的 CS 學位(已經完全轉向 Java)更有份量的原因之一。賓州大學也放棄 Scheme 和 ML 語言(譯註:此兩種語言常見於AI領域上),嘗試用 Java 來教授那門幾乎整死我和我朋友的 CSE121 課程。並不是說我不會雇用來自杜克或賓州大學的聰明孩子,我會的。只是對我來說,要分辨誰夠聰明要難上許多。過去我能分辨出聰明的孩子,因為他們能瞬間解通一個遞迴的演算法,而且用指標實作鍵結串列的速度和在白板上寫一樣快。但是當 Java 學校的畢業生卡在這些問題時,我無法分辨是因為他們受的教育不足,或是他們根本缺少進行龐大編程工程所需的天賦。Paul Graham 管他們叫做 Blub 程式員

Java 學校不能淘汰這些永遠無法成為偉大程序員的孩子,這已經是很糟糕的事,可是學校可以辨稱這不是他們的問題,但業界(至少那些用 grep 篩選履歷的招募人員是如此)卻是確實地吵著學校必須教授 Java 課程。

然而 Java 學校也無法訓練孩子們的腦袋更熟練、聰穎、靈活,讓他們能完成良好的軟體設計(我不是指那種花費無數時間改寫程式碼來重調繼承架構,或是為了 has-a 還是 is-a 之類的假性「問題」煩惱的 OO「設計」)。你需要訓練才能同時在多個抽象層次上思考事情,而在設計龐大的軟體架構時正需要這種思考能力。

你或許會想知道,物件導向編程(OOP)是否能取代指標跟遞迴,成為良好的淘汰工具。簡單的答案是「否」。撇開 OOP 的功過不論,它就是沒有難到足以淘汰平庸的程式員。學校教的 OOP 絕大多數都是在背誦一堆像「封裝」、「繼承」之類的詞彙,再做些多型與多載(overload)間差異的單選題小測驗。OOP並不比在歷史課上背誦重要日期和名字難很多,而是用不適當的心智挑戰嚇跑一年級學生。據稱當你面對 OOP 問題時,程式仍然能工作,只是有點難維護而已。但是當你與指標問題奮戰時,程式只會產生一行 Segmentatidon Fault,除非你停下來深呼吸,然後真正試著集中精神同時在兩個不同抽象層次進行思考,否則永遠不知道發生了甚麼事。

另外我有很好的理由嘲笑那些使用關鍵字過濾履歷的面試者。我從未看過哪個會用 Scheme、Haskell 和 C 指標的人,不能在兩天內熟悉 Java 並寫出超越 5 年 Java 經驗老手的程式碼。不過跟一般人力資源部門的懶人解釋似乎是徒勞無功的。

但 CS 學院的 CS 任務該怎麼辦呢?他們並不是職業學校呀!訓練人們到業界工作並不應該是他們的任務。他們會說這是由社區大學和針對轉職工作者的政府再教育計畫處理的。他們應該是提供基本工具讓學生可以生活,而不是為他們第一週上班作準備。不是嗎?

Cs1.png

還有,CS 關乎證明(遞迴)、演算法(遞迴)、語言(lambda 演算)、作業系統(指標)、編譯器(lambda 演算),所以不教 C 和 Scheme 課程的爪哇學校其實也沒有在教資訊科學。對於真實世界來說,函式 curry 化的概念或許對真實世界沒什麼用,但對 CS 研究所來說顯然是必要資格。我不能理解為何 CS 學校課程委員會的教授,竟然會讓他們的課程沈淪至此,不僅無法產生有用的程式員,甚至不能產生可能獲得博士學位並與他們競逐教職的CS研究生。噢,等等,或許我真的瞭解原因了。

事實上當你回頭研究學術界在 Java 狂熱時代所進行的討論,就會注意到最大的議題為 Java 是否簡單到足以作為一種教學語言。

我的天呀,他們正試著讓課程更進一步的簡化,我這樣想著。為何不乾脆把所有東西都用湯匙餵給學生算了?讓我們再請助教幫他們寫考卷,如此就不會有人落跑到美國研究去了(譯註:American Studies,研究美國文化、社會等等的單位)。如果課程已被仔細地設計,讓所有東西都變得比原本更容易,怎能祈求有任何人可以從這學到任何事情?看起來似乎有個工作小組會在進行某個任務(PDF文件),想要找出某個簡化後的 Java 子集來教育學生,這個計畫製作簡化的文件,小心地隱藏所有 EJB/J2EE 廢話不讓學生稚嫩的心靈接觸,因此不再需要讓他們的小腦袋去擔心任何連簡單無比的 CS 問題集都不用做的課程。

至於 CS 系所為何如此執著於簡化課程,最好的解釋是這樣能空出更多時間來教授真正的 CS 觀念,不過這得假設不需要花兩堂課對學生說明 Java intInteger 間的差異。嗯,假設真是如此,6.001 課程可以給你一個完美的答案:Scheme,一個教學用語言,它是如此的簡單,對聰明的學生來說十分鐘內就可以教會,然後你可以用剩下的整個學期去教固定點理論。

哈!

我要回到0與1的世界了。

(你有1嗎?你幸運的混蛋!我們拿到的全是0)


你是個大三學生嗎?而且能瞬間弄通一個遞迴演算法,或用指標實作鍵結串列的速度和在白板上寫一樣快嗎?看看我們在紐約的[暑期實習]!到期日是二月一日。


這些網頁的內容為表達個人意見。
All contents Copyright © 1999-2006 by Joel Spolsky. All Rights Reserved.