1952年初春的早晨,由于一系列巧合,我正式进入了编程界,成为了程序员历史上第一位荷兰人。回想起来,程序员作为一种职业,是以现在很难相信的缓慢速度出现的,至少在我所了解的范围内是这样,这让人非常惊奇。那个缓慢时期的两段清晰回忆让我心存感激。
在有了三年编程经验后,我和当时我在阿姆斯特丹数学中心的老板 A. Van Wijngaarden(译注:荷兰数学家和计算机科学家),进行了一场讨论,关于这场讨论我在有生之年都会感激他。讨论的焦点在于,我本来是要在编程的同时,在莱顿大学学习理论物理,但是当发现鱼和熊掌不可兼得时,我不得不做出选择,要么停止编程,成为一个名符其实的可敬的理论物理学家;或者把我的物理学研究敷衍了事,而成为一个…那个叫什么?程序员?但那是个受人尊敬的职业么?什么又是编程呢?它作为一门学科所需要的完备知识体系又在哪里呢?我非常清晰得记得自己有多嫉妒我从事硬件的同僚们,因为当被问到专业技能时,他们至少可以谈自己所知道关于真空管,放大器,和其他一些硬件的一切;而被问到这个问题时,我只能茫然无措。满心焦虑,我敲开了 van Wijngaarden 的办公室大门,问道:“是否能占用他一点时间”;而在几个小时后离开他办公室时,我整个人焕然一新。在耐心听完我的问题后,他同意当时并没有学科是关于编程的,但是他接下来解释说,自动化电脑会继续发展,而我们正处于摸索阶段,那我能不能成为先驱者之一,使编程在未来成为一个受人认可的学科呢?这成了我人生中的一个转折点,促使我尽快完成了我的物理学研究。上述故事的寓意是,我们必须谨慎地向年轻人提供意见,因为有时他们真的会听的!
荷兰婚礼仪式上有要求新人陈述职业的传统,而两年后的1957年,当我结婚时我宣告自己是一名程序员。但是阿姆斯特丹的市政当局没有接受,理由是并不存在程序员这样一种职业。不管你信不信,在我婚姻证书上“职业”这一栏里,可笑的写着“理论物理学家”!
关于程序员作为一种职业在我国的缓慢出现,就说这么多了。从那时起,我见识到了外面的世界,留下的总体印象是,尽管起步的时间不同,但是其他国家的发展模式是大同小异的。
让我尝试更多地回顾下昔日的一些细节,以期更好地理解现在的情况。现在我们对问题进行分析时,应该知道,关于编程任务很多常见误解是可以追溯到很久以前的。
Edsger W. Dijkstra
第一代的电子计算机是独特的机器,并且只能在各种进行开拓性试验的实验室里被找到。从人类见识了自动化计算机那天起,实现它就是对当时现有的电子技术一个巨大挑战,不过有一件事很确定,那就是我们不能否认那些致力于开发这些设备先驱们的勇气。这些设备是如此的令人惊奇,回想起来,至少是有时候,人们只能怀疑,这些机器是否真的运行起来了。最难解决的问题就在于让机器跑起来并让其保持工作秩序。一些较老的计算机科学学会的命名中依然反映着自动计算机硬件方面的当务之急,如美国计算机协会(ACM)和英国计算机协会,这些协会的名称中明确提到了物理设备。
那么可怜的程序员又是什么样的处境呢?实情是:他根本没有被人注意。一方面,第一代计算机是如此得笨重,以至于无法搬来搬去,同时,它们又需要大规模的维护,因此很自然的,人们就在发明这些计算机的实验室里使用它们。另一方面,程序员的工作既不为人所知又缺少魅力,在打动参观者的程度上,展示机器比展示几页代码要高出几个数量级。但是最重要的是,程序员以非常谦逊的眼光看待自己的工作:程序员工作的所有重要性都继承自硬件设备。因为每一台计算机都是不同的,程序员非常清楚,他的程序只有在特定计算机上才能运行,并且由于计算机的寿命有限,导致他的工作会随着机器的老化而丧失价值。最后,还有一种情况对程序员的工作态度产生了深远的影响:一方面,除了不稳定,他工作的机器一般还存在运行缓慢、内存太小等问题,这让巧妇难为无米之炊;另一方面,程序中通常又会存在少量古怪代码来应对突发的状况。在那些日子里,有很多聪明的程序员通过一些巧妙的方法,使他的设备可以完成一些本来不可能完成的任务,以这样的方式来获得智力上的巨大满足感。
关于编程的两种观点就起源于那个时期。我现在提下这件事,等下会回到这个话题。一种观点认为真正专业的程序员应该具有解决问题的头脑,并且非常喜欢聪明的伎俩;另一种观点认为,编程就是在某个方向上优化计算效率的过程。
后一种观点源自于设备落后的年代,那时候有些人简单的期望着,一旦机器变得更为强大,编程将不会成为难题,到那时想尽办法榨干机器的性能将不再有必要,这就是编程的目的,难道不是吗?但是下一个十年里发生了巨变,更为强大的机器被造出来了,不是一个数量级的强大,而是好几个数量级的强大。但是出人意料的是,我们并没有一劳永逸地解决所有的问题,反而发现自己处在了软件危机中!这是怎么回事呢?
一个小小的原因是:现代计算机在一个或两个方面比老式的计算机更难以操作。首先,现代计算机有I/O中断,中断的发生不可预知也不可重现,这个特性与能完全掌控运行过程的旧式计算机相比,是一个巨大的变化,但是这个特性会产生难以预料的逻辑错误,很多程序员花白的头发见证了这一点。第二,现在的计算机配置了多级存储设备,关于设备管理的策略,虽然已经有大量的文献,但是对我们来说仍然相当难以捉摸。关于计算机结构的变化所增加的复杂性就讲这么多了。
但是上面所举的只是“小”原因,真正大的原因是…现代计算机性能比原来强大了好几个数量级!可以不客气的说:当世上没有计算机的时候,根本就不会有编程问题;当我们有了几台性能弱小的计算机后,编程就出现小问题了,现在我们有了性能强大的计算机,编程自然变成了巨大的问题。在这样的发展过程中,电子产业非但没有解决一个问题,而是产生了问题,即使用产品所带来的问题。换种方式说,如果现有计算机性能增长了千分之一,那么社会对于使用这些机器的期望也会以同样的比例增长,而可怜的程序员会发现自己处于到底是目的优先还是方式优先的紧张选择中。硬件性能的提升,加上其可靠性甚至更急剧的提升,使得几年前程序员做梦都不敢想的问题变得可以实现。而几年后,他不得不梦见这个问题,更糟的是,他不得不将这样的梦变成现实!那么我们发现自己仍身处于软件危机中是不是一个奇迹呢?当然不是了,正如你猜测的那样,这些甚至是可以提前预知的,只不过这种小众预测的问题在于五年后你才能知道它是正确的。
接着在六十年代中期,有一件可怕的事情发生:所谓的第三代计算机出现了。官方的文献表示,性价比一直是他们主要的设计目标之一。但是如果你将机器众多组件的占空比作为“表现”的衡量标准,你会看到一个内存被必要性存疑的内部常驻活动所占据的设计。如果你对于价格的定义是硬件的价值,你会看到一个对其编程极其困难的设计:举个例子,无论对于程序员还是系统,用于执行的指令码早期绑定所带来的问题都不能真正得到解决。并且在很大程度上,这些令人不快的可能性看起来已经成为了现实。
当这样的机器宣布发售,其功能规格为人所知后,我们之中的不少人肯定相当难受,至少我是这样。第三代计算机的发行肯定会席卷计算机界,而人们更加期待它的设计能够尽量健全。但是因为这样一个有着如此严重缺陷的设计,让我感觉到计算机科学至少退步了十年:这也让我的职业生涯经历了最为黑暗的一个星期。也许最可悲的事情是,即使有了这么多年令人沮丧的经验,依然有如此多的人天真的相信计算机必须是这样。他们用机器的销量来打消自己的疑虑,并且从这种观察中得到使用这些机器是安全的错觉,毕竟,机器的设计不可能那样糟糕。但是仔细想想,这种被销量欺骗的安全感就和吸烟必须是健康的说法相差无几,因为吸烟的人很多。
正是这方面,我很遗憾,在发表对最新公布的计算机的评论时,计算机领域的科学期刊并没有习惯像其他科学出版物那样做出复查:对机器的复查至少应该同样重要。这里我要检讨:在六十年代早期,我写过这样的评论并准备提交给CACM,尽管我没有向同事们寻求建议,但他们极力主张我这样做,可我还是不敢,因为担心这样无论对我还是对编委会来说,困难都太大。是懦弱没有让我提交这样一份报告,对此我越来越自责。我预见到的困难是当时缺乏普遍接受的标准,虽然确信自己的标准是正确的,但我还是担心我的报告会被拒绝,或者被贴上“个人口味问题”的标签。我仍然认为这样的报告是及其有用的,并且渴望着它们的出现,因为它们的出现将代表着计算机界的成熟。
之所以对硬件保持上面提到那样的关注,是因为我相信影响那些使用者的思考习惯是任何计算工具最重要的作用之一,并且我有理由相信,这种影响力比预期的更为强烈。现在让我们的注意力回到软件上。
由于软件具有显著的多样性,我必须将自己限制在几个立足点上。这使得我做出的选择显得很武断,也让我觉得很痛苦,希望大家不要因此怀疑我对其他没有提到的努力的欣赏。
刚开始的时候,EDSAC 在英国的剑桥兴起,我对其起初让子程序库在机器设计和使用方法中发挥主要作业的观点印象深刻。接近25年后的今天,计算领域彻底的变化了,但是软件的基本观念还伴随着我们,闭合子程序的观念也还是我们编程的核心概念之一。我们应该认可闭合子程序作为最伟大的软件发明之一,它经历了三代计算机的发展并且仍将继续存活几代,因为它迎合了我们基本抽象模式的接口思想。遗憾的是,在第三代计算机的设计中,它的重要性被低估了,而这个设计中,大量明确命名为寄存器的算术计算单位揭示了子程序机制的广泛使用。尽管如此,也没有让子程序的概念就此消失,我们只能祈祷这种变化不会在下一代的计算机中被遗传。
我要讲的第二个软件业的主要发展是FORTRAN的诞生。在当时这是一个伟大而冒失的计划,负责这个计划的人们值得我们大声地赞美。因为大约10年后才日渐明显的外延错误用法而去责备他们是显然不公平的:能够成功预测十年后的团队相当罕见。当我们回顾过去时,必须把FORTRAN看做一项成功但是对其产生概念基本没啥帮助的编码技术,在需求如此迫切的现在,这项技术已经过时了。我们应该尽快忘记FORTRAN,对于思想的马车而言,它不再胜任:它浪费了我们的脑力,使用它过于冒险,因此也太过奢侈。FORTRAN的悲惨命运已经因为它广泛的接受度,影响了数以千计的程序员为我们过去的错误买单。我每天都祈祷,会有更多程序员小伙伴找到从通用性的祸害中解脱出来的方法。
第三个不能忽略的就是LISP,一个完全与众不同的迷人设计。基于LISP的几个基本原则使得LISP展示出了非凡的健壮性。除此以外,LISP成为了相当多的复杂计算机载体。LISP曾经被调侃为滥用电脑的最智能方法。我想这种描述是一种很高的赞美,因为它传递了解放的气息——它已经帮助我们之中最有天赋的人思考了之前不可能思考的东西。
第四个要提到的就是 ALGOL 60。到目前为止,FORTRAN程序员仍然倾向于从他们的开发中了解他们的编程语言——八进制的兴起和十六进制的衰落;而LISP的定义依然是一种令人好奇的混合体,其中包括这门语言意味着什么和这门机制是怎么工作的,《算法语言》那篇著名的报告中说道,ALGOL 60是真正努力去承载抽象概念至关重要的一步,再加上通过独立于语言之外的方法定义一门编程语言的成果。有人会说,ALGOL 60的作者们已经如此的成功,以至于他们自己引出这门语言是否可以实现产生的严肃疑问!那篇报告冠冕堂皇地展示了BNF范式(即现在人尽皆知的Backs-Naur-Form)的作用,和英语谨慎措辞的力量,至少是像Peter Naur一样聪明的人使用时。我觉得可以负责任地说,基本没有像它这么短而在计算机界有相同影响力的文档存在。人们习惯于使用用“ALGOL”或者是“类ALGOL”这样未经保护的标签,向大量基本不相关的年轻语言分享ALGOL的荣耀,这本身某种程度上就是对ALGOL惊人生命力的极大致敬。BNF作为一种严格定义的语言,它的长处导致了我个人认为是这门语言的缺点——过分精心制作并且语法定义不规则,很难在几页纸中完全说明。如果有个BNF般强大的设备,《算术语言》中那篇关于ALGOL60的报告可以变得更短很多。除此以外,我对ALGOL60的参数机制表示怀疑,它赋予程序员如此多的组合自由,以至于要求程序员更自律。除了开发成本外,它使用起来似乎也很危险。
最后,尽管令人不太愉快,但我必须提及——PL/1,一门描述文档非常庞大而且复杂的编程语言。使用PL/1就像开着一架有着7000个按钮,使用开关和扳手操作的飞机。我完全不能理解怎么靠智力来把握这种完全怪异的编程语言(我们的基本工具),使之保持稳定的发展,提醒你,这已经脱离我们智力的掌控了。还有如果非要描述PL/1对其用户的影响,我脑海中最为形象的隐喻就是毒品。我记得这个出自一个自称是PL/1的忠实用户在一个高级语言的专题讨论会上做的一个演讲。但是,在这个为期一小时充满对PL/1赞美的演讲中,他希望大家添加50种新特性,却没有想过他问题的源头是这门语言已经包含了太多的特性。演讲者展示了所有令人沮丧大的症状,他陷入内心停滞,但是渴求更多。当FORTRAN被称为婴儿期的凌乱时,完整的PL/1却是危险的肿瘤,最后成长为了一种致命病毒。
关于过去的事,就讲这么多吧。但是如果我们不能从中汲取教训的话,制造错误是没有任何意义的。事实上,我觉得我们学习了如此多的错误,以至于几年后的编程可以和之前截然不同。让我简述下你们可能的未来。乍看一下,这种编程的想象也许会让你不久的将来变得非常的不切实际。所以也允许加上也许会让人得出“这个人的想象相对实际”的结论的考虑吧。
这种想象就是,在七十年代结束之前,我们有可能设计和实现那种尽量利用编程能力,开支是许多年前百分之几的系统。此外,这些系统可以几乎摆脱bug。这两项提升相辅相成。在后一个方面,软件看上去和许多其他产品不同,很多产品质量和价格是成正比的。那些想要真正有效的软件的人将会发现他们必须从找到避免大多数bug的方法开始,最后,编程过程将变得便宜。如果你想要一些有能力的程序员,你将发现他们不会浪费时间在调试上,他们不应该以调试bug作为开始。换句话说,两种目标指向同样的变化。
在如此短的一段时间内发生如此激烈的变革,这会是一场革命,对所有人来说,基于他们对未来的期望,对过去(诉诸不成文的社会,文化惰性的法律)做出的和平推断,这种巨大变革会发生的机会几乎微不足道。但我们都知道有时候革命真的发生了。 那么这次变革我们的机遇是什么呢?
似乎有三个主要条件需要满足。一般来说,世界必须承认需要变化,第二经济需求十分强烈,还有第三,变革在技术上是可行的。让我讨论按顺序讨论一下上述三个条件。
谈到对软件更为可靠的需求,我表示完全同意。在几年前,就不一样了——讨论软件危机是对上帝的亵渎。转折点是 1968年十月在Garmisch举行的软件工程的学术会议,一次萌生了知觉承认软件危机的回忆。到目前为止,普遍认为任何大型系统的设计都是一项十分困难的工作,无论何时,人们遇到负责这样工作的人,都会发现他们非常关心可靠性问题。简而言之,我们第一个条件似乎满足了。
现在说到经济需求。现在人们总是遇到说六十年代编程是一个薪酬过高的职业的观点,并且说未来几年内,程序员薪酬希望可以下降。通常,这种观点的表述与经济衰退有关,但这是一种不同,健康的事物的征兆——也许过去几十年里程序员没有很好完成他们应该完成的工作。社会对程序员的表现和他们的产品感到不满意。但还存在另外一种导致重担的因素。现在的情况是,对于特定的系统,为软件升级的价格和升级硬件的价格在同一个数量级,社会或多或少接受了这一点。但硬件制造商告诉我们说在接下来数十年,硬件价格将会以十倍速度下降。如果软件发展还是一如既往的笨拙,程序一如既往的昂贵,局势将失去平衡。你不能指望社会接受这一点,因此我们必须学会有效的编程。 换句话说,只要机器还是预算中的大项,那么笨拙的编程技术还能侥幸逃脱,但是保护伞会快的折起来。总之,我们的第二个条件似乎也能满足。
现在轮到第三个条件,技术上可行吗?我觉得可行,我会用六个论据支撑我的观点。
一份程序结构的研究表明程序,即便是同一个任务的替补程序和有着相同的数学内容,在程序管理方面都有着巨大的差异。研究发现许多规律,违反任何一条规律要么局部或者整体的破坏程序的人为管理。这些规律不外乎两种。第一种容易在物理上加以利用,即选用合适的编程语言。Goto语句的和多输出参数的程序的剔除是很好的佐证。对于第二种,我至少看不到物理上使之暴露的方法(可能是我能力不足),好像需要一些我没有证明存在的自动化的定理证明程序。因此,第二种规律时不时作为程序员训练的要素之一出现。有些规律我清楚的知道以至于可以教给他人和不需要判断一段给定的程序是否违反了。 我们给出必要的例子——任何循环需要给出终止条件或者声明不变量之间的关系保证不变量不会被程序的循环语句执行而破坏。
我现在提议把我们限制在智能可控程序的设计和实现的范围内。如果有些人害怕这种限制过于严格,我们没有办法存活,我保证智能可控程序的种类足够的丰富,可以囊括现实很多能够解决算术问题的程序。我们不能忘记我们的职业不是为了编程,而是设计能够表现预设行为的计算类别。把我们限制在智能可控程序的建议是我所谓的六个论据的前两个的基础。
论据一,程序员只要考虑智能可控问题,选择更为容易考虑。
论据二,我们一决定把我们限制在智能可控程序的子集内,我们就一劳永逸的实现了考虑解决方案的空间的减少。
论据三是建立在程序正确性问题的建设性方法上的。今天,一项普通的技术就是写一个程序,然后去测试。 尽管,程序测试是一种非常有效的方法去暴露bugs,但对证明不存在bugs几乎是完全没用的。显著提高程序可信度唯一有效的方法是给出一个令人信服的关于正确性的证据。但是我们不应该首先写出程序,然后去证明它的正确性,因为要求证明只会增加苦逼程序员的负担。相反,程序员应该让正确性证明和程序相互验证,发展。论据三本质上是从以下的观察得来的。如果一个人问自己一个令人信服的证据应该具备什么,他了解后,写了一个很好的满足了证明要求的程序,然后这些关于正确性的担心变成一种有效的启发式的指导。当我们把自己限制在智能可控程序时,按照定义,只有这种方法是可行,但这种方法也提供许多有效的方法,让我们从中挑选一个满意的。
设计一个程序需要多少人力根据程序的长度判断,论据四与此相关。曾经有人指出存在一种自然法则告诉我们耗费人力是程序长度的平方。但是谢天谢地,还没有人能够证明这种法则。这是因为它需要是假的。我们都知道能够解决很多问题的推理论证工具称之为抽象,抽象能力的有效开发可以被认为一个有能力的程序员至关重要的敏捷之一。关于这一点,值得指出抽象的意图并不是为了模糊本身,而是去创造新的准确语义水平。当然,我曾经尝试去找到能够阻止我们抽象机制起作用的基础原因。但不管我多么努力,我都找不到任何一个原因。最后,我倾向于假设(直到现在未通过经验证明)我恰当的抽象化能力,也就是人力需要想象或者理解一个程序的耗费不会根据程序长度按照超过正比例的速度增长。但是这些调查的一个衍生品更有实际意义,实际上,它是我论据四的基础。衍生品是许多在整个编程过程中扮演重要角色的抽象模式的识别。你了解这些抽象模式足够多,你就可以就每个模式作报告。这些抽象模式的熟悉和了解让我幡然醒悟,例如从BNF到方向句法编译,可以用几分钟代替几年的花费。 因此,我把我们最近对重要抽象模式的理解作为论据四。
现在说到论据五,它和我们建立在我们思考习惯上的工具的影响有关。我观察到一种十有八九来源于文艺复兴的文化传统,为了忽略这种影响,需要把人心视为肉体最高自主的主人。 但我一开始分析我和同类的思考习惯时,我得到一个完全不同的结论,不管我喜欢与否,即我们使用的工具和我们用来表达或者记录我们想法的语言或记号,是决定我们能够想到什么的主要因素。对编程影响程序员的思考习惯的分析和脑力是我们几乎不曾使用的资源的认识,它们给出了从多方面给出不同编程语言优缺点的尺度。一个有能力的程序员能够意识到他自己脑容量的严格尺寸,因此,他谦逊的完成编程任务,牵涉到其他事情时,他避免小聪明像躲避瘟疫一样。说到一种著名的会话式程序设计技术,我从不同渠道被告知说如果一个计算社区一旦装备终端,一种特殊的现象就会发生,这种现象甚至有了一个被广泛接受的名称——打趣的人。它有一到两种不同的形式,一个程序员在别人桌面放了一个调侃的程序,他要么骄傲的展示它的用途并问别人你能用更少的字符写完吗(好像有任何概念的相关性一样),要么就问说猜猜这是用来干嘛的。通过这个观察,我们必须总结说这门语言是一种宣扬奇技淫巧的工具,同时这会是它的一些诉求的解释,例如说那些喜欢展示他们有多聪明的人,对不起,但是我必须把它视作关于编程语言最令人恶心的地方。我们必须从过去学到的另外一课是所谓功能强大,丰富的编程语言的发展是一种错误,就像这些奇怪庞然大物,某人特有的气质的聚集,都是心灵上,肉体上不可控的。我从系统的谦逊的编程语言上看到很美好的未来。 当我说谦逊时,我的意思是,例如,不仅是ALGOL60的for分支语句,还有FORTRAN的DO循环语句发现因为变得过于怪异而被淘汰。我曾经和一些有经验的志愿者做过一点编程实验,但有些不期望发生和预料不到的事情发生了。我的志愿者没有一个找到明显而漂亮的解决方法。通过更为细致的观察,我们找到相同的源头:他们对与重复的概念与用于加速的联合控制变量的联系过于紧密,以至于他们被蒙蔽了完全看不到明显的方法。他们的方法低效,晦涩难懂,并且耗费了大量时间。这是一段对我来说具有启示作用,和令人震惊的经历。最后,从某个方面上来讲,如果一个人希望明天的编程语言和现在的大为不同,很大程度的优于现在的,他们应该邀请我们在我们写下的所有需要用来应付概念上我们如今设计的抽象结构中思考。关于我们未来工具的优越性,也就是我们第五个论据的基础,就讲到这里。
作为旁观者,我希望提醒一下那些以现有工具不足而觉得编程任务困难的人。编程依旧会十分困难因为一旦我们从详尽的笨重中解放出来,我们将会发现自己得以面对解决远在我们编程能力以外的问题。
你可以不同意我的第六个论据,因为很难收据支持的实验证据,但不能阻止我相信它的正确性。直到现在,我还没有提到分层这个词,但我认为把它作为一个所有收录着一个精细分解解决方案的系统的核心概念是合理的。我甚至可以走更远一步写一篇关于信仰的文章,即我们能够以令人满意的方式解决的唯一问题是那些最后接受精细分解解决方案的问题。乍看之下,这种人类局限的观点是一种令人抑郁的关于我们处境的观点,但我恰恰相反,不这么觉得。学会和我们的局限共存的方法就是了解我们的局限。等到我们足够谦逊去尝试分解方案的死后,因为其他形式的努力已经超过我们智力的掌控,我们将要尽最大的努力去避免所有这些内部损害我们以有用的方式分解系统的能力的交流。我不得不希望这不停的引领我们发现一个容易解决的问题最终也是可以分解的。任何一个看到了大多数所谓的“代码生成”的编译状态的麻烦都可追溯到指令码的有趣特性的人,都会知道一个我在脑海中想到的事情简单示例。适用性更好的分解良好的解决方案是我第六个也是最后一个论据用于支持技术上可行的可能会在这十年发生的革命。
原则上,我把这些论据留给你,让你决定我的考察占多少分量,因为我很清楚我没有办法强迫任何人跟随我的信仰。每次重要的变革都会招致剧烈反对,每个人都可以问自己希望保守力量抵消多少发展。我不指望主要的大财团,甚至计算机领域的集团,我宁愿希望教育机构提供培训,希望那些保守团体的计算机用户认为他们古老的程序很重要以至于不值得重写或者优化。关于这一点,很多大学校园的中心电脑设备的选择视一些现成但昂贵且不理会千千万万愿意自己编程的小用户的问题的程序的需求而定,学校将为他们的选择埋单,这是相当可悲的。这种事情太常发生,例如,高能物理似乎曾经用他们剩下的实验设备勒索科学社区。当然,最容易的解决方法,是对技术可行性的干脆的拒绝,但我担心你需要足够支撑这种方法的论据。唉,现在普遍程序员的脑力水平可以阻止变革发生是得不到任何保证的,因为其他人的编程变得更为有效,程序员很容易在社会的版图中被边缘化。
还有很多政治方面的障碍。即便我们知道怎么去培养未来的专业的程序员,我们不能确定社会允许我们这样做。传授方法论(而不是散布知识)的第一影响是增强了现有的能者的能力,因此拉大了智商上的差异。在一个教育系统是用来建立平均文化的社会,在一个精英不允许出现在顶层的社会,培养有能力的程序员在政治上是不对味的。
让我总结一下。计算机已经伴随我们走过一个世纪的四分之一了。它们以工具的身份对我们社会产生了深远的影响,但是和在人类历史上史无前例的以智力挑战的形式产生深远的影响相比,它们只能以波浪的形式影响我们文化的表面。似乎拥有决定在某种程度上将物体视作一个不可分割整体的权利的分层系统,被视作一个级别更低,细节更多的混合物,最后,当我们将注意力从一级转向更低一级时,时空的天然粒面会以合适的数量级减少。 我们知道墙以砖为单位,砖以结晶体为单位,结晶体以分子为单位,等等。在分层系统中,许多级别可以有意义的区分出来,这和最大与最小粒度的比率的对数成正比,因此,除非比率很大,我们不能指望能够分很多层。在计算机编程中,我们基本的编程语句有低于一微秒的时间粒度,但我们的程序却可能花费几小时的计算时间。我不知道任何一种超过10的10次方的比率的技术,以它超凡速度为优点的计算机,似乎是第一个给我们提供需要分层粒度大和实现它的环境的。这样的挑战,即面对编程任务,是独一无二的,因此这样小说一般的经历可以教会我们很多关于自己的知识。它加深了我们对设计和创造程序的理解,它帮助我们更好的完成想法条理化的任务。如果它没有这样做,对我来说,我们根本不值得拥有计算机。
它已经给我们上了几课,在这次演讲中我要强调以下几点。我们应该更好的编程,证明我们用满是对任务带来的巨大困难的感激的方法完成任务,证明我们坚持谦逊和优雅的编程语言,证明我们尊重人类内心固有的限制和以谦卑的程序员的身份完成任务。
1952年初春的早晨,由于一系列巧合,我正式进入了编程界,成为了 程序员历史上第一位荷兰人。回想起来,程序员作为一种职业,是以现在很难相信的缓慢速度出现的,至少在我所了解的范围内是这样,这让人非常惊奇。那个缓慢时期的两段清晰回忆让我心存感激。在有了三年编程经验后,我和当时我在阿姆斯特丹数学中心的老板 A. Van Wijngaarden(译注:荷兰数学家和计算机科学家),进行了一场讨论,关于这场讨论我在有生之年都会感激他。讨论的焦点在于,我本来是要在编程的同时,在莱顿大学学习理论物理,但是当发现鱼和熊掌不可兼得时,我不得不做出选择,要么停止编程,成为一个名符其实的可敬的理论物理学家;或者把我的物理学研究敷衍了事,而成为一个…那个叫什么?程序员?但那是个受人尊敬的职业么?什么又是编程呢?它作为一门学科所需要的完备知识体系又在哪里呢?我非常清晰得记得自己有多嫉妒我从事硬件的同僚们,因为当被问到专业技能时,他们至少可以谈自己所知道关于真空管,放大器,和其他一些硬件的一切;而被问到这个问题时,我只能茫然无措。满心焦虑,我敲开了 van Wijngaarden 的办公室大门,问道:“是否能占用他一点时间”;而在几个小时后离开他办公室时,我整个人焕然一新。在耐心听完我的问题后,他同意当时并没有学科是关于编程的,但是他接下来解释说,自动化电脑会继续发展,而我们正处于摸索阶段,那我能不能成为先驱者之一,使编程在未来成为一个受人认可的学科呢?这成了我人生中的一个转折点,促使我尽快完成了我的物理学研究。上述故事的寓意是,我们必须谨慎地向年轻人提供意见,因为有时他们真的会听的!
荷兰婚礼仪式上有要求新人陈述职业的传统,而两年后的1957年,当我结婚时我宣告自己是一名程序员。但是阿姆斯特丹的市政当局没有接受,理由是并不存在程序员这样一种职业。不管你信不信,在我婚姻证书上“职业”这一栏里,可笑的写着“理论物理学家”!
关于程序员作为一种职业在我国的缓慢出现,就说这么多了。从那时起,我见识到了外面的世界,留下的总体印象是,尽管起步的时间不同,但是其他国家的发展模式是大同小异的。
让我尝试更多地回顾下昔日的一些细节,以期更好地理解现在的情况。现在我们对问题进行分析时,应该知道,关于编程任务很多常见误解是可以追溯到很久以前的。
Edsger W. Dijkstra
第一代的电子计算机是独特的机器,并且只能在各种进行开拓性试验的实验室里被找到。从人类见识了自动化计算机那天起,实现它就是对当时现有的电子技术一个巨大挑战,不过有一件事很确定,那就是我们不能否认那些致力于开发这些设备先驱们的勇气。这些设备是如此的令人惊奇,回想起来,至少是有时候,人们只能怀疑,这些机器是否真的运行起来了。最难解决的问题就在于让机器跑起来并让其保持工作秩序。一些较老的计算机科学学会的命名中依然反映着自动计算机硬件方面的当务之急,如美国计算机协会(ACM)和英国计算机协会,这些协会的名称中明确提到了物理设备。
那么可怜的程序员又是什么样的处境呢?实情是:他根本没有被人注意。一方面,第一代计算机是如此得笨重,以至于无法搬来搬去,同时,它们又需要大规模的维护,因此很自然的,人们就在发明这些计算机的实验室里使用它们。另一方面,程序员的工作既不为人所知又缺少魅力,在打动参观者的程度上,展示机器比展示几页代码要高出几个数量级。但是最重要的是,程序员以非常谦逊的眼光看待自己的工作:程序员工作的所有重要性都继承自硬件设备。因为每一台计算机都是不同的,程序员非常清楚,他的程序只有在特定计算机上才能运行,并且由于计算机的寿命有限,导致他的工作会随着机器的老化而丧失价值。最后,还有一种情况对程序员的工作态度产生了深远的影响:一方面,除了不稳定,他工作的机器一般还存在运行缓慢、内存太小等问题,这让巧妇难为无米之炊;另一方面,程序中通常又会存在少量古怪代码来应对突发的状况。在那些日子里,有很多聪明的程序员通过一些巧妙的方法,使他的设备可以完成一些本来不可能完成的任务,以这样的方式来获得智力上的巨大满足感。
关于编程的两种观点就起源于那个时期。我现在提下这件事,等下会回到这个话题。一种观点认为真正专业的程序员应该具有解决问题的头脑,并且非常喜欢聪明的伎俩;另一种观点认为,编程就是在某个方向上优化计算效率的过程。
后一种观点源自于设备落后的年代,那时候有些人简单的期望着,一旦机器变得更为强大,编程将不会成为难题,到那时想尽办法榨干机器的性能将不再有必要,这就是编程的目的,难道不是吗?但是下一个十年里发生了巨变,更为强大的机器被造出来了,不是一个数量级的强大,而是好几个数量级的强大。但是出人意料的是,我们并没有一劳永逸地解决所有的问题,反而发现自己处在了软件危机中!这是怎么回事呢?
一个小小的原因是:现代计算机在一个或两个方面比老式的计算机更难以操作。首先,现代计算机有I/O中断,中断的发生不可预知也不可重现,这个特性与能完全掌控运行过程的旧式计算机相比,是一个巨大的变化,但是这个特性会产生难以预料的逻辑错误,很多程序员花白的头发见证了这一点。第二,现在的计算机配置了多级存储设备,关于设备管理的策略,虽然已经有大量的文献,但是对我们来说仍然相当难以捉摸。关于计算机结构的变化所增加的复杂性就讲这么多了。
但是上面所举的只是“小”原因,真正大的原因是…现代计算机性能比原来强大了好几个数量级!可以不客气的说:当世上没有计算机的时候,根本就不会有编程问题;当我们有了几台性能弱小的计算机后,编程就出现小问题了,现在我们有了性能强大的计算机,编程自然变成了巨大的问题。在这样的发展过程中,电子产业非但没有解决一个问题,而是产生了问题,即使用产品所带来的问题。换种方式说,如果现有计算机性能增长了千分之一,那么社会对于使用这些机器的期望也会以同样的比例增长,而可怜的程序员会发现自己处于到底是目的优先还是方式优先的紧张选择中。硬件性能的提升,加上其可靠性甚至更急剧的提升,使得几年前程序员做梦都不敢想的问题变得可以实现。而几年后,他不得不梦见这个问题,更糟的是,他不得不将这样的梦变成现实!那么我们发现自己仍身处于软件危机中是不是一个奇迹呢?当然不是了,正如你猜测的那样,这些甚至是可以提前预知的,只不过这种小众预测的问题在于五年后你才能知道它是正确的。
接着在六十年代中期,有一件可怕的事情发生:所谓的第三代计算机出现了。官方的文献表示,性价比一直是他们主要的设计目标之一。但是如果你将机器众多组件的占空比作为“表现”的衡量标准,你会看到一个内存被必要性存疑的内部常驻活动所占据的设计。如果你对于价格的定义是硬件的价值,你会看到一个对其编程极其困难的设计:举个例子,无论对于程序员还是系统,用于执行的指令码早期绑定所带来的问题都不能真正得到解决。并且在很大程度上,这些令人不快的可能性看起来已经成为了现实。
当这样的机器宣布发售,其功能规格为人所知后,我们之中的不少人肯定相当难受,至少我是这样。第三代计算机的发行肯定会席卷计算机界,而人们更加期待它的设计能够尽量健全。但是因为这样一个有着如此严重缺陷的设计,让我感觉到计算机科学至少退步了十年:这也让我的职业生涯经历了最为黑暗的一个星期。也许最可悲的事情是,即使有了这么多年令人沮丧的经验,依然有如此多的人天真的相信计算机必须是这样。他们用机器的销量来打消自己的疑虑,并且从这种观察中得到使用这些机器是安全的错觉,毕竟,机器的设计不可能那样糟糕。但是仔细想想,这种被销量欺骗的安全感就和吸烟必须是健康的说法相差无几,因为吸烟的人很多。
正是这方面,我很遗憾,在发表对最新公布的计算机的评论时,计算机领域的科学期刊并没有习惯像其他科学出版物那样做出复查:对机器的复查至少应该同样重要。这里我要检讨:在六十年代早期,我写过这样的评论并准备提交给CACM,尽管我没有向同事们寻求建议,但他们极力主张我这样做,可我还是不敢,因为担心这样无论对我还是对编委会来说,困难都太大。是懦弱没有让我提交这样一份报告,对此我越来越自责。我预见到的困难是当时缺乏普遍接受的标准,虽然确信自己的标准是正确的,但我还是担心我的报告会被拒绝,或者被贴上“个人口味问题”的标签。我仍然认为这样的报告是及其有用的,并且渴望着它们的出现,因为它们的出现将代表着计算机界的成熟。
之所以对硬件保持上面提到那样的关注,是因为我相信影响那些使用者的思考习惯是任何计算工具最重要的作用之一,并且我有理由相信,这种影响力比预期的更为强烈。现在让我们的注意力回到软件上。
由于软件具有显著的多样性,我必须将自己限制在几个立足点上。这使得我做出的选择显得很武断,也让我觉得很痛苦,希望大家不要因此怀疑我对其他没有提到的努力的欣赏。
刚开始的时候,EDSAC 在英国的剑桥兴起,我对其起初让子程序库在机器设计和使用方法中发挥主要作业的观点印象深刻。接近25年后的今天,计算领域彻底的变化了,但是软件的基本观念还伴随着我们,闭合子程序的观念也还是我们编程的核心概念之一。我们应该认可闭合子程序作为最伟大的软件发明之一,它经历了三代计算机的发展并且仍将继续存活几代,因为它迎合了我们基本抽象模式的接口思想。遗憾的是,在第三代计算机的设计中,它的重要性被低估了,而这个设计中,大量明确命名为寄存器的算术计算单位揭示了子程序机制的广泛使用。尽管如此,也没有让子程序的概念就此消失,我们只能祈祷这种变化不会在下一代的计算机中被遗传。
我要讲的第二个软件业的主要发展是FORTRAN的诞生。在当时这是一个伟大而冒失的计划,负责这个计划的人们值得我们大声地赞美。因为大约10年后才日渐明显的外延错误用法而去责备他们是显然不公平的:能够成功预测十年后的团队相当罕见。当我们回顾过去时,必须把FORTRAN看做一项成功但是对其产生概念基本没啥帮助的编码技术,在需求如此迫切的现在,这项技术已经过时了。我们应该尽快忘记FORTRAN,对于思想的马车而言,它不再胜任:它浪费了我们的脑力,使用它过于冒险,因此也太过奢侈。FORTRAN的悲惨命运已经因为它广泛的接受度,影响了数以千计的程序员为我们过去的错误买单。我每天都祈祷,会有更多程序员小伙伴找到从通用性的祸害中解脱出来的方法。
第三个不能忽略的就是LISP,一个完全与众不同的迷人设计。基于LISP的几个基本原则使得LISP展示出了非凡的健壮性。除此以外,LISP成为了相当多的复杂计算机载体。LISP曾经被调侃为滥用电脑的最智能方法。我想这种描述是一种很高的赞美,因为它传递了解放的气息——它已经帮助我们之中最有天赋的人思考了之前不可能思考的东西。
第四个要提到的就是 ALGOL 60。到目前为止,FORTRAN程序员仍然倾向于从他们的开发中了解他们的编程语言——八进制的兴起和十六进制的衰落;而LISP的定义依然是一种令人好奇的混合体,其中包括这门语言意味着什么和这门机制是怎么工作的,《算法语言》那篇著名的报告中说道,ALGOL 60是真正努力去承载抽象概念至关重要的一步,再加上通过独立于语言之外的方法定义一门编程语言的成果。有人会说,ALGOL 60的作者们已经如此的成功,以至于他们自己引出这门语言是否可以实现产生的严肃疑问!那篇报告冠冕堂皇地展示了BNF范式(即现在人尽皆知的Backs-Naur-Form)的作用,和英语谨慎措辞的力量,至少是像Peter Naur一样聪明的人使用时。我觉得可以负责任地说,基本没有像它这么短而在计算机界有相同影响力的文档存在。人们习惯于使用用“ALGOL”或者是“类ALGOL”这样未经保护的标签,向大量基本不相关的年轻语言分享ALGOL的荣耀,这本身某种程度上就是对ALGOL惊人生命力的极大致敬。BNF作为一种严格定义的语言,它的长处导致了我个人认为是这门语言的缺点——过分精心制作并且语法定义不规则,很难在几页纸中完全说明。如果有个BNF般强大的设备,《算术语言》中那篇关于ALGOL60的报告可以变得更短很多。除此以外,我对ALGOL60的参数机制表示怀疑,它赋予程序员如此多的组合自由,以至于要求程序员更自律。除了开发成本外,它使用起来似乎也很危险。
最后,尽管令人不太愉快,但我必须提及——PL/1,一门描述文档非常庞大而且复杂的编程语言。使用PL/1就像开着一架有着7000个按钮,使用开关和扳手操作的飞机。我完全不能理解怎么靠智力来把握这种完全怪异的编程语言(我们的基本工具),使之保持稳定的发展,提醒你,这已经脱离我们智力的掌控了。还有如果非要描述PL/1对其用户的影响,我脑海中最为形象的隐喻就是毒品。我记得这个出自一个自称是PL/1的忠实用户在一个高级语言的专题讨论会上做的一个演讲。但是,在这个为期一小时充满对PL/1赞美的演讲中,他希望大家添加50种新特性,却没有想过他问题的源头是这门语言已经包含了太多的特性。演讲者展示了所有令人沮丧大的症状,他陷入内心停滞,但是渴求更多。当FORTRAN被称为婴儿期的凌乱时,完整的PL/1却是危险的肿瘤,最后成长为了一种致命病毒。
关于过去的事,就讲这么多吧。但是如果我们不能从中汲取教训的话,制造错误是没有任何意义的。事实上,我觉得我们学习了如此多的错误,以至于几年后的编程可以和之前截然不同。让我简述下你们可能的未来。乍看一下,这种编程的想象也许会让你不久的将来变得非常的不切实际。所以也允许加上也许会让人得出“这个人的想象相对实际”的结论的考虑吧。
这种想象就是,在七十年代结束之前,我们有可能设计和实现那种尽量利用编程能力,开支是许多年前百分之几的系统。此外,这些系统可以几乎摆脱bug。这两项提升相辅相成。在后一个方面,软件看上去和许多其他产品不同,很多产品质量和价格是成正比的。那些想要真正有效的软件的人将会发现他们必须从找到避免大多数bug的方法开始,最后,编程过程将变得便宜。如果你想要一些有能力的程序员,你将发现他们不会浪费时间在调试上,他们不应该以调试bug作为开始。换句话说,两种目标指向同样的变化。
在如此短的一段时间内发生如此激烈的变革,这会是一场革命,对所有人来说,基于他们对未来的期望,对过去(诉诸不成文的社会,文化惰性的法律)做出的和平推断,这种巨大变革会发生的机会几乎微不足道。但我们都知道有时候革命真的发生了。 那么这次变革我们的机遇是什么呢?
似乎有三个主要条件需要满足。一般来说,世界必须承认需要变化,第二经济需求十分强烈,还有第三,变革在技术上是可行的。让我讨论按顺序讨论一下上述三个条件。
谈到对软件更为可靠的需求,我表示完全同意。在几年前,就不一样了——讨论软件危机是对上帝的亵渎。转折点是 1968年十月在Garmisch举行的软件工程的学术会议,一次萌生了知觉承认软件危机的回忆。到目前为止,普遍认为任何大型系统的设计都是一项十分困难的工作,无论何时,人们遇到负责这样工作的人,都会发现他们非常关心可靠性问题。简而言之,我们第一个条件似乎满足了。
现在说到经济需求。现在人们总是遇到说六十年代编程是一个薪酬过高的职业的观点,并且说未来几年内,程序员薪酬希望可以下降。通常,这种观点的表述与经济衰退有关,但这是一种不同,健康的事物的征兆——也许过去几十年里程序员没有很好完成他们应该完成的工作。社会对程序员的表现和他们的产品感到不满意。但还存在另外一种导致重担的因素。现在的情况是,对于特定的系统,为软件升级的价格和升级硬件的价格在同一个数量级,社会或多或少接受了这一点。但硬件制造商告诉我们说在接下来数十年,硬件价格将会以十倍速度下降。如果软件发展还是一如既往的笨拙,程序一如既往的昂贵,局势将失去平衡。你不能指望社会接受这一点,因此我们必须学会有效的编程。 换句话说,只要机器还是预算中的大项,那么笨拙的编程技术还能侥幸逃脱,但是保护伞会快的折起来。总之,我们的第二个条件似乎也能满足。
现在轮到第三个条件,技术上可行吗?我觉得可行,我会用六个论据支撑我的观点。
一份程序结构的研究表明程序,即便是同一个任务的替补程序和有着相同的数学内容,在程序管理方面都有着巨大的差异。研究发现许多规律,违反任何一条规律要么局部或者整体的破坏程序的人为管理。这些规律不外乎两种。第一种容易在物理上加以利用,即选用合适的编程语言。Goto语句的和多输出参数的程序的剔除是很好的佐证。对于第二种,我至少看不到物理上使之暴露的方法(可能是我能力不足),好像需要一些我没有证明存在的自动化的定理证明程序。因此,第二种规律时不时作为程序员训练的要素之一出现。有些规律我清楚的知道以至于可以教给他人和不需要判断一段给定的程序是否违反了。 我们给出必要的例子——任何循环需要给出终止条件或者声明不变量之间的关系保证不变量不会被程序的循环语句执行而破坏。
我现在提议把我们限制在智能可控程序的设计和实现的范围内。如果有些人害怕这种限制过于严格,我们没有办法存活,我保证智能可控程序的种类足够的丰富,可以囊括现实很多能够解决算术问题的程序。我们不能忘记我们的职业不是为了编程,而是设计能够表现预设行为的计算类别。把我们限制在智能可控程序的建议是我所谓的六个论据的前两个的基础。
论据一,程序员只要考虑智能可控问题,选择更为容易考虑。
论据二,我们一决定把我们限制在智能可控程序的子集内,我们就一劳永逸的实现了考虑解决方案的空间的减少。
论据三是建立在程序正确性问题的建设性方法上的。今天,一项普通的技术就是写一个程序,然后去测试。 尽管,程序测试是一种非常有效的方法去暴露bugs,但对证明不存在bugs几乎是完全没用的。显著提高程序可信度唯一有效的方法是给出一个令人信服的关于正确性的证据。但是我们不应该首先写出程序,然后去证明它的正确性,因为要求证明只会增加苦逼程序员的负担。相反,程序员应该让正确性证明和程序相互验证,发展。论据三本质上是从以下的观察得来的。如果一个人问自己一个令人信服的证据应该具备什么,他了解后,写了一个很好的满足了证明要求的程序,然后这些关于正确性的担心变成一种有效的启发式的指导。当我们把自己限制在智能可控程序时,按照定义,只有这种方法是可行,但这种方法也提供许多有效的方法,让我们从中挑选一个满意的。
设计一个程序需要多少人力根据程序的长度判断,论据四与此相关。曾经有人指出存在一种自然法则告诉我们耗费人力是程序长度的平方。但是谢天谢地,还没有人能够证明这种法则。这是因为它需要是假的。我们都知道能够解决很多问题的推理论证工具称之为抽象,抽象能力的有效开发可以被认为一个有能力的程序员至关重要的敏捷之一。关于这一点,值得指出抽象的意图并不是为了模糊本身,而是去创造新的准确语义水平。当然,我曾经尝试去找到能够阻止我们抽象机制起作用的基础原因。但不管我多么努力,我都找不到任何一个原因。最后,我倾向于假设(直到现在未通过经验证明)我恰当的抽象化能力,也就是人力需要想象或者理解一个程序的耗费不会根据程序长度按照超过正比例的速度增长。但是这些调查的一个衍生品更有实际意义,实际上,它是我论据四的基础。衍生品是许多在整个编程过程中扮演重要角色的抽象模式的识别。你了解这些抽象模式足够多,你就可以就每个模式作报告。这些抽象模式的熟悉和了解让我幡然醒悟,例如从BNF到方向句法编译,可以用几分钟代替几年的花费。 因此,我把我们最近对重要抽象模式的理解作为论据四。
现在说到论据五,它和我们建立在我们思考习惯上的工具的影响有关。我观察到一种十有八九来源于文艺复兴的文化传统,为了忽略这种影响,需要把人心视为肉体最高自主的主人。 但我一开始分析我和同类的思考习惯时,我得到一个完全不同的结论,不管我喜欢与否,即我们使用的工具和我们用来表达或者记录我们想法的语言或记号,是决定我们能够想到什么的主要因素。对编程影响程序员的思考习惯的分析和脑力是我们几乎不曾使用的资源的认识,它们给出了从多方面给出不同编程语言优缺点的尺度。一个有能力的程序员能够意识到他自己脑容量的严格尺寸,因此,他谦逊的完成编程任务,牵涉到其他事情时,他避免小聪明像躲避瘟疫一样。说到一种著名的会话式程序设计技术,我从不同渠道被告知说如果一个计算社区一旦装备终端,一种特殊的现象就会发生,这种现象甚至有了一个被广泛接受的名称——打趣的人。它有一到两种不同的形式,一个程序员在别人桌面放了一个调侃的程序,他要么骄傲的展示它的用途并问别人你能用更少的字符写完吗(好像有任何概念的相关性一样),要么就问说猜猜这是用来干嘛的。通过这个观察,我们必须总结说这门语言是一种宣扬奇技淫巧的工具,同时这会是它的一些诉求的解释,例如说那些喜欢展示他们有多聪明的人,对不起,但是我必须把它视作关于编程语言最令人恶心的地方。我们必须从过去学到的另外一课是所谓功能强大,丰富的编程语言的发展是一种错误,就像这些奇怪庞然大物,某人特有的气质的聚集,都是心灵上,肉体上不可控的。我从系统的谦逊的编程语言上看到很美好的未来。 当我说谦逊时,我的意思是,例如,不仅是ALGOL60的for分支语句,还有FORTRAN的DO循环语句发现因为变得过于怪异而被淘汰。我曾经和一些有经验的志愿者做过一点编程实验,但有些不期望发生和预料不到的事情发生了。我的志愿者没有一个找到明显而漂亮的解决方法。通过更为细致的观察,我们找到相同的源头:他们对与重复的概念与用于加速的联合控制变量的联系过于紧密,以至于他们被蒙蔽了完全看不到明显的方法。他们的方法低效,晦涩难懂,并且耗费了大量时间。这是一段对我来说具有启示作用,和令人震惊的经历。最后,从某个方面上来讲,如果一个人希望明天的编程语言和现在的大为不同,很大程度的优于现在的,他们应该邀请我们在我们写下的所有需要用来应付概念上我们如今设计的抽象结构中思考。关于我们未来工具的优越性,也就是我们第五个论据的基础,就讲到这里。
作为旁观者,我希望提醒一下那些以现有工具不足而觉得编程任务困难的人。编程依旧会十分困难因为一旦我们从详尽的笨重中解放出来,我们将会发现自己得以面对解决远在我们编程能力以外的问题。
你可以不同意我的第六个论据,因为很难收据支持的实验证据,但不能阻止我相信它的正确性。直到现在,我还没有提到分层这个词,但我认为把它作为一个所有收录着一个精细分解解决方案的系统的核心概念是合理的。我甚至可以走更远一步写一篇关于信仰的文章,即我们能够以令人满意的方式解决的唯一问题是那些最后接受精细分解解决方案的问题。乍看之下,这种人类局限的观点是一种令人抑郁的关于我们处境的观点,但我恰恰相反,不这么觉得。学会和我们的局限共存的方法就是了解我们的局限。等到我们足够谦逊去尝试分解方案的死后,因为其他形式的努力已经超过我们智力的掌控,我们将要尽最大的努力去避免所有这些内部损害我们以有用的方式分解系统的能力的交流。我不得不希望这不停的引领我们发现一个容易解决的问题最终也是可以分解的。任何一个看到了大多数所谓的“代码生成”的编译状态的麻烦都可追溯到指令码的有趣特性的人,都会知道一个我在脑海中想到的事情简单示例。适用性更好的分解良好的解决方案是我第六个也是最后一个论据用于支持技术上可行的可能会在这十年发生的革命。
原则上,我把这些论据留给你,让你决定我的考察占多少分量,因为我很清楚我没有办法强迫任何人跟随我的信仰。每次重要的变革都会招致剧烈反对,每个人都可以问自己希望保守力量抵消多少发展。我不指望主要的大财团,甚至计算机领域的集团,我宁愿希望教育机构提供培训,希望那些保守团体的计算机用户认为他们古老的程序很重要以至于不值得重写或者优化。关于这一点,很多大学校园的中心电脑设备的选择视一些现成但昂贵且不理会千千万万愿意自己编程的小用户的问题的程序的需求而定,学校将为他们的选择埋单,这是相当可悲的。这种事情太常发生,例如,高能物理似乎曾经用他们剩下的实验设备勒索科学社区。当然,最容易的解决方法,是对技术可行性的干脆的拒绝,但我担心你需要足够支撑这种方法的论据。唉,现在普遍程序员的脑力水平可以阻止变革发生是得不到任何保证的,因为其他人的编程变得更为有效,程序员很容易在社会的版图中被边缘化。
还有很多政治方面的障碍。即便我们知道怎么去培养未来的专业的程序员,我们不能确定社会允许我们这样做。传授方法论(而不是散布知识)的第一影响是增强了现有的能者的能力,因此拉大了智商上的差异。在一个教育系统是用来建立平均文化的社会,在一个精英不允许出现在顶层的社会,培养有能力的程序员在政治上是不对味的。
让我总结一下。计算机已经伴随我们走过一个世纪的四分之一了。它们以工具的身份对我们社会产生了深远的影响,但是和在人类历史上史无前例的以智力挑战的形式产生深远的影响相比,它们只能以波浪的形式影响我们文化的表面。似乎拥有决定在某种程度上将物体视作一个不可分割整体的权利的分层系统,被视作一个级别更低,细节更多的混合物,最后,当我们将注意力从一级转向更低一级时,时空的天然粒面会以合适的数量级减少。 我们知道墙以砖为单位,砖以结晶体为单位,结晶体以分子为单位,等等。在分层系统中,许多级别可以有意义的区分出来,这和最大与最小粒度的比率的对数成正比,因此,除非比率很大,我们不能指望能够分很多层。在计算机编程中,我们基本的编程语句有低于一微秒的时间粒度,但我们的程序却可能花费几小时的计算时间。我不知道任何一种超过10的10次方的比率的技术,以它超凡速度为优点的计算机,似乎是第一个给我们提供需要分层粒度大和实现它的环境的。这样的挑战,即面对编程任务,是独一无二的,因此这样小说一般的经历可以教会我们很多关于自己的知识。它加深了我们对设计和创造程序的理解,它帮助我们更好的完成想法条理化的任务。如果它没有这样做,对我来说,我们根本不值得拥有计算机。
它已经给我们上了几课,在这次演讲中我要强调以下几点。我们应该更好的编程,证明我们用满是对任务带来的巨大困难的感激的方法完成任务,证明我们坚持谦逊和优雅的编程语言,证明我们尊重人类内心固有的限制和以谦卑的程序员的身份完成任务。