程序员成才的关键——内在兴趣和善于发现

  本文是Common Lisp专家Peter Seibel对计算机科学家Guy Steele的访谈,谈到了他程序人生开启的历程以及程序员成才的关键。


  初涉编程

  Seibel:你是怎样接触编程的?

  Steele:嗯,当我还是个小学生时,我就已经深深迷恋科学和数学了,我读了很多这方面的书,比如Irving Adler的Magic House of Numbers,它是我的最爱。我也喜欢儿童科幻小说,比如DanngDunn系列等等。总的来说,我对科学和数学有着广泛的兴趣。所有我能找到的关于科学和数学的东西,我都读了,同时我也读到了一点关于即将到来的新奇的计算机的介绍。

  Seibel:你编写的第一段有趣的程序是什么?

  Steele:嗯,我首先学习了Fortran语言,不过在我开始学习IBM 1130汇编语言之后,事情才变得真正有趣。我能想起来的最早的有趣的程序是一段能产生上下文关键字索引的东
西。IBM为他们的用户手册提供一个被称作是快速索引的东西:给定一个关键字,你可以从一个按字母排序的索引中查找,关键字的前后是这个关键字的上下文的一些单词。

  Seibel:你在MIT很自在,但最终却还是去了哈佛读书,而同时又在MIT打工,这是怎么回事呢?

  Steele:我申请大学的时候,申请了三所学校,MIT、哈佛还有普林斯顿。我最想去的是MIT。三所学校同时都录取了我。波士顿拉丁学校的校长Wilfred L.O’Leary是个老派的学者。老先生人非常好,打电话给我父母说:“你们知道令郎拿着哈佛的通知书实际上却考虑去MIT吗?”他就这样向我父母施压,我父母转而对我施压,最终我决定去哈佛了。

  我父母继续找我的麻烦,让我去打一份夏季工,而不是在家待着——你知道,做父母的都会这样。我很清楚自己的兴趣是计算机,我可不想去快餐店摆弄汉堡包。我面试了打孔工的工作,并且自以为是完全能够胜任的。但是没有人愿意雇用我,部分原因是我还不满18岁,可找到后才明白。他们听了我的叙述后说:“不要打电话给我们,我们会打给你的。”然后就杳无音信了。

  大约7月初我听说MIT的BillMartin正在寻找Lisp程序员。我想:“啊哈,机会来了,我了解Lisp啊。”我过去经常出没于MIT的时候,从AI实验室搞到了一些Lisp文档的副本,我也曾偷偷溜进实验室摆弄过计算机。那些日子里实验室大门是敞开的,反越战抗议发生后门才被锁上。我在高中四年级时在IBM1130计算机上实现过我自己的Lisp程序。

  于是,我这个不知道哪里冒出来的小瘦猴儿,跑到BillMartin的办公室,从门口探进头说:“我听说你在招Lisp程序员。”他并没有嘲笑我,只是打量了我一下,然后说:“你得先做做我出的Lisp考题。”“没问题,现在考怎么样?”我就坐了下来,花了两个小时来答题。完成后我把试卷递给他,他用了十分钟浏览了一遍,然后对我说:“你被录取了。”

  编程导师

  Seibel:在你起步时有没有遇到对你很重要的导师呢?

  Steele:在拉丁学校期间我的数学老师对我的适当鼓励刺激很重要。9年级的RalphWellings,就是在那个感恩节周末借我书的那位老师,和我做了一个交易。他说:“我注意到你在所有数学测验中都得到了100分。我可以让你在每周的前4天数学课都待在计算机室,不过在第5天数学课的测试上你必须得到100分,否则,交易就自动终止。”看,这就是激励。在那年余下的时间中我变成了考试高手——我特别刻苦地学习数学,因为这能让我接触到计算机。更好的是,第二年我的数学老师没有与我做同样的交易,这正好,因为我对那一年的数学了解不多。他们做出了恰当的评估。我的老师都是非常好的老师,我要学什么他们总是为我大行方便。

  Seibel:在那之后,随着你更深入地学习计算机,有没有特别的人在这领域帮助你呢?

  Steele: 有,当然就是雇用我的Bill Martin。还有Joel Moses,他领导着Macsyma项目,我受雇于MIT期间就在这个项目组里。

  Seibel:在整个大学期间,你一直在做这个项目吗?

  Steele:是的,我在哈佛读书的时候就一直是MIT的一名雇员。在暑假时是一份全职工作,开学后它就变成了一份下午的兼职工作。我尽可能地把哈佛的课程安排到早上,这样我就可以搭乘地铁去MIT,用两三个小时来编程,然后再回去。

  Seibel:一直用Lisp做Macsyma项目吗?

  Steele:是的。具体说就是当Maclisp解释器的维护人员。Jon L.White原本同时负责解释器和编译器的工作。他后来成为了一位相当厉害的编译器大师,而我则负责解释器,这个分工不错。就这样,Jon L.White成了我的导师。Macsyma项目组里所有的人都很关照我。我也得以结识一些AI实验室的人,所以当我申请读MIT的研究生的时候,很容易就被录取了,因为他们已经了解我,并且知道我在干什么。

  Seibel:你得到了计算机科学学士学位?

  Steele:是的,我本来打算主修纯数学,并且都安排好了我的课程。后来发现我对什么无穷维巴拿赫空间完全没有感觉,简直要害死我了。幸好,我已经在业余时间学习了足够多的计算机课程,这让我可以在专业的时候很主动。确切地说,我转去修应用数学专业,而计算机科学是应用数学的一个分支,在哈佛应用数学又属于工程学的一部分。

  Seibel:如果有可能让你重新学习编程,你会有什么不同吗?有什么事情你希望更早一点完成的吗?

  Steele:并不是一开始在我的脑海里就有特定的目标。我对我选择的这条路也不后悔。回首往事,我想我是一个幸运儿,受惠于一系列有趣的巧合,或者说,恩赐。

  现在我意识到,实际上同时在MIT和哈佛的经历是很不寻常的。我可以跑来跑去,然后说:“这条河(编者注:哈佛大学与MIT只有一河之隔,即查尔斯河)那一边的教授是这样说的。”而这一边的教授就会说:“哦,别信他,你应该这么想。”这很快让我的视野更开阔。

  作为高中生就能进入MIT是另一个相当不寻常的经历。我15岁时就可以摆弄那些价值数百万美元的机器,在那时1百万元可真是一笔相当大的钱。所以,我当然没有抱怨,没有后悔,也不会有任何得陇望蜀的想法。我本性也是个随遇而安的,既来之,则安之。

  Seibel:与那时相比,对于编程的思维方式,有哪些大的改变?除了认识到冒泡排序不是最好的排序算法之外。

  Steele:我想对我来说,最大的变化是认识到你不可能了解运行在你计算机上的所有一切。有些事情绝对超出了你的控制,因为不可能了解所有软件的一切细节。而在上世纪70年代计算机仅仅有4K字节的内存,你完全可以做一个内存转储,然后一个字一个字地去检查是不是你期望的。阅读操作系统的源码,了解它是如何运行的自然也正常。我也确实这样干过——我研究过磁盘管理程序和卡片阅读机程序,然后实现了我自己的版本。我觉得我自己了解整个IBM 1130是如何运作的,或者至少可以说我了解我自己想了解的所有事情。不过现在你再也不能这样干了。

  编程参考书

  Seibel:在你学习编程的时候,有没有什么书对你特别重要?

  Steele:在70年代的书当然是Knuth的TAOCP《计算机程序设计艺术》。

  Seibel:你从头到尾地读过吗?

  Steele:差不多每页都读过,差不多。我做了几乎所有我能做的习题。一些被称作是高等数学之类的东西我不太明白,我做了些注释或跳过了那些我不懂的。不过头两卷和第三卷的大部分我都很认真地读过。还有Aho、Hopcroft和Ullman编著的那本算法书(编者注:是指The Desing and Analysis of Computer Alogorithms(《算法分析与设计》)一书)——我想我是从这里面真正学到如何排序的。我得从我的书库里查找一下,看看能不能还记得有什么别的书。我是个收集狂——这类书我都有。不过这两本是我首先想到的。还有Lisp的书。Berkeley和Bobrow编辑的III Lisp(编者注:III指IntformationInternational,Inc.):是主题各异的论文集,不过我从中学到了很多有意思的东西。然后我开始读《SIGPLAN公报》和《ACM通讯》。那些日子里的《ACM通讯》可是有很多真正的技术内容,非常值得一读。

  我要提及两件事。第一件,当我在拉丁学校开始对科学感兴趣的时候,我决定从事计算机科学相关的事情。有一天有个导师问我:“你考虑过成为ACM的学生会员吗?”我不知道他的名字。不过我从那时起就非常感谢他,这给了我很大的鼓励。

  而我上哈佛以后,每当早晨有点空闲时间,我就会去Lamont图书馆做两件事:按照我的方式,从后往前阅读《科学美国人》,或者从前往后阅读《ACM通讯》。对《科学美国人》,我特别注意MartinGardner的所有数学游戏专栏。对《ACM通讯》则阅读所有我感兴趣的文章。在1972年这本期刊还只有15年的历史,所以不难把它们全部都过一遍。

  Seibel:阅读所有文章在那时比在今天要容易得多,一个人还是希望了解整个领域的。

  Steele:是的,你有希望了解这个领域。有很多只有一页长短的文章,让你知道:“这儿有一项新的散打技术。”我读了很多这类的文章。

  Seibel:旧的文章我个人常常觉得不太容易理解,因为它们和一些旧硬件或者旧语言联系得比较紧密。

  Steele:是这样的,需要是创新之母——一个想法的出现是因为在一个特定的环境下需要它。过了一段时间,大众认识到这个想法很重要。然后你需要摆脱环境的局限,展现出核心思想本身凸显出来,这样就可以流行好几年了。“这个神奇的技巧可以按位逆转字。”他们给出了7090汇编语言的一些东西。有些很有趣的数学思想在里头,不过他们还不能从中抽象出来。

  Seibel:的确很多人从学校里开始,在指导下学习计算机科学知识。但是还有很多程序员是没有正规学历背景的,只是边干边学。对这个你有什么建议吗?你怎么开始阅读那些技术论文,如何抓住要点并理解它呢?应该从ACM最初读起,一直读到现在吗?

  Steele:嗯,首先,我得说通读《ACM通讯》并不是我刻意博览群书成为一名伟大的计算机科学家的计划。我阅读是因为我有兴趣,有内在的动力去学习那些资料。所以我觉得这里有两个因素:第一是有内在的动力,想要阅读它们,因为你有兴趣或者说你觉得能提高你的技能。

  另一个问题是你怎样才能发现好的东西?当然,对“好”的认识也是三十年河东,三十年河西。今年你觉得是真正好的十年后说不定过时了。我觉得你可以拜访一位曾经经验丰富的前辈,问他觉得什么才是好的东西。对我而言就是Knuth,就是Aho、Hopcroft和Ullman。还有GeraldWeinberg《程序设计心理学》,那本书今天还是非常值得读一读的。Fred Brook的《人月神话》也给我一些启示。

  那时候我流连于MIT书店的计算机科学书架,下决心每个月到那里去一次,去翻翻那些书架。今天你再去一个书店,它的计算机书架规模可能是那时的10倍了,不过其中大部分图书都是如何使用C或者Java的。但还是会有一部分理论背景、算法这类书。

  代码阅读

  Seibel:另一种阅读——我知道你认为很重要的——是代码阅读。你是怎么样以你的方式切入不是你编写的一大段代码的呢?

  Steele:如果那个软件我知道如何使用,但不了解内部的工作机制,我通常会选择一个特定的命令或者交互行为然后追踪下去。

  Seibel:执行路径吗?

  Steele:是的。如果我要开始阅读Emacs源代码的话,我会说:“让我们看看‘向前移动一个字符’的那部分代码吧。”即使我不能完全理解,我至少会知道它使用的一些数据结构以及缓冲区是怎么表示的。如果我足够幸运,我能找到缓冲区增加一个的地方。一旦我理解之后,我接下来会尝试“后退一个字符”、“删除一行”。通过我的方式就了解越来越多的使用方法或者交互,直到我觉得我能够按照这种方式追踪代码的其他更重要的部分。

  Seibel:“追踪”是指查看源代码在心里执行它呢,还是要在调试器中启动它,然后单步执行进去呢?

  Steele:两种方式我都会做,我会用单步调试器对付那些70年代或者80年代的小一点的程序。今天的问题是从启动程序到它真正可以做点什么,这中间有一段很长的初始化过程。所以更好的办法是找到主命令循环或者中央控制子程序,从那里开始追踪。

  Seibel:当你找到了那些以后,你是设置一个断点然后单步跟进去呢,还是仅仅在脑海中想象它们的执行过程?

  Steele:我更愿意做桌面检查——就是阅读代码想象它会做什么。如果我确实需要理解整段代码,我会坐下来试图按照我的方式来通读代码。不过你不能一上来就这样做,应该先在脑子中有了事情的组织框架。现在,如果你足够幸运,程序员会留下一些文档或者规则的命名,或者合理组织文件的顺序,方便你快速阅读他们的代码。

  合理组织文件的顺序

  Seibel:什么是合理组织文件的顺序?

  Steele:很好的问题。使我想起了诸如Pascal这样的程序语言的一个问题,Pascal是为只过一遍的编译器设计的,源文件中的过程倾向按照自底向上的方式组织,因为在使用过程之前你必须定义过它们。也就是说,阅读Pascal程序最好的方法实际上是从后面读起,因为这样你就会看到程序自顶向下的结构。现在(编译器)形式如此多样,你也就不能指望什么了,除非程序员有一颗很强的责任心,将一切事情安排得井井有条,有助理解。不过,第三点,我们现在也有很棒的IDE来帮助你查看交叉引用,也许程序的线性组织也不再是那么重要了。

  第四点,我个人非常不喜欢IDE的一个原因是,你看完了所有内容后,还是很难理解。在图形迷宫里乱窜,很难知道所有地方都走到了。但如果你得到的是线性顺序,就会确保所有事情都会梳理到。

  Seibel:那么在你写代码的这些日子里,你是不是尽量按照自顶向下来组织代码呢?高层函数出现在它们依赖的低层函数之前?

  Steele:我尽量表现高层的想法。最好的表现方法可能是展示一个中心的命令,控制的过程,以及向下面分发的事情。或者,重要的事情可能是首先要展现数据结构,或者说较重
要的数据结构。重点是要像讲故事那样去表现想法,而不是只罗列一堆代码在那里。

  在MIT工作时,一件很棒的事情是可以随意访问到没有加密的代码,它们全是非常聪明的黑客作品。于是我读过了ITS操作系统,也读过了TECO的实现和Lisp的实现。还有第一个相当漂亮的Lisp格式打印程序,是BillGosper编写的。事实上,我在读高中的时候就读过它们,还试图复制一些到我个人的1130实现当中。

  如果没有接触到在其他机型上的现有Lisp实现,我一定不能为1130实现Lisp的,我根本就不知道怎么做。这是我个人教育的一个很重要的部分。时至今日,我们面对的部分问题是软件已经变得很有价值了,大部分软件都是商用的,也就是说我们不再有可作为免费例子的优秀代码来参考了。开源运动在某种程度上扭转了这一点。如果你愿意,你可以深入阅读Linux的代码。在我那个时候阅读TeX的代码是一项很有意义的练习,因为它是一大块良好组织的、易于调试的代码。

  本文节选自人民邮电出版社北京图灵文化发展有限公司出版的《编程人生》一书。该书是当今15位大师级计算机程序员的访谈录,重点介绍了他们的编程感悟。特此感谢图灵公司授权。

it知识库程序员成才的关键——内在兴趣和善于发现,转载需保留来源!

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。