Seibel:你是怎么開始編程的?
Bloch:我想這是受益于我的家庭影響。我父親是Brookhaven國家實(shí)驗(yàn)室的化學(xué)家。當(dāng)我上小學(xué)四年級的時候,他參加了一個程序設(shè)計培訓(xùn)班。當(dāng)然在那個時候,電腦都是放在玻璃窗背后的大型機(jī),你只能把寫好的程序卡片交給操作員。雖然沒法兒親自動手,但我還是被電子計算機(jī)可以幫助你做事兒這一點(diǎn)震撼了。所以,我在父親上課的那段時間,跟他學(xué)了一點(diǎn)兒Fortran。
Seibel:那大概是哪一年?
Bloch:我想是1971年。直到很多年以后我才真的對程序產(chǎn)生了強(qiáng)烈的興趣。讓我產(chǎn)生興趣的當(dāng)然是分時系統(tǒng)。長島有一臺DEC system-10電腦,供Suffolk縣內(nèi)所有的學(xué)校使用。Nassau縣也有一臺。很神奇的是,很多著名人物的事業(yè)都是從這兩臺DEC system-10電腦開始的。
你的程序一旦有交互,就會有Bug。大概是從1973~1976年,那時候我跟其他人一樣,在寫B(tài)ASIC程序。我就是從那時開始正式寫程序的。你知道嗎,我還保存著當(dāng)年寫的程序,是印在電信打印紙上的。如今回頭再看這些程序的時候我發(fā)現(xiàn),我代碼風(fēng)格中的某些部分從那個時候起就一直沒變過。
Seibel:你還記得你寫的第一個有趣的程序是什么嗎?
Bloch:噢,我記得那是1977年7月4日,我為經(jīng)典的二十問游戲?qū)懥艘粋程序,叫“猜動物”。這個程序包含一個二叉樹,是非題位于它的內(nèi)部節(jié)點(diǎn),動物位于它的葉節(jié)點(diǎn)上。如果用戶所提的動物是葉節(jié)點(diǎn)上沒有的,它會向用戶提出是非題,通過區(qū)別新動物和它猜出的錯誤動物之間的差異來了解新動物。二叉樹保存在硬盤上,這樣程序可以越來越“聰明”。
我當(dāng)時想,“天啊,真酷,程序真的能學(xué)習(xí)!边@是我一生難忘的瞬間。我還記得另一件事。當(dāng)時我在高中,應(yīng)該是10年級吧。是關(guān)于DEC system-10的。當(dāng)時不允許我們編寫現(xiàn)在叫做即時消息軟件的東西,因?yàn)樗鼈儗ο到y(tǒng)資源的消耗實(shí)在太大了。
Seibel:如果時光能夠倒流,可以一切從頭來過,有什么東西是你真的希望改變的?Basic對你來說太簡單了?其他還有什么?
Bloch:我沒什么遺憾的,實(shí)際上Basic很有趣。我覺得Dijkstra對Basic的看法是完全錯誤的。原諒我這么評價已故的人,愿他在天堂安息。我知道很多非常好的程序員,他們是從BASIC編程開始的,因?yàn)槟鞘撬麄兡苷业降奈ㄒ坏恼Z言。
然而我覺得使用多種語言是件好事。上大學(xué)的時候,我用很多語言編程。每門課都可以用一門語言。在數(shù)學(xué)課或者理工科課上,應(yīng)該用Fortran。那時候編程課學(xué)的都是Pascal、SAIL、Simula或者類似的東西。在人工智能課上,用LISP。
不過也許我應(yīng)該學(xué)更多的語言。有意思的是,一開始我對面向?qū)ο蟛⒉桓忻,直到那個二十問游戲開發(fā)快結(jié)束了,我才真正對面向?qū)ο笥辛烁杏X。嚴(yán)格來說,Java才是我真正使用的第一種面向?qū)ο笳Z言,某種程度上是因?yàn)槲也惶胗肅++。
Seibel:那是什么時候?
Bloch:那是我1996年加入Sun公司時。我覺得要是我能更早學(xué)習(xí)這些概念就好了。我不認(rèn)為這些概念都是好的。面向?qū)ο蠛苡幸馑迹袃蓪雍x。第一,它意味著模塊化。模塊化是非常好的。但是我不認(rèn)為這是創(chuàng)造面向?qū)ο蟮娜藗兊膶@D憧梢匀タ匆郧暗奈墨I(xiàn),例如,Parnas關(guān)于信息隱藏的論述,就會發(fā)現(xiàn)這種概念可以看作面向?qū)ο缶幊讨蓄惛拍畹囊环N抽象的原型。第二,它意味著繼承,我認(rèn)為繼承有利也有弊,這跟如今很多人的使用感受一致。
另外,我應(yīng)該進(jìn)入更多的領(lǐng)域,計算機(jī)科學(xué)領(lǐng)域內(nèi)外都應(yīng)涉獵。你學(xué)的東西越多,開始得越早,對你越好。我一直沒有真正做過的就是GUI編程,在某種程度上說我應(yīng)該強(qiáng)迫自己做做看。但是由于種種原因,如這些年來開發(fā)庫代碼,構(gòu)建他人可以使用的代碼塊,這些事情已經(jīng)占據(jù)了我的大部分時間。這樣算來,我做數(shù)據(jù)結(jié)構(gòu)和算法等方面的工作已經(jīng)有幾十年了。
Seibel:有什么書是所有程序員都應(yīng)該看看的?
Bloch:《設(shè)計模式》無疑是一本,雖然我對它的感情有點(diǎn)復(fù)雜,但是我還是認(rèn)為每個人都應(yīng)該讀一下。書中列出了通用的詞匯,也提出了很多好的創(chuàng)意。另一方面,這本書有點(diǎn)兒像方法和語言的大雜燴,內(nèi)容也有些過時了。但是我認(rèn)為它絕對值得一讀。
另外一本書是《Elements of Style》,它甚至不是一本編程書。為什么要看這本書呢?理由有兩條。首先,每個軟件工程師工作中很大一部分是寫文檔。如果你無法寫出精確、統(tǒng)一、易讀的說明書,那么沒人會去用你的產(chǎn)品。所以說可以改善你寫作風(fēng)格的東西都值得借鑒。其次,該書里面的大部分思想都適用于編程。
我的荒島列表有點(diǎn)古怪。例如,最重要的書是Herry Warren寫的《高效程序的奧秘》(Hacker’s Delight)。
Seibel:這是一本位操作(bit-twiddling)書?
B loch:是的。我愛位操作,這跟我的工作有關(guān)聯(lián)。如果你寫庫、編譯器、底層圖形代碼或者加密代碼,這本書是不可或缺的。Warren把曾經(jīng)口口相傳的東西放在一起,用嚴(yán)謹(jǐn)?shù)臄?shù)學(xué)去進(jìn)行驗(yàn)證。這本書出版的時候,我被震驚了。
當(dāng)然還有Knuth的《計算機(jī)程序設(shè)計藝術(shù)》。事實(shí)上,我從來沒有讀完這一套書,至少沒有從頭到尾看過。但當(dāng)我研究某個具體算法的時候,我就去看他會怎么說。往往可以得到我想要的東西,這套書太全面了。
但是我沒有能力、也沒有時間去讀完整套書,所以如果我告訴你我讀完了,那么我就是在說謊。我覺得還有一本非常好的老書,是Kernighan和Plauger寫的The Elements of Programming Style。書里面的例子都是用Fortran IV和PL/I寫的,所以有點(diǎn)過時。不過,雖然這本書這么老,但里面的思想?yún)s從未過時。
另外一本老書是Frederick Brooks的《人月神話》。這本書都出版40年了,里面的思想仍舊同出版時一樣有影響力。閱讀它是一種快樂,每個人都應(yīng)該讀一下。這本書的主要信息是“給一個延期的項(xiàng)目加人,會讓它延期得更加厲害”,今天這一點(diǎn)仍舊是正確的。里面還有其他很多重要的觀點(diǎn)。有些細(xì)節(jié)雖然過時了,但仍值得一讀。
現(xiàn)在每個人都必須要學(xué)習(xí)并發(fā)編程。所以應(yīng)該看看《Java并發(fā)編程實(shí)踐》這本書。雖然標(biāo)題中有Java,但是很多內(nèi)容并不限于任何具體的編程語言。
Seibel:這就是你和Brian Goetz合著的那本書?
Bloch:我的名字是印在封面上的,但是我提到它的原因恰恰是因?yàn)檫@不是我寫的書。第一作者是Brian,第二作者是Tim Peierls,制定Java并發(fā)標(biāo)準(zhǔn)JSR-166的每一個人也都是這本書的作者。把我的名字印在了封面上僅僅是出于禮貌,我貢獻(xiàn)了些材料,但是沒有正式參與編寫此書。
噢,還有一本:《韋氏學(xué)院詞典(第11版)》。我去哪里都帶著它。這倒不是你實(shí)際上要讀的東西,但是我說過,寫程序的時候,必須能命名好變量。你的文筆必須好。沒有好的字典,我就會覺得少了點(diǎn)兒什么。
Seibel:除了命名好變量,盡量少的復(fù)制粘貼以外,你經(jīng)驗(yàn)豐富后,還有哪些寫程序的習(xí)慣改變了?
Bloch:隨著年齡的增長,我逐漸意識到編程不僅僅是讓程序運(yùn)行而已;編程是創(chuàng)造一個易于理解的、可以維護(hù)的、高效的作品。一般來說,我發(fā)現(xiàn),干凈整潔的代碼,往往運(yùn)行起來更快。這與流行觀點(diǎn)正好相反。而且即使它們不快,也可以很容易地讓它們變快。正如人們所說的,優(yōu)化正確的代碼比改正優(yōu)化過的代碼容易多了。
我的一些改變是跟具體語言相關(guān)的。每種語言都提供了一個工具箱。你要使用正確的工具,在這種語言中正確的工具在另外一種語言中可能不是最好的。舉一個簡單的例子:如果你用Java 5,使用枚舉來代替整數(shù)常量或者布爾常量可以大大簡化程序,讓它更安全,更可靠。
Seibel:說到這兒,你能否談?wù)勅绾文芸焖偈煜ひ环N新語言?
Bloch:這跟人類的語言很類似。一種方法是學(xué)會很多語言。如果你已經(jīng)熟悉意大利語和西班牙語,那么學(xué)葡萄牙語就不需要花太多時間了。你知道的越多,你能吸收的就越多。
學(xué)習(xí)一種新語言的時候,要利用以前所學(xué)的語言的功底,但是也要保持開放的心態(tài)。有些人執(zhí)著于一種理念:“這就是寫所有程序必須遵循的方法!蔽也徽f是哪種語言,但是某些語言,出于某種原因,令人執(zhí)著于這樣的理念。當(dāng)他們開始學(xué)習(xí)新的語言的時候,他們批評這種語言跟真正的神的語言的所有不同之處。當(dāng)他們使用新的語言時,他們極力使用真正的神的語言的方法去寫。這樣,你就會錯過這個新語言真正的獨(dú)特之處。
這就像你本來只有一個榔頭,有人給了你一個螺絲刀,你說:“唉,這不是一把好榔頭,但是我應(yīng)該可以倒著抓住螺絲刀,用螺絲刀把來砸東西。”你得到了一個很爛的榔頭,但事實(shí)上它是一把很不錯的螺絲刀。所以你應(yīng)該對所有事物保持開放和積極的心態(tài)。當(dāng)然,最重要的是代碼!代碼!代碼!要多用語言,這樣才能學(xué)得更快。
Seibel:為什么人們對所選的計算機(jī)語言那么虔誠?
Bloch:我不知道。但是選擇一種語言時,所考慮的不僅僅是一系列技術(shù)上的權(quán)衡,而是在選擇一個社群。這就像選擇一個酒吧。沒錯,你希望去一個提供美酒的酒吧,但是美酒不是最重要的。主要是那個酒吧里都有什么樣的人,他們在談?wù)撔┦裁。選擇計算機(jī)語言也是這樣的。時間一長,就這門語言也形成了一個社群,社群里不僅僅有人群,還有他們的軟件成果,如工具、庫等。這就是有些理論上看起來更好的語言無法成功的原因,他們無法在周圍構(gòu)建成功的社群。
Seibel:要是這么理解的話,Java非常有趣,它有兩個社群。一個是實(shí)現(xiàn)者和系統(tǒng)開發(fā)者,也就是在Javasoft、Weblogic或者類似地方工作的人們。另一個是所有用Java、應(yīng)用服務(wù)器、構(gòu)建好的框架來構(gòu)建商業(yè)應(yīng)用的人們。這兩個酒吧差別非常大。
Bloch:與Java或者其他語言關(guān)聯(lián)的社群很多。如果語言周圍沒有形成社群,這通常表明,要么這個語言無人問津,要么就還很不成熟。語言繁榮發(fā)展,就會自然地表現(xiàn)為出現(xiàn)越來越多各式各樣的社群。同時,如果對一門語言的投入總額增長了,那么它的價值也會相應(yīng)地增長。
這就像梅特卡夫定律(編者注:一種網(wǎng)絡(luò)技術(shù)發(fā)展規(guī)律,由3COM公司創(chuàng)始人、計算機(jī)網(wǎng)絡(luò)先驅(qū)羅伯特·梅特卡提出。):網(wǎng)絡(luò)的價值與用戶數(shù)量的平方成正比。這對于編程語言也適用。所有使用這種語言的用戶構(gòu)成社群,然后突然間出現(xiàn)了Eclipse,出現(xiàn)了FindBugs,出現(xiàn)了Guice。即使Java對你來說不是最好的語言,但是使用它有這么多附加的好處,所以你還是會創(chuàng)建社群,解決如何在Java中進(jìn)行數(shù)學(xué)編程,或者你需要的其他類型的編程方法。
Seibel:你有沒有過這樣的感覺:你越來越清楚那程序就是搞不定,到處都是這樣那樣的問題,幾乎令人絕望?
Bloch:當(dāng)然有過。寫書也是這樣的。每次開始一件事情的時候,我總想逃避。開始是最艱難的,有時候我會鼓勵自己:“加油Josh!這行你都干了三十多年了,你知道怎么能做到跟別人一樣好,不必瞻前顧后,動手吧!被蛘邔ψ约赫f:“你瞧,以前的一切你都做的挺好的,這次也錯不了!
Seibel:你剛才提到你的生活體驗(yàn)變寬廣了,這可能會影響編程,但是有沒有什么東西,是編程以外的體驗(yàn),但是幫助你成為了一個更好的程序員呢?
Bloch:當(dāng)然有。我認(rèn)為你能做好的每件事情都有這個作用。思想是沒有學(xué)科限制的。我想到了一個例子。我寫論文的時候,要對一種分布數(shù)據(jù)結(jié)構(gòu),RSM(Replicated Sparse Memory,復(fù)制型稀疏內(nèi)存)做一個分析。而做這個分析的基礎(chǔ)思想來自于我所上的化學(xué)課。那是一個動態(tài)平衡公式:如果系統(tǒng)里有一個動態(tài)的平衡關(guān)系,就可以寫出一個等式,“事物進(jìn)入一個特定狀態(tài)的速度,和他們離開這個狀態(tài)的速度相等!边@樣就得到了三個變量的三個等式,求解這三個等式,計算出來的結(jié)果和觀察到的這種復(fù)雜的分布數(shù)據(jù)結(jié)構(gòu)的行為恰好匹配。這就是我直接從化學(xué)里偷來用于計算機(jī)科學(xué)的思想。
你在生活中看到的很多東西,不管是架構(gòu)上的,即建筑物構(gòu)建的方法,還是在語言上的,即人們進(jìn)行溝通的方法,很多思想都是可以借用的。當(dāng)然包括數(shù)學(xué)。數(shù)學(xué)和編程相當(dāng)類似。所以要睜大雙眼,積極地吸收重組各種思想,這樣做絕對錯不了。