作者在本节继续介绍复杂系统形成原因的第二大因素~交互,即很多独立小单元之间还会形成各种各样的交互,让整个系统变的更加复杂。对此,人们好像没有更好的解决办法,特别是面临巨大重置或替换成本的时候,只能维持现状,保持稳定。
如果你以前写过代码,那么你应该清楚计算机程序是如何抵制简化工作的。随着计算机程序变得越来越庞大、越来越复杂,代码也变得越来越复杂,而且绝大部分代码的聚合方式都是令人费解的。为了确保大型程序仍可控,我们开发出了各种各样的技术方法,例如版本控制、错误跟踪,以及跨团队沟通工具等,但是这些方法通常都只是“战斗失败”后的亡羊补牢之术。(哈哈哈,的确,但又不得不做呀)不仅软件代码本身在不断吸积,每个组成部分也在越来越频繁地与其他组成部分进行交互。与存在于“真空”中的全新项目有所不同,任何一个计算机程序都是一个大规模的互联系统:不仅会作用于自身,还会与其他程序相互作用。我们在旧代码中一次又一次地加入新代码,并以出其不意的新方式去使用它们,以此将各个层次拼接在一起。
交互过程,包括许多意外交互在内,有时会因编程语言本身的原因而加剧。即使是刚入门的程序员也知道,GOTO语句会带来麻烦。在BASIC编程语言中,通过设置GOTO语句,可以让程序轻松地从某一行跳转到另一行。换句话说,如果代码中包含了GOTO语句,那么程序就可以轻松地从某一行指向另一行,从代码中的一个点跳转到另一个点。如此容易便能实现跳转,难怪有人会说,对于那些想要对自己的计算思维进行测试的文科生而言,GOTO语句无疑是“天赐良品”。(跳转次数太多了之后,基本就看不明白啦)
在一个小程序中,使用GOTO语句实现跳转,既容易又无伤大雅。但是,随着程序变得越来越大,GOTO语句最终会将代码绑定到某些庞杂的节点上,但即使是最熟练的程序员也无法解开这些庞杂的节点。最终,你得到的将是所谓的“意大利面条”式的代码,因为所有东西都纠缠在了一起,既难解开,又难理解。在这种情况下,要想搞清楚程序指令执行的次序几乎是不可能的,这也是为什么这样的计算机程序特别容易出现令人意想不到和无法理解的行为。(debug就是从最早的计算机连接线排错诞生的)
此类简化命令即使只是在独立的、较小的环境下发挥作用,也有可能通过某种方式脱离当初设定的目标。如果使用的频率和方式超出了预设范围,系统及其组成部分就会出现诸多问题,而这些问题比当初设想的要庞杂得多。GOTO语句就是一个突出的例子,它从一个美妙的超快捷工具变成了既不优雅,又实为“有害”的东西。
为了更好地理解并强化系统秩序,专家们想出了很多方法,包括使用更加复杂的计算机语言。在大多数由专家构建的新系统中,意大利面条式的代码已成为过去式。然而,由于互联的易发性和各种层次上的不断吸积,交互作用正在持续增多。于是,高度互联的系统动态,即信息的流动和各部分之间的交互,也就变得异常复杂和不可预测。仍以丰田汽车软件为例,因为存在交互,丰田汽车软件中的大量代码已无法被测试了。(这可能也是传统车厂软件系统无法开放的原因之一吧,做不了生态)
除了互操作性之外,不同类型的技术之间还会产生相互依赖性,例如互联网与电网之间的相互依赖性。研究者在研究了多种类型的系统,并了解了它们的优缺点后指出,某些系统在多种条件下均可能会出现故障或崩溃。例如,某个规模相当小的电网出现了故障,继而引发了无法收拾的级联效应。对于这种风险,有一种观点是:将技术系统之间的相互联系切断。然而,这种想法的可操作性几乎为零。互联系统的构建成本其实很低:在当今这个充满互操作性的时代,工程师和设计人员都在有意为各个系统创建接口,因此,不同的系统可以很容易被关联起来。(构建成本是很低的,但做大之后调整成本就很高了)
我们在构建新事物时,通常都会在故障成本和构建成本之间进行权衡。我们需要知道,如果出了故障,失败的成本会有多大。如果Word崩溃了,那么尚未保存下来的东西将会丢失。尽管没有人希望看到这样的结果,但这个故障的成本的确是相对较低的。(人性呀,总是要长记性才行)如果电网出了故障,并导致美国很多地区停电,那么故障的成本就极其高昂了。例如,在2003年,美国东北部的大停电对5 000万人的生活和工作造成了影响,并导致11人丧生,直接损失估计高达60亿美元。(这个成本已经非常巨大了)
每一项故障成本都应该拿来与系统的构建成本进行比较。纵观历史,我们所构建的系统越重要,构建成本就越高。例如,构建银行系统的基础设施所耗费的资源,比编写一个聊天程序多得多。因此,我们必须确保那些昂贵的系统不易发生故障,而这又意味着需要增加构建成本。换句话说,在极高的构建成本面前,通过大量检查和测试来降低故障成本的做法,变得至关重要。(方向选择还是维持稳定,这样也是不得已而为之呀,经济利益驱动)
在一个相当长的时期内,这种方法一直行之有效。因为对构建成本的重视程度超过了对故障成本的重视程度,所以我们所依赖的所有重要的社会保障系统,都是花费大量资源构建起来的。然而,现在事情已经发生了变化。出于各种原因,例如,我们可以找到现成的工具和组件,同时“云”上面也存有很多可用资源,所以构建成本已大幅下降。创立技术公司已不再需要太多启动资金:你可以快速地设计和生产出复杂的工具,并通过市场进行测试,而你为此所付出的成本并不大。(云计算确实是颠覆性的技术,化繁为简的大杀器,难怪亚马逊和微软的云业务估值那么高,改变世界的基础设施呀)
与此同时,与互联有关的故障成本也已出现持续上升的趋势。尽管系统关联技术相当简单,而且成本很低,但是这种互联系统的故障成本却非常巨大。当我们把数字地图软件与出行指导软件关联到一起时,哪怕只是一个很小的错误也有可能导致一场灾难。例如,苹果地图在首次发布时就曾将超市错标为医院。(特斯拉汽车关系到生命安全,所以故障成本就更高了,怪不得他们希望代码尽量简洁,减少出错机会)
一般来说,随着系统内部及系统之间的交互增多,包括拥有子系统的大型系统在内的所有系统的复杂性都会增加。有人认为,互联性的不断提高,体现了技术的基本要求。技术终究会产生交互和聚合,并在这种情况出现时进一步推动我们走向复杂化。
尽管从开始构建大型技术系统的第一天起,这些趋势就一直存在,但是近年来,它们变得愈发强大了。正如我在本书导论中所提到的那样,计算机科学家艾兹格·迪科斯彻对当下的大型系统,特别是计算机系统的激进新颖性所进行的分析发人深省。早在1988年,迪科斯彻就已指出,计算机程序的设计需要克服大量规模上的差异,当然,在计算机问世之前,没有人需要去处理这样的事情。以智能导航系统为例,迪科斯彻很好地解释了其跨度极大的层级结构。从程序中的1个比特,到机器存储空间里的几百兆字节,的确是从非常小到非常大的跨越。这种跨越涉及近10亿次的跳转,极端的规模变化不但超乎想象,而且史无前例。事实上,这一切已经,并将继续走向极端化,因为日常应用技术的普通用户,现在已经熟悉了千兆或万兆这样的前缀,而这些前缀又意味着,我们要对庞大的规模差异负责,而这种庞大系统的边界已近乎天文意义上的边界了。(确实有点可怕,存储服务已经变得比较昂贵了)
在过去的短短几十年间,大型系统已变得异常庞大且错综复杂,用迪科斯彻的话来说即是“概念层级的深度,绝非人类心智曾需面对的任何事物可比”。(现在数据规模单位好像已经到了PB级别,确实没人能完全看完这些东西了)
网友评论