计算机科学与人物

谦卑的程序员-Edsger W. Dijkstra(zz)

2011年11月19日 阅读(520)

       【原题】 The Humble Programmer

【译题】谦卑的程序员

【作者】Edsger W. Dijkstra

经过一系列巧合,我在1952年春天的第一个早上正式开始了职业编程领域,而且就我所了解,我是第一个在我们国家做这一行的荷兰人。在回顾最叫人惊奇的事上,就是编程职业缓慢的涌现出来,至少在我那部分的世界中是如此,一种于今让人难以想象的缓慢。但是我很感谢来自那个“建立了不容置疑的缓慢的”时期的两个生动回忆。

在编了大概3年程序后,我和 van Wijngaarden 作了一次讨论,他那时是我在 Amsterdam 数学中心的老板,那是一次我会终身感激他的讨论。问题是(The point was that)我同时被要求在莱顿大学(the University of Leiden)学习理论物理,而且我发现这两项活动越来越难以相处。我不得不接受,要么停止编程而变为一个真正叫人尊敬的理论物理学家,要么把我对物理学的研究带入到交差了事的状态(a formal completion only, with a minimum of effort),而且变为…..,是的,什么?一个程序员?不过那是一个值得尊敬的职业么?毕竟话说回来,什么是编程呢?哪里有令人信服的知识得以支持它,说编程是一个智力上令人尊敬的学科?我非常清晰的记得我是多么羡慕我的搞硬件的同事们,当被问及其专业能力时候,他/她们至少可以指出知道关于真空管,放大器以及其余的所有事,此时我感到的是,当面对那个问题,我只有交白卷了(I would stand empty-handed)。充满了忧虑,我敲开了 van Wijngaarden 办公室的门,问他我是否可以“对他说一会儿”;当我数小时后离开他的办公室时,我是另一个人了。在静静的听了我讲述的问题之后,他同意到目前为止还不太有编程学科,不过之后他继续安静的解释这里要说到的自动计算机,我们还仅仅是在开端,我就不可以是使得编程成为一个值得尊敬的学科的那些人当中的一个么?这成为我人生的转折,并且我尽其所能的快速的形式上完成了我对理论物理的研究。上述故事的一个寓意当然是说,我们在给年轻人建议的时候必需小心又小心;有时候年轻人会跟着建议走的!

另一个两年过去了,在1957年,我结婚了,而且荷兰的结婚仪式要求你陈述你的职业,我就说我是一个程序员。但是 Amsterdam 镇市府当局基于没有这种职业的理由,不能够接受它。而且,不管信不信,我的结婚仪式的“职业”一栏显示了可笑的条目“理论物理学家”!

我所看到的编程职业在我的国家中涌向出来是如此之缓慢。从那时以后我看到了更多的世界,且我的一般印象就是在其它国家,除开日子可能有点不对外,增长模式几乎一样。

請允许我试着捕捉那些旧岁月的更加详细一点的情形,这是为了对今日的情形有更好的了解。当我们从事自己的分析时,我们可以看到有如此之多的通常的之于编程任务的本性之误解是可以回溯到那遥远的过去的。

最初的自动电子计算机都是完全唯一,单拷贝的机器,那些机器都是在有振奋人心氛围的实验研究室环境下造起来的。一旦自动计算机的设想存在,其实现就是对那时的电子技术的巨大挑战,而且有一点是可以肯定的:我们是不可以拒绝来自团体的激励“决定尝试而且构建如此奇妙的设备”。对设备的这些“奇妙的片段(fantastic pieces)”而言:某人的回忆中仅仅是可以对“最早的机器竟然还可以工作,至少有时候是这样”感到惊讶。全局性的问题是使得并保持机器可以正常运转(in working order)。带物理角度的自动计算机的眼光还是从在该领域中更早的科学社会(the older scientific societies)的名字中反应出来,比如计算机器协会(the Association for Computing Machinery ),或者,不列颠计算机社会(the British Computer Society)其清晰的名字指的就是物理设备。

可怜的程序员怎么办阿?好吧,说个最真真正正的事实:他不大可能被注意到。从事情的一方面来讲,最初的那些机器如此之大,你不大可能移动它们,除此以外,它们需要如此广泛的维护,从而非常自然的就是人们试图使用这种机器的地方,也就是这种机器被开发出来的同一个实验室。其次,他多少有点看不见的工作没什么魅力可言:你可以把机器显示给访客,这比把几页代码拿出去要壮观好几个数量级了。不过最重要的是,程序员他自己对其工作有一个非常摩登的观念:他的工作会导出“来自那个奇妙的机器的存在的”所有重要性。因为那时独一无二的机器,他太清楚他的程序只有本地重要性(local significance),同时也由于很明显的“这个机器只有有限的生命期”,他知道他作的工作中只有很少那么点将会有持续的价值。最后,还有另外一种境况(circumstance)对程序员对其自己的工作据意义深远的影响:一方面,出了不大牢靠外,他的机器通常太慢,而且其内存通常太小,即,他要面对的是一只小鞋子,同时在另一方面,其通常有些奇怪的命令代码要迎合最不可预料的构建(unexpected constructions)。而且在那些天中,许多聪明的程序员通过“他设法把不可能变到他设备约束中去(he contrived to squeeze the impossible into the constraints of his equipment)”的方式,从机巧(the cunning tricks)中导出了一个极好的智力上的满足。

两个从那些日子以来的对编程的意见主张(opinion)。我现在提到了它们,我稍后会返回到它们。第一个意见主张就是一个真正能够胜任的程序员应当据问题意识(puzzle-minded),并非常喜欢聪明的技巧;第二个意见主张是说,编程不过是“对计算过程有效性去从这个方向或其它方向作最优化(optimizing the efficiency of the computational process, in one direction or the other)”而已。后一个意见主张是“频繁发生的境况实在就是可得的设备是痛苦的小鞋子” 的结果,而且在那些天里某人总是遭遇到天真的期望说,一旦有了更有力的机器话,编程就不再是问题了,因为在那时“努力去把机器放到其限制内就不再是需要的了,而那却是程序之所以为程序之所有” ,不是么?但是在下一个十年,某些完全不同的东西出现了:有了更加有力的机器,不仅仅是在能力上多了一个数量级,甚至是数个数量级之多。不过取代 “我们发现了所有编程问题都一劳永逸的解决了”的状态,我们发现软件危机已近淹到了我们的脖子了!怎么来的?

有一个次要的原因:在一两个层面上现代机器本质上要不控制老机器更加困难。首先,我们有发生在不可预知和不可再现时刻的I/O中断;相比较,就的序列化机器可认为是一台“完全确定自动机(fully deterministic automaton)”,这是一个巨大的变化,而且系统程序员的许多白发见证了“我们不会是轻松的讨论有关那个特性产生的逻辑问题”事实。其次,我们有了装备有多层存储(multi-level stores)的机器,就对我们提出了策略管理的问题,虽说对这个主题有丰富的文献,还是很难琢磨的(in spite of the extensive literature on the subject, still remain rather elusive)。由于实际机器的结构变更,增加了的复杂性是如此之多。

但是我还是把这个称作次要原因;主要原因是…机器的能力变得比以前要高出几个数量级!相当坦率的来说:只要没有机器,那么编程也就不会是个问题;当我们有少数的弱小的计算机时,编程就是一个谈谈的问题了,并且现在我们有了巨型机(gigantic computers),编程不得不也变为同等巨大的问题。从电子工业没有解决任务单独问题的意义上来说,它仅仅是制造了它们,它用其产品产生出问题(In this sense the electronic industry has not solved a single problem, it has only created them, it has created the problem of using its products)。用另外一种办法来做:当可用的机器的能力是以大于1000为因子增长的时候,社会的雄心“对应用这些机器”也成比例增长(society’s ambition to apply these machines grew in proportion),而且正是可怜的程序员发现他正是在这个目的与手段之间存在张力的爆炸领域当中讨生活。硬件能力的不断增加,集合了其可靠性可能更甚的增加,使得程序员没多少年前做梦也不敢想的解决方案成为可能。而且现在,没几年以后,他不得不梦见那些解决方案,更糟的是,他还必需把这些梦变为现实! 我们发现的“自己身处一个软件危机之中”是一个奇迹么?不是,当然不是,而且你可能猜测,它甚至可能已近提前预见到了;不过伴随这次要预言的麻烦事当然就是,只不过过了5年你就确实知道了他们是对的。

然后就是在60年代中期,可怕的事情发生了:所谓的第三代计算机使得它们出现了。官方文档告诉我们它们的价格/性能比(price/performance ratio)成为设计的主要追求之一(one of the major design objectives)。但如果你把“性能”当作是机器不同组件的责任周期(duty cycle)的话,没啥东西会阻止你以一个“其中你的性能目标的主要部分是通过‘其必要性是有怀疑的内部家用开支活动’而达到的”设计而告终(little will prevent you from ending up with a design in which the major part of your performance goal is reached by internal housekeeping activities of doubtful necessity)。而且如果你对价格的定义是支付硬件的价格的话,没啥可以阻止你以一个“很难以对之编程的”设计而告终,对之编程的例子就是代码顺序可能以强制,不是在程序员前就是在系统前,早期绑定决策提供了确实不可解决的冲突的如此方式(And if your definition of price is the price to be paid for the hardware, little will prevent you from ending up wth a design that is terribly hard to program for: for instance the order code might be such as to enforce, either upon the progrmmer or upon the system, early binding decisions presenting conflicts that really cannot be resolved )。而且在很大程度上,这些令人不快的可能性看上去已经变作事实了。

当有了这些机器而且其功能特性是清晰的,我们中相当多的人必定会变得非常悲惨;至少我是这样的。仅仅去期望“这样的机器将会冲击计算社区”才是理性的,而且因此它们的设计和听上去的可能性一样非常重要。但是“表现出我所感到的如此严重缺陷的”设计 势将延缓计算科学的进步至少10年(But the design embodied such serious flaws that I felt that with a single stroke the progress of computing science had been retarded by at least ten years):在那时我在整个职业生涯中渡过了最黑暗的一周。可能现在最可悲的事情就是,即便经历了所有的这些年的挫折,仍旧有这么多人忠诚的相信,某些自然定律告诉我们机器就是要那样子的。通过对“有多少这种机器卖出去了”的观察,他们的争论归于安静,且从那种观察中得出一种安全的假象(the false sense of security),毕竟,设计不至于那么差劲。不过基于细致检查,那条防御线,就像讨论说“抽雪茄肯定有利于健康,因为这么多人都在这么做”,有同样的说服力量。

正是在这种联系中,我对“它不是通常在计算领域中的,对科学性的学术期刊发布最新宣布的计算机的评论, 就像我们评论科学出版物一样的(it is not customary for scientific journals in the computing area to publish reviews of newly announced computers in much the same way as we review scientific publications)”而感到遗憾:可以评论机器终归会是一重要的事。而且这里我要做一个告白:在60年代早期我写过这样的一个意图去提交给 CACM 的评论,不过虽然事实是将这个文本递交以征求其建议的少数同行,都敦促我这么做,我还是不敢这么做,担心对我或对编委而言,困难可能是太大了。这种压制是一种我越来越谴责自己的在我身上的怯懦行为。我所预见到的困难是通用可接受的准则的缺乏之结果,而且尽管我确信(was convinced of)我所选择以应用的准则之有效性。我担心我的评论将会被拒绝或者被作为“不过是个人品位的事(a matter of personal taste)”而弃之不用。我还是认为这样的评论会是非常有用的,而且我期盼见到它们的出现,因为它们被接受的出现将会是计算社区成熟的一个信号。我所以付出了上述对硬件场景关注的原因在于我有一种感觉,任何计算工具的最重要角度之一是其对那些试图去使用它的思考习惯之影响(one of the most important aspects of any computing tool is its influence on the thinking habits of those that try to use it),而且由于我有理由相信那种影响要数倍于通常所认为的之巨。让我们把关注转到软件场景。

这里的差异是如此之巨大,以至于要借助一些垫脚石。我痛苦的认识到本人选择的武断,我也请求您们在“考虑我对许多仍旧是未提及的努力之欣赏”时,不要下任何结论。最初有英格兰剑桥的 EDSAC ,而且我认为子程序库(a subroutine library )这个概念,在一开始设计那机器时就扮演了一个核心角色以及子程序库应当被使用的方式,是非常之令人震撼的。现在已经过了25年了,而且计算场景也也极大的改变了,但是基本的软件概念还与我们同在,封闭子程序这一见解(the notion of the closed subroutine )仍旧是编程中的核心概念。我们应当认识到封闭子程序是最重要的软件创新之一(the closed subroutines as one of the greatest software inventions);这一概念经历了共三代的计算机,而且其仍旧会继续经历几代,这是因为封闭子程序为“我们的基本抽象模式之一的实现”提供所需。抱憾的是,其重要性在第三代计算机的设计中被低估了, 在第三代计算机中,其算法单元的大量的明确命名寄存器显示了在子程序机制上有一个大的开销(the great number of explicitly named registers of the arithmetic unit implies a large overhead on the subroutine mechanism)。但即使那样也不会扼杀子程序这个概念,而且我们只能祈祷“这种突变不会变作遗传(the mutation won’t prove to be hereditary)”。

我愿意提到的软件场景中的第二个主要进展,就是 FORTRAN 的诞生。在那时 FORTRAN 的诞生还只是缘于一个大而蛮勇的计划(this was a project of great temerity ),而且负责它的人受到我们的极大尊敬。批评他们的“只有在经过了10年以后或者类似的广泛使用以后再表现出来的毛病”,这肯定是不公平的:谁能准确预测10年后的未来呢(groups with a successful look-ahead of ten years are quite rare)!在回顾中我们必需推举 FORTRAN 作为一个成功的代码技术,而几乎没有有效的对其产生之帮助(but with very few effective aids to conception),现在“当来到了把它(译注:指,FORTRAN 实在是一种成功的编码技术)看成是过期之时”是如此急迫的需要这种帮助。 我们之可以把 FORTRAN 存在过的事实遗忘的越早,其作为思想媒介之不再适合就越好(The sooner we can forget that FORTRAN has ever existed, the better, for as a vehicle of thought it is no longer adequate):它浪费了我们的智能(brainpower),其太危险因此对我们过于昂贵。FORTRAN悲惨的命运是由于其广泛的接受,精神上把千千万万的程序员束缚到我们过去的错误。我每天都祈祷说,我更多的编程伙伴们可以发现把他们自己从兼容性的诅咒中解放出来的手段。

我不大愿意略去不提的第三个计划是 LISP,一种有完全不同本性的神奇进取心(a fascinating enterprise of a completely different nature)。伴随其创立时的少数非常基本的原则,LISP已经显示出了卓越的稳定性。出了稳定性以外,LISP  在我们最精密计算机应用场景中作出了大量的担当(the carrier for a considerable number of in a sense our most sophisticated computer applications)。LISP 被开玩笑的描述为“以最聪明的办法去误用一台计算机(the most intelligent way to misuse a computer)”。我认为那种描述是一种很大的敬意,因为这种描述传达出了对解放的完全品位(I think that description a great compliment because it transmits the full flavour of liberation):它帮助了许多我们最有天赋的人去思考先前不可能去想的东西(in thinking previously impossible thoughts)。需要提到的第四个计划是ALGOL 60。当到目前为止FORTRAN 程序员仍旧是倾向于依据“他们所与之工作的特定实现,即是八进制和十六进制存储的流行(hence the prevalence of octal and hexadecimal dumps)” 去理解他们的程序语言,当对LISP 的定义仍旧是“语言所指为何,以及机器如何工作(what the language means and how the mechanism works)”的一个奇怪混合体,对算法的语言ALGOL 60 的著名报告是天才努力“将抽象更迈进了重要一步,以及以一种独立于语言的方式去定义一个程序语言(carry abstraction a vital step further and to define a programming language in an implementation-independent way)”的成果。某人也可以在其作者如此成功的“他们已经产生了,对其到底是否可以实现的严肃怀疑(they have created serious doubts as to whether it could be implemented at all)!”这方面作出争论。该报告光耀的展示了形式化方法 BNF 的能力,现在被认为是巴斯克-诺尔范式(Backus-Naur-Form),以及显示了仔细措辞的英语之能力,至少是在被某些象Peter Naur 这样聪明的人使用的时候是如此。我认为说“只有非常少的像这么短的文档才在计算社区中据有同等深远影响(only very few documents as short as this have had an equally profound influence on the computing community)”是公平的。在以后的岁月中以ALGOL与类ALGOL名字之易用,就像一个不受保护的商标,把其一些光环借给了一些很难相关的年轻计划,对其地位有些令人震惊的恭维。BNF 作为一种定义策略(a defining device)的能力要对我认为是该语言(译注:指 BNF ?)的弱点之一负责:一个画蛇添足的和不太有系统的语法现在可以被挤到很少页的定义中(an over-elaborate and not too systematic syntax could now be crammed into the confines of very few pages)。要是有一种策略能像 BNF 一样有强大,算法语言ALGOL 60的报告就可以短的多。除了那点外,我正越来越非常怀疑ALGOL 60 的参数机制:其允许程序员如此之多的组合自由(combinatorial freedom),即其自信是建立在对“来自程序员的强准则”需要上的(that its confident use requires a strong discipline from the programmer)。除了实施的昂贵外,它看上去还对我们有害。

最后尽管说这个主题不是不太令人愉快,我必须提及 PL/1,这是一种编程语言,其定义的文档有吓人的大小和复杂性。使用 PL/1肯定是像驾驶一架“在座舱内切换和控制操纵有7000个按钮”的飞机一样。当由其纯粹巴洛克式的编程语言“提醒你,这是我们基本的工具!”早已脱离了我们智力所及之时,我肯定是看不到我们是如何得以在我们的智力所及之内保持程序恒定增长了(I absolutely fail to see how we can keep our growing programs firmly within our intellectual grip when by its sheer baroqueness the programming language —our basic tool, mind you!— already escapes our intellectual control)。而且如果我得以描述 PL/1 可以对其用户产生的影响话,我头脑中出现的最接近喻就是麻醉药(a drug)。我记得在一次高级别编程语言的座谈会上有个自称是贡献者之一的人讨论了PL/1的定义。但是在一个小时的对于PL/1的赞颂演讲内,他努力的要求附加15个新“特性”,没有多少是很好的支持他的主要问题源,因为其包含了太多的“特性”。演讲者展示了所有叫人沮丧的附加和缩减的符号,好像他大脑停滞了一般只能要求更加的多的多的多的…当FORTRAN 被叫做是幼稚的混乱(an infantile disorder)时,随着危险肿瘤的不断增长,完全PL/1会变为致命疾病。

过去就谈到这里吧。但制造错误没什么意义(there is no point in making mistakes),除非我们可以从错误中学到东西。作为事实,我认为我们已经学的够多了,在不多的几年编程中一项活动就足以变得和其开始时面目全非(within a few years programming can be an activity vastly different from what it has been up till now),如此的不同以至于我们最好对这种休克有所准备。让我为你廓清可能的未来之一吧。初次一瞥,在可能已经在不远未来的这种编程眼光可能以全然不可思议的好来打动你(strike you as utterly fantastic)。因此让我也添加那种可能导致某人下“这种想象力可能是非常可行的(this vision could be a very real possibility)”结论的注意事项(considerations )。

这种想象力就是,在70年代完全结束以前(well before the seventies have run to completion),我们应当可以设计和实现这种类型的系统正在以许多年中只是我们对其付出的一个小百分比的代价损坏我们的编程能力,而且除此之外这些系统几乎没有故障。这两个改进是肩并肩前行的。在后一个方面中软件看上去和许多其它“更高的质量往往暗示了更高的价格”产品是不同的。那些希求真正可靠软件的人会发现,他们必需找到避免从故障开始的手段,作为结果就是编程过程将会变得便宜。如果你想要更有效的程序,你将会发现他们不应当把其时间浪费在调试排错上,他们不应当以介入故障作为开始(should not introduce the bugs to start with)。换言之:两个目标指向同一个变化。

如此剧烈的变化在如此短暂的周期内发生将会是一次革命,以及对所有“对未来的期望认为是最近过去的慢慢衍生”人--对某些没有成文的社会定律以及文化惯性有吸引力,这种剧烈的变更将有可能要会发生,其视角是负面的。不过我们都知道有时候革命确确实实就发生了!对这个的机会又在哪里呢?

看上去有三个主要的条件必需得到满足。整个世界必需让认识到对变化的需要;其次它所需要的经济必需足够的强;而且,第三,这种变化还必需是技术上可行的。让我以上述的顺序讨论一下这三个条件。

考虑到对软件的更大可靠性之需求的认识 ,我希望不再有异议。这只是在没几年前还是不同的:谈论一个软件危机就是亵渎神明。转机是在Garmisch的软件工程大会,1968年10月,那次会议产生了一种第一次公开认同有软件危机的感觉。而且到现在大体上认为说,设计任何大型复杂系统是一项非常困难的任务,而且无论何时你要遇到对这样的事业(undertakings)负责的人,你会发现他们非常关心可靠性议题,理所应当。简言之,我们的第一个条件(译注:指,整个世界必需让认识到对变化的需要)看上去得到了满足。

现在说说经济需要(Now for the economic need)。现如今某人常常遭遇到“在六十年代编程是一项实过于名的职业(an overpaid profession)”的观念,而且在之后的年岁中程序员的薪水可以期望是下降的。通常表现出这个观念通常是和不景气相联系的,但它却可以是某些不同和非常健康的一个符号,也即,过去年岁中的程序员可能没做好他们应该做好的工作。社会变得对程序员和其产品的表现失望了。但还有另一个权重大得多的因素。在目前的情形下,对一个特定的系统来说“”是非常普通的,需要支付给开发软件的价格是与硬件所需要的价格有相同数量级的,而且社会也或多或少的接受了这点。不过硬件制造者告诉我们在下一个十年,硬件的价格可以期望跌落到十分之一(with a factor of ten)。如果软件开发还继续保持笨拙和像如今一般昂股的处理,事情就会完全失去平衡。你不能期望社会去接受这点,并因此我们必需以更加有效的数量级去学习编程。把它放到另一种方式下:只要机器还是预算上最大的开支, 编程职业就会侥幸逃脱其笨拙的技术,但那把伞还是会迅速的合拢。简言之,我们的第二个条件看上去也得到了满足。

现在是第三个条件了:技术上是可行的么?我认为是的,而且我会对你给出6条论据以支持此主张。

对程序结构的研究要揭示出“那个程序,即便是对相同任务和相同数学内容而言的替代程序,在其智力易处理性上有极大差异(that programs —even alternative programs for the same task and with the same mathematical content— can differ tremendously in their intellectual manageability)”。多个规则已经被发现,“其发现的破坏性在于,既可严重削弱亦可完全摧毁程序的智力易操作性(violation of which will either seriously impair or totally destroy the intellectual manageability of the program)”。这些规则分两种。第一种是可以很机械的被强加的,即是说,可通过一个适当选择的程序语言的强加(Those of the first kind are easily imposed mechanically, viz. by a suitably chosen programming language)。例子就是排除goto语句以及排除多于一个输出参数。对那种第二类而言,我至少看到“但也可能是由于我本人所及的匮乏”没什么方法去机械的强加给它们,当它看上去需要某种类型的自动定理证明器(automatic theorem prover ),对之我没有存在的证据。因此,就现在和可能永远(for the time being and perhaps forever),第二种类型的规则把它们自己呈现当作是程序员所要求的学科元素(elements of discipline )。在我头脑中的某些规则是如此清晰,以至于它们可以被教授,以及“从来就不需要一个关于‘一给定的程序是否破坏了它们’的争论”。例子就是对“在没有提供一个对结束的证明,或是没有开始‘其变量不会被执行重复状态而破坏的’这种关联时,无需写下循环 (no loop should be written down without providing a proof for termination nor without stating the relation whose invariance will not be destroyed by the execution of the repeatable statement)”的需求。

我现在建议我们把自己限制在对“理智可驾驭的程序(intellectually manageable programs)”的设计和实施。如果有某人担心我们不能承受这种是太严苛了的约束,我可以消除他的疑虑:理智可驾驭的程序之种类,对包含许多非常现实的“之于任务有算法解决方案的问题(for any problem capable of algorithmic solution)”程序而言,仍旧是足够的丰富。我们必需不能忘记编程(make programs)不是我们的事,我们的事是,其能够展示一个期望的行为“设计计算指令的种类(design classes of computations)”。把我们自己约束在理智可驾驭的程序内的这个建议,是我宣称的6个论据中的头两个的基础。

论据一,当程序员仅需考“虑理智驾驭的程序”时,他就大大的容易作出选择了(as the programmer only needs to consider intellectually manageable programs, the alternatives he is choosing between are much, much easier to cope with)。论据二,一旦我们决定把我们自己限制到“理智驾驭的程序”子集内,我们需要考虑到的解决方案空间就一劳永逸的达到了一急剧减小的状态(as soon as we have decided to restrict ourselves to the subset of the intellectually manageable programs, we have achieved, once and for all, a drastic reduction of the solution space to be considered)。而且这个论据独立于论据一。

论据三是基于到程序正确性问题的构造方式(based on the constructive approach to the problem of program correctness)。

今日通常的技术就是先做出一个程序,然后测试它。但是:程序测试可以是一种非常有效的现实故障存在的方式,但是对现实其不存在却是先天不足的。显著提升一个程序的信任级别(the confidence level)唯一有效的办法就是,给出其正确性的有说服力的证据(give a convincing proof of its correctness)。不过你不应当现实作出程序,然后证明其正确性,这是因为其后对提供证明的需求只会增加可怜的程序员的负担。反其道而行的是:程序员应当让正确性证明和程序肩并肩的成长。论据三本质上是基于以下观察。如果你第一次问你自己“一个叫人服膺的证明之结构会是什么样子(what the structure of a convincing proof would be)”,而且找到了这样的一个证明,然后构建一个满足了这种证明需要的程序,然后这些所关心的正确性,原来就是非常有效的启发式指导(then these correctness concerns turn out to be a very effective heuristic guidance)。通过这种方式的证明只能在“当我们把我们自己限制在理智驾驭的程序内”时是可以应用的,但是这种方式给我们提供了“介于这些正确性中找寻一种符合要求的一个正确性”的有效手段(but it provides us with effective means for finding a satisfactory one among these)。

论据四必需是处于一种“需要去‘设计一基于程序长度的程序’的智力努力量存在其中的”方式下。已经建议说,某些种类的自然律告诉我们“所需的智力努力量是随程序长度而平方增长的(the amount of intellectual effort needed grows with the square of program length)”。(译注:基于胡塞尔的世界是由对象组成的现象学观点而产生的面向对象编程,是否是对这种自然律的应战?)。不过,谢天谢地,没人可以证明这条定律。这是因为它不必是真的。我们都知道在“一非常有限的推理可以覆盖大多数的案例(a very finite piece of reasoning can cover a myriad cases)”意义上而言的唯一精神工具,就是“抽象(abstraction)”;作为一个结果就是,对其抽象能力的有效探索必需被看作是一个有能力的程序员最重要的活动之一。在这种联系下可能指出“所以抽象的目的不是要含糊不清,而是要产生一种新的语法层次,在其中可以绝对的精确”是值得而为的。当然我已经试着找能“阻止我们的抽象机制不能足够有效”的寻基本原因。但是不管我如何努力,我都没有发现这样的一个原因。结果我就倾向于总结,到目前为止还没有被经验所反驳,通过对我们的抽象能力合适的应用,智力努力就需要考虑或者理解一个“不需要较程序长度比例做更多增长的(need not grow more than proportional to program length)”程序。但是这些投资的一个副产品可能有显著的多的实践上影响,而且事实上,就是我第四个论据所在(the basis of)。该副产品是识别出“在组成程序的整个过程中扮演了核心角色”抽象的许多模式。现在关于这些抽象模式的了解是足够了,其中每一个都值用一次讲课来介绍。当我认识到“当抽象模式的那些知识在15年前(译注:指50年代后半期)还只是常识时,以“从BNF 到句法制导编译器(syntax-directed compilers)”那一步为例,是可以没几分钟内迈出的,而不是几年”,这些抽象模式显示给我的是多么熟悉和清晰的知识阿。因此我提出我们最近关于重要的抽象模式的知识来作为第四个论据。

现在是第五个论据。这个论据和“在我们自己的思考习惯下而试图使用的工具所带来的影响”有关。我观察到一个文化传统,其所有可能性之根源自文艺复兴(the Renaissance),忽略这种影响,这种文化传统把人类看作是对人工制品而言最高的和自主的主人。但如果我开始分析我自己的以及我伙伴的思考习惯时,我就得到了,无论我是否喜欢,一个完全不同的结论,即是,我们试图使用的工具,以及语言或我们使用的用来表达或记录我们想法的观念,是主要的因素,完全决定了我们可以想什么或表达什么!去分析程序加诸于使用者思考习惯之上所产生的影响,以及到目前为止对于脑力是我们稀缺的资源之认识,它们共同给我们一种“用于比较各异编程语言的相关优点”之绳墨(a new collection of yardsticks )。有能力的程序员对自己的能力所限有清晰的认识(译注:作者指所观察到的上述文化传统);因此他完全谦卑的一步步去面对编程任务,而且在其它方面他也避免像躲避瘟疫一样的躲避机巧(avoids clever tricks like the plague)。众所周知的对话编程语言案例中,我被多处告知说一旦编程社区为之装备一个终端,就会发生一个特别现象,就是有固定名字所谓的“打趣者”(the one-liners)。它采取了两种不同形式中的一种:一个程序员把一个打趣程序放置在另一个的桌子上,并且或者他自豪的说出了打趣程序能做什么并追加了问题“你能对这个用更少的符号来编码么?”——就好像这有什么概念相关性似的!——又或者他仅仅问“猜它做了什么!”从这个观察中我们必需总结认为作为工具的这种对话编程语言是对机巧的公开邀请(an open invitation for clever tricks);并且虽然 这确实可对其某些吸引力作解释,即是说,对那些希望显示他们有多聪明的人来说,我很遗憾,不过我必须把这个认为是对可以就一门编程语言而言的,最该受到诅咒的事。另一个我们应该从就在不久的过去中汲取的教训就是,对“更丰富”或“更有力”程序语言的开发,从这所谓的“巴洛克丑八怪(baroque monstrosities)”(译注:指繁而不整,怪言怪行意义上的巴洛克风格)意义上来说是一种错误,这些丑陋的风格实在是无论从物理上还是精神上说都不可驾驭。我看到一个非常系统化和非常端正的编程语言的伟大前程(a great future for very systematic and very modest programming languages)。当我说“端正(modest)”,我是说,比如,不仅仅是ALGOL 60的 “for 语句”,甚而 FORTRAN的“DO循环”都可能发现自己由于太过巴洛克式而被舍弃。我已经和有经验的志愿者运行了少数程序实验,但是某些非常无计划和出乎所料的事出现了。我的志愿者中没有人发现明显的和最优雅的解决方案。给予切近的分析,这被证明是有一个通用源:他们重复的观念与“相关用于升级的控制变量(an associated controlled variable to be stepped up)”观念绑定的是如此紧密,从而他们对很是明显的倒是视而不见了(mentally blocked from seeing the obvious)。他们的解决方案不甚有效,难于理解,而且他们费了好久才找到了它们(译注:它们?)。这对我是一种展示,但也是一种震惊的经历。最后,在某一方面某人希望明日的程序语言将会与我们今日所使用的有巨大的不同:要比迄今为止“它们应当引导我们去在我们写下‘所有需要应对我们所设计的东西的观念上之复杂性’抽象的那种结构中反思 ”的不同还要大得多(to a much greater extent than hitherto they should invite us to reflect in the structure of what we write down all abstractions needed to cope conceptually with the complexity of what we are designing)。对我们未来的工具就适当的说道这里吧,这是第五个论据的基础。

作为一个旁白,我将会插入一个对那些“那些把编程任务的困难看成是对我们当前工具的不足性的徒劳挣扎的”人的警告,因为它们可能概括出说,一旦我们的工具将会充足的多的时候,编程就不再是个问题了。编程仍旧会非常的困难,因为一旦我们把自己从弯弯道道这个细节中解放出来(freed ourselves from the circumstantial cumbersomeness),我们会发现我们得以自由的面对这个目前远远超出我们编程能力的问题(译注:指智力有限性问题)。

你可以不同意我的第六个论据,因为不是这么容易去收集实验证据以对其支持的,该事实不会阻碍我对其有效性的认识。到目前为止我还没有提到“层级(hierarchy)”这个单词,但我认为“这是对所有‘嵌入了一个精致分解了的解决方案之’系统的一个核心概念”这样说是很公平的。我甚至可以进一步的写一篇有关其信仰的文章来,即是说,我们可以以一种令人满意方式解决的唯一问题是“最终承认一精细分解的解决方案(that finally admit a nicely factored solution)”。初一瞥,这个有关人类能力限制的观点可能打击了你,认为是一个关于我们境况的相当沮丧的观点,但我不是那么认为的,恰恰相反!学会和我们的限制一起生活的最好方式就是知道这些限制(The best way to learn to live with our limitations is to know them)。只有到对“以试图分解解决方案”而言足够现代的时候(By the time that we are sufficiently modest to try factored solutions only), 由于其它的努力不在我等掌控之中(the other efforts escape our intellectual grip),我们将会尽其所能的避开所有这些界面,以一种有益的方式去修复我们分解系统的能力。任何见过“编译阶段所谓‘代码生成’是如何得把大多数麻烦放置于命令代码的有趣属性 ”的人(how the majority of the troubles of the compiling phase called "code generation" can be tracked down to funny properties of the order code),会知道我头脑里的这类事情的一个简单例子。精细分解的解决方案之广泛适应性就是我的第六个和最后一个之于“可能发生于当前这个十年(译注:指70年代)的革命之技术可行性”的论据。

原则上我留给你自己来决定我的这种考虑的分量到底几斤几两,我很清楚的晓得我不能强迫任何其他人来分享我的观点。就像每一次严肃的革命一样,它会激起猛烈的反对,而且你可以问你自己去哪里才能期望保守派力量试图阻止这样的一个发展。我不会去期望它们主要的发生在大公司,甚或是计算机行业;我会希望是在那些提供了今日的培训的教育机构中,以及是在组织保守的那些计算机用户中,他们把他们的老旧程序看的很重以至于他们不认为有必要去重写并改进它们。在这种据说是对“中央计算设备对许多大学营的选择,太多时候是决定于带有‘对有如此多的小用户视而不见’的少数建立起来了但却是昂贵的应用 (that on many a university campus the choice of the central computing facility has too often been determined by the demands of a few established but expensive applications with a disregard of the question how many thousands of "small users") ”观察的联系中。作为一个太常见的例子,高能物理看上去拿走了科学社区余下的实验设备。最简单的回答当然就是对这种技术可能性断然拒绝,不过我恐怕你需要一个相当强的理由来这样说断然拒绝。没有什么反复保证,关切是可以从以下这样言辞中获得的:“今日平均程序员的智力天花板会阻止革命的发生(the intellectual ceiling of today’s average programmer will prevent the revolution from taking place):随着其他程序员是如此有效率,他也就在此没什么立锥之地了(with others programming so much more effectively, he is liable to be edged out of the picture anyway)”。

也可能有政治上的困难。即便我们知道如何教育明日的专业程序员,我们存在的社会是否允许我们这么做还是不确定的。教授一个方法论——远非传播知识(rather than disseminating knowledge)——的第一个效应就是强化了已经可能的能力(enhancing the capacities of the already capable),因此放大了智力中的差异。在教育系统被作为“一种用于建立平均文化的器具(an instrument for the establishment of a homogenized culture)”的社会中  ,其中金子不能从沙子里冒出来的(the cream is prevented from rising to the top),当代程序员的教育就可能不合政治的胃口了。

請允许我总结一下。自动计算机已经存在了四分之一个世纪了。它们已经由于其工具的能力而对我们的社会产生了巨大影响,但是就那种能力而言,其影响,相对于它们将会对文化历史中史无前例的智力挑战之深刻的多的影响,对我们的文化将不过是浮光掠影而已(but in that capacity their influence will be but a ripple on the surface of our culture)。层级系统看上去有以下属性:“某些物体被当作一个在某层次上不可分实体,在下一更低更细节级别中被当作一组合对象(something considered as an undivided entity on one level, is considered as a composite object on the next lower level of greater detail)”;结果就是,当我们把我们的关注从一个级别转向另一个更低的级别时,可以应用到各个级别的“空间和时间的自然属性(the natural grain of space or time)”就有数量级的减小。我们通过砖理解了墙,通过晶体理解了砖,通过分子理解了晶体,等而下之。作为一个结果 ,可以有意义的在一层级系统中作区分的层次数目,就有点和介于最大和最小属性的比率之对数相称了(kind of proportional to the logarithm of the ratio between the largest and the smallest grain)(译注:?)而且因此,除非这个比率非常大,我们是不可以期望许多层次的。在计算机科学中我们基本构建块是和时间小于一微妙的时间属性相关的(basic building block has an associated time grain of less than a microsecond)。我还不知道其它什么技术用到了1010或更甚:计算机,由于其惊人的快速,看上去是第一个提供给我们“高度层级化人工产品于其不但是可能的而且是必需的”环境。这种挑战,即是说,编程任务所面对的,是如此独特以至于这种新奇的体验可以交给我们关于自身很多很多。它也应该开阔我们对设计和创造进步的理解,它也应该给我们对驾驭组织我们的思想的任务更好控制(better control over the task of organizing our thoughts)。假设说它没有这样做,就我的品位而言,我们完全不应当去怪计算机!(to my taste we should not deserve the computer at all)

它已经给了我们一些教训,而且我选出了其中之一在这次谈话中作了强调,如下。我们应当做出一个好得多的编程饭碗,前提就是,表示出对其极其惊人困难的完全欣赏的方式处理编程任务(we approach the task with a full appreciation of its tremendous difficulty);前提就是,我们坚持谦虚和优雅的编程语言(we stick to modest and elegant programming languages),前提就是,我们尊重人类大脑的内在限制(we respect the intrinsic limitations of the human mind)以及作为一个非常谦虚的程序员去处理任务。

(完)

You Might Also Like