本文是Commmon Lisp专家Peter Seibel对Google公司首席Java架构师Joshua Bloch的访谈,谈到程序员应该看什么书、如何能快速熟悉一种新语言以及为什么说选择编程语言就像选择酒吧。
Seibel:你是怎么开始编程的?
Bloch:我想这是受益于我的家庭影响。我父亲是Brookhaven国家实验室的化学家。当我上小学四年级的时候,他参加了一个程序设计培训班。当然在那个时候,电脑都是放在玻璃窗背后的大型机,你只能把写好的程序卡片交给操作员。虽然没法儿亲自动手,但我还是被电子计算机可以帮助你做事儿这一点震撼了。所以,我在父亲上课的那段时间,跟他学了一点儿Fortran。
Seibel:那大概是哪一年?
Bloch:我想是1971年。直到很多年以后我才真的对程序产生了强烈的兴趣。让我产生兴趣的当然是分时系统。长岛有一台DEC system-10电脑,供Suffolk县内所有的学校使用。Nassau县也有一台。很神奇的是,很多著名人物的事业都是从这两台DEC system-10电脑开始的。
你的程序一旦有交互,就会有Bug。大概是从1973~1976年,那时候我跟其他人一样,在写BASIC程序。我就是从那时开始正式写程序的。你知道吗,我还保存着当年写的程序,是印在电信打印纸上的。如今回头再看这些程序的时候我发现,我代码风格中的某些部分从那个时候起就一直没变过。
Seibel:你还记得你写的第一个有趣的程序是什么吗?
Bloch:噢,我记得那是1977年7月4日,我为经典的二十问游戏写了一个程序,叫“猜动物”。这个程序包含一个二叉树,是非题位于它的内部节点,动物位于它的叶节点上。如果用户所提的动物是叶节点上没有的,它会向用户提出是非题,通过区别新动物和它猜出的错误动物之间的差异来了解新动物。二叉树保存在硬盘上,这样程序可以越来越“聪明”。
我当时想,“天啊,真酷,程序真的能学习。”这是我一生难忘的瞬间。我还记得另一件事。当时我在高中,应该是10年级吧。是关于DEC system-10的。当时不允许我们编写现在叫做即时消息软件的东西,因为它们对系统资源的消耗实在太大了。
Seibel:如果时光能够倒流,可以一切从头来过,有什么东西是你真的希望改变的?Basic对你来说太简单了?其他还有什么?
Bloch:我没什么遗憾的,实际上Basic很有趣。我觉得Dijkstra对Basic的看法是完全错误的。原谅我这么评价已故的人,愿他在天堂安息。我知道很多非常好的程序员,他们是从BASIC编程开始的,因为那是他们能找到的唯一的语言。
然而我觉得使用多种语言是件好事。上大学的时候,我用很多语言编程。每门课都可以用一门语言。在数学课或者理工科课上,应该用Fortran。那时候编程课学的都是Pascal、SAIL、Simula或者类似的东西。在人工智能课上,用LISP。
不过也许我应该学更多的语言。有意思的是,一开始我对面向对象并不感冒,直到那个二十问游戏开发快结束了,我才真正对面向对象有了感觉。严格来说,Java才是我真正使用的第一种面向对象语言,某种程度上是因为我不太想用C++。
Seibel:那是什么时候?
Bloch:那是我1996年加入Sun公司时。我觉得要是我能更早学习这些概念就好了。我不认为这些概念都是好的。面向对象很有意思,它有两层含义。第一,它意味着模块化。模块化是非常好的。但是我不认为这是创造面向对象的人们的专利。你可以去看以前的文献,例如,Parnas关于信息隐藏的论述,就会发现这种概念可以看作面向对象编程中类概念的一种抽象的原型。第二,它意味着继承,我认为继承有利也有弊,这跟如今很多人的使用感受一致。
另外,我应该进入更多的领域,计算机科学领域内外都应涉猎。你学的东西越多,开始得越早,对你越好。我一直没有真正做过的就是GUI编程,在某种程度上说我应该强迫自己做做看。但是由于种种原因,如这些年来开发库代码,构建他人可以使用的代码块,这些事情已经占据了我的大部分时间。这样算来,我做数据结构和算法等方面的工作已经有几十年了。
Seibel:有什么书是所有程序员都应该看看的?
Bloch:《设计模式》无疑是一本,虽然我对它的感情有点复杂,但是我还是认为每个人都应该读一下。书中列出了通用的词汇,也提出了很多好的创意。另一方面,这本书有点儿像方法和语言的大杂烩,内容也有些过时了。但是我认为它绝对值得一读。
另外一本书是《Elements of Style》,它甚至不是一本编程书。为什么要看这本书呢?理由有两条。首先,每个软件工程师工作中很大一部分是写文档。如果你无法写出精确、统一、易读的说明书,那么没人会去用你的产品。所以说可以改善你写作风格的东西都值得借鉴。其次,该书里面的大部分思想都适用于编程。
我的荒岛列表有点古怪。例如,最重要的书是Herry Warren写的《高效程序的奥秘》(Hacker’s Delight)。
Seibel:这是一本位操作(bit-twiddling)书?
B loch:是的。我爱位操作,这跟我的工作有关联。如果你写库、编译器、底层图形代码或者加密代码,这本书是不可或缺的。Warren把曾经口口相传的东西放在一起,用严谨的数学去进行验证。这本书出版的时候,我被震惊了。
当然还有Knuth的《计算机程序设计艺术》。事实上,我从来没有读完这一套书,至少没有从头到尾看过。但当我研究某个具体算法的时候,我就去看他会怎么说。往往可以得到我想要的东西,这套书太全面了。
但是我没有能力、也没有时间去读完整套书,所以如果我告诉你我读完了,那么我就是在说谎。我觉得还有一本非常好的老书,是Kernighan和Plauger写的The Elements of Programming Style。书里面的例子都是用Fortran IV和PL/I写的,所以有点过时。不过,虽然这本书这么老,但里面的思想却从未过时。
另外一本老书是Frederick Brooks的《人月神话》。这本书都出版40年了,里面的思想仍旧同出版时一样有影响力。阅读它是一种快乐,每个人都应该读一下。这本书的主要信息是“给一个延期的项目加人,会让它延期得更加厉害”,今天这一点仍旧是正确的。里面还有其他很多重要的观点。有些细节虽然过时了,但仍值得一读。
现在每个人都必须要学习并发编程。所以应该看看《Java并发编程实践》这本书。虽然标题中有Java,但是很多内容并不限于任何具体的编程语言。
Seibel:这就是你和Brian Goetz合著的那本书?
Bloch:我的名字是印在封面上的,但是我提到它的原因恰恰是因为这不是我写的书。第一作者是Brian,第二作者是Tim Peierls,制定Java并发标准JSR-166的每一个人也都是这本书的作者。把我的名字印在了封面上仅仅是出于礼貌,我贡献了些材料,但是没有正式参与编写此书。
噢,还有一本:《韦氏学院词典(第11版)》。我去哪里都带着它。这倒不是你实际上要读的东西,但是我说过,写程序的时候,必须能命名好变量。你的文笔必须好。没有好的字典,我就会觉得少了点儿什么。
Seibel:除了命名好变量,尽量少的复制粘贴以外,你经验丰富后,还有哪些写程序的习惯改变了?
Bloch:随着年龄的增长,我逐渐意识到编程不仅仅是让程序运行而已;编程是创造一个易于理解的、可以维护的、高效的作品。一般来说,我发现,干净整洁的代码,往往运行起来更快。这与流行观点正好相反。而且即使它们不快,也可以很容易地让它们变快。正如人们所说的,优化正确的代码比改正优化过的代码容易多了。
我的一些改变是跟具体语言相关的。每种语言都提供了一个工具箱。你要使用正确的工具,在这种语言中正确的工具在另外一种语言中可能不是最好的。举一个简单的例子:如果你用Java 5,使用枚举来代替整数常量或者布尔常量可以大大简化程序,让它更安全,更可靠。
Seibel:说到这儿,你能否谈谈如何能快速熟悉一种新语言?
Bloch:这跟人类的语言很类似。一种方法是学会很多语言。如果你已经熟悉意大利语和西班牙语,那么学葡萄牙语就不需要花太多时间了。你知道的越多,你能吸收的就越多。
学习一种新语言的时候,要利用以前所学的语言的功底,但是也要保持开放的心态。有些人执著于一种理念:“这就是写所有程序必须遵循的方法。”我不说是哪种语言,但是某些语言,出于某种原因,令人执著于这样的理念。当他们开始学习新的语言的时候,他们批评这种语言跟真正的神的语言的所有不同之处。当他们使用新的语言时,他们极力使用真正的神的语言的方法去写。这样,你就会错过这个新语言真正的独特之处。
这就像你本来只有一个榔头,有人给了你一个螺丝刀,你说:“唉,这不是一把好榔头,但是我应该可以倒着抓住螺丝刀,用螺丝刀把来砸东西。”你得到了一个很烂的榔头,但事实上它是一把很不错的螺丝刀。所以你应该对所有事物保持开放和积极的心态。当然,最重要的是代码!代码!代码!要多用语言,这样才能学得更快。
Seibel:为什么人们对所选的计算机语言那么虔诚?
Bloch:我不知道。但是选择一种语言时,所考虑的不仅仅是一系列技术上的权衡,而是在选择一个社群。这就像选择一个酒吧。没错,你希望去一个提供美酒的酒吧,但是美酒不是最重要的。主要是那个酒吧里都有什么样的人,他们在谈论些什么。选择计算机语言也是这样的。时间一长,就这门语言也形成了一个社群,社群里不仅仅有人群,还有他们的软件成果,如工具、库等。这就是有些理论上看起来更好的语言无法成功的原因,他们无法在周围构建成功的社群。
Seibel:要是这么理解的话,Java非常有趣,它有两个社群。一个是实现者和系统开发者,也就是在Javasoft、Weblogic或者类似地方工作的人们。另一个是所有用Java、应用服务器、构建好的框架来构建商业应用的人们。这两个酒吧差别非常大。
Bloch:与Java或者其他语言关联的社群很多。如果语言周围没有形成社群,这通常表明,要么这个语言无人问津,要么就还很不成熟。语言繁荣发展,就会自然地表现为出现越来越多各式各样的社群。同时,如果对一门语言的投入总额增长了,那么它的价值也会相应地增长。
这就像梅特卡夫定律(编者注:一种网络技术发展规律,由3COM公司创始人、计算机网络先驱罗伯特·梅特卡提出。):网络的价值与用户数量的平方成正比。这对于编程语言也适用。所有使用这种语言的用户构成社群,然后突然间出现了Eclipse,出现了FindBugs,出现了Guice。即使Java对你来说不是最好的语言,但是使用它有这么多附加的好处,所以你还是会创建社群,解决如何在Java中进行数学编程,或者你需要的其他类型的编程方法。
Seibel:你有没有过这样的感觉:你越来越清楚那程序就是搞不定,到处都是这样那样的问题,几乎令人绝望?
Bloch:当然有过。写书也是这样的。每次开始一件事情的时候,我总想逃避。开始是最艰难的,有时候我会鼓励自己:“加油Josh!这行你都干了三十多年了,你知道怎么能做到跟别人一样好,不必瞻前顾后,动手吧。”或者对自己说:“你瞧,以前的一切你都做的挺好的,这次也错不了。”
Seibel:你刚才提到你的生活体验变宽广了,这可能会影响编程,但是有没有什么东西,是编程以外的体验,但是帮助你成为了一个更好的程序员呢?
Bloch:当然有。我认为你能做好的每件事情都有这个作用。思想是没有学科限制的。我想到了一个例子。我写论文的时候,要对一种分布数据结构,RSM(Replicated Sparse Memory,复制型稀疏内存)做一个分析。而做这个分析的基础思想来自于我所上的化学课。那是一个动态平衡公式:如果系统里有一个动态的平衡关系,就可以写出一个等式,“事物进入一个特定状态的速度,和他们离开这个状态的速度相等。”这样就得到了三个变量的三个等式,求解这三个等式,计算出来的结果和观察到的这种复杂的分布数据结构的行为恰好匹配。这就是我直接从化学里偷来用于计算机科学的思想。
你在生活中看到的很多东西,不管是架构上的,即建筑物构建的方法,还是在语言上的,即人们进行沟通的方法,很多思想都是可以借用的。当然包括数学。数学和编程相当类似。所以要睁大双眼,积极地吸收重组各种思想,这样做绝对错不了。