在2000年1月1日到来前的几年里,许多工程师都在研究如何解决“千年虫”问题。简而言之,若一个软件在存储年份时使用的是两位数,而不是四位数,那么当2000年到来时,这个软件就会“认为”那是1900年,从而引发诸多问题。恐怕没有任何人、任何机构会比美国联邦航空管理局(FAA)更担心“千年虫”问题了。如果空中交通管制系统在新千年到来时出现故障,那将会导致巨大的灾难。因此,美国联邦航空管理局检查了计算机系统,并对系统进行了测试:如果系统认为那是1900年,会出现什么情况? [13]
在测试过程中,他们发现交通管制系统中的IBM 3083计算机问题特别棘手。作为技术人员代表,美国联邦航空管理局的工会主席指出主要问题在于:“IBM公司只有两个人知道这种型号的计算机的微代码,但是他们都退休了。” [14] 但真正的原因是,IBM 3083属于大型机,从20世纪80年代开始发售,而且所用的系统软件早在发售前几年就已投入使用。这就意味着,到了20世纪90年代后期,这个为全美的飞机制定航线的计算机系统所使用的代码几乎已无人可识。
这还算不上令人震惊。一直以来,许多大型系统的基础都是较小和较陈旧的系统。只要这些系统能够继续平稳地运行下去,就不会有人在意那些旧东西上面到底堆了多少新东西,系统中到底累积了多少次第加入的片段。据一位消息人士透露,直到2007年,美国国税局所使用的报税系统依旧是20世纪60年代早期,也就是肯尼迪政府时期开发的系统。 [15] 美国国税局所使用的另一个系统则始建于20世纪70年代,并于1985年进行了大修。与此类似,美国的航天飞机在执行最后一次航天任务时, [16] 所用的平台是由5台IBM计算机组成的,其计算能力甚至还比不上今天的一部普通智能手机。然而,这些软件和技术仍然在使用着。
1975年出版的《人月神话》( The Mythical Man-Month )一书中,计算机科学家小弗雷德里克·布鲁克斯(Frederick P. Brooks Jr.)讨论了有关软件设计和项目编程的管理问题。在这本书中,他引用了业内的一句俗语:“每次加一点,每次加一点,最后就有了一大堆。” [17] 每一个独立设计,无论是为了修复,还是用来提供新功能,看上去都不过是一次独立的选择,而且都很合理:要么解决了问题,要么为用户创造了新的令人兴奋的功能。然而,日积月累下,它们终会变成“一大堆”。从交通运输业到能源业,再到农业,我们都可以从中清楚地看到,但凡是大型的技术系统,就定会发生这种情况。
举例来说,一大堆石头不一定会成为问题,即使它们看上去可能很难处理、过于零乱,但却不一定深奥难解。真正的问题是,当我们创造的“一大堆”引发出意料之外的状况时,我们就会遭遇“雪崩”。不幸的是,我们不断地往技术系统中加入一个又一个片段,“雪崩”在所难免。“一大堆”不仅变得更大,而且变得更难琢磨了。
我记得我最早是在一些讨论“行星系如何形成”的文章中看到“吸积”这个术语的。行星系由一团旋转的尘埃和气体凝聚而成,这种星星点点的累积过程,就是“吸积”的过程。 [18] 这个用来描述行星系如何形成的概念由来已久,而在技术的增长过程中也是类似的吸积作用。
吸积过程的结果之一就是形成了人们常说的遗留代码(legacy code)或遗留系统(legacy systems),即过时的机器和技术,也就是开发出来之后使用至今的机器和技术,譬如美国国税局所使用的报税系统。这种老旧的系统并不罕见,甚至可以说相当常见。 [19] 它们经历了多年的吸积过程,成了拼凑起来的系统,从科学模型到城市基础设施,几乎无处不在。例如,在城市的排水系统中,既有服役超过百年的旧管道,也有刚刚埋设好的新管道。
就计算机领域而言,很多技术系统都依赖于已停产的旧型号计算机系统,而且程序代码也是用早已退役的编程语言所写。例如,许多科学软件现在都成了遗留系统,它们一般都是用Fortran语言编写的,那是一种功能强大但早已过时的编程语言。随着技术的高速发展,如今我们再来看Fortran语言编写的计算机代码,就好像是在看中古时代的英语。
在这里,不妨引用《全球概览》( Whole Earth Catalog )的创始人斯图尔特·布兰德(Stewart Brand)在《万年钟传奇》( The Clock of the Long Now )一书中的说法:“通常,这些已经过时的遗留系统,在过去的许多年里,一直都扮演着十分重要的角色,若是替换掉它们,必定会‘伤筋动骨’,恐怕没有人能够承担这样的后果。此外,它们也是无法被完全修复的,一是因为问题过于复杂,二是因为没有人完全了解整个系统。”
那么,当我们面对一个仍在缓慢增大、小故障不断的遗留系统时,又该怎么办呢?我们只能小心翼翼地对待它,因为设计它的人可能早就“杳无音讯”了。这个遗留系统可能已经完全嵌入了其他系统,彻底移除它的后果,可能远比容忍它的小故障更加糟糕。这种系统实在难以处理,有时甚至会被称为“恐怖爬行兽”(crawling horrors),也就是美国恐怖、科幻小说作家霍华德·菲利普斯·洛夫克拉夫特(H. P. Lovecraft)小说中那种无法形容的怪物。 [20]
司法系统条文,也有类似的情况。在法律体系中,随着时间的推移,法律条文会被修正或修改。人们会根据不断变化的环境,对法律条文做出调整,但总会留下一些数十年前制定的法律条文。例如,互联网流量管理的相关法规就源于1934年通过的一项法律。随着时间的推移,法律体系也在不断地吸积,最终成了一个拼凑起来的系统。它可以发挥作用,但是远远谈不上优雅。
以税法为例。事实上,美国的税法早已复杂不堪了,立法者也早就承认了这个事实。税表的使用说明已经从1940年的两页,增加到了2013年的200多页。 [21] 鉴于此,如果你在申报纳税时,因为法律法规太过复杂而出了错,那么最高法院会裁定你无罪,因为你在错误报税这件事上并没有“主观故意”。 [22] 尽管如此,就法律体系本身而言,在现有税法上修修补补,要比重新制定更容易,也更有效。
另外,我们也要考虑一下诸如美国环境保护署之类的政府部门和机构所颁布的法规的总体增长趋势。事实上,只要看一看《美国联邦法规》的总页数就足够了。 [23] 《美国联邦法规》收录了各行政机构颁布的各种法规,在过去的50年里,其页数从不到25 000页增加到了超过165 000页。
我们还观察到,行政人员和行政机构的数量也出现了类似的增长趋势。20世纪50年代,《经济学人》杂志中有一篇文章提到了帕金森定律(Parkinson's Law),并定量地描述了行政人员数量的增长规律。 [24] 虽然这篇文章的观点还不太完善,但帕金森定律毕竟有数据的支持,其结论到今天仍基本成立:政府部门的行政人员数量以每年5%至6%的速度在增长。毫无疑问,随着行政机构的规模越来越大,机构的管理问题只会越来越复杂。
事实上,软件界已经将吸积和积累奉为普适规则。 [25] 就发展而言,软件系统的规模势必会与日俱增,除非有人积极地尝试简化它们。
那么,为什么我们不能对复杂的系统进行定期清理并从头开始呢?这和实际操作有关。例如,软件未能按时重写完,索性就在推出新版本之前先发布一个补丁。 [26] 我在想,只要愿意花上很多年的时间,那么微软内部的任何一位软件专家都可以重写Word的全部代码。当时间、精力和金钱都有限,且不得不进行权衡时, [27] 我们通常会选择对系统进行修改,让它“足够好”就行了。这意味着,我们需要不断对系统进行调试和修正,就像立法者对美国法律体系所做的那样,也就是说,我们需要在以往的基础上加上一层又一层的东西。我们的城市拥有一个多世纪之前埋设的燃气管道 [28] 、20世纪30年代建成的运输网络 [29] ,以及废弃的地铁站。它们都隐藏在城市的地下。
不过,更多的时候,我们之所以放弃从头开始的想法,是因为那样做不仅太困难,而且太危险。没有人能够完全理解一个系统所依赖的所有旧的组成部分的全部作用,所以重新设计一个未经检验的系统不仅是愚蠢的行为,更是危险的行为。试想一下,一个几十年前设计好的、非常复杂的银行软件系统正慢慢适应着各种先进的技术,无论是新型的计算机,还是新的操作系统,或是无处不在的互联网。虽然这个系统的核心基础并不适用当今时代,但它们已经嵌入得太深,以致无法删除。总而言之,我们必须接受这样一个普遍规则,那就是:无论何种技术系统,终将变得日益复杂。 [30]
但是,当仔细观察技术系统中的遗留代码时,无论是在一个软件中,还是在一个法律体系中,我们都会发现,真正的复杂性绝不仅仅只体现在日益扩大的系统规模上。毕竟,只有和另一个因素结合起来,吸积才能使技术系统变得复杂,这个因素就是交互。