1.1 什么是复杂系统
我们很难给复杂系统下一个举世公认的定义。专门从事复杂系统研究的Melanie Mitchell在接受Ubiquity杂志专访时,“勉为其难”地为复杂系统给出了一个相对通俗的定义:由大量相互作用的部分组成的系统。与整个系统比起来,这些组成部分相对简单,没有中央控制,组成部分之间也没有全局性的通信,并且组成部分的相互作用导致了复杂行为。[1]388
这个定义庶几可以表达软件复杂度的特征。定义中的“组成部分”对于软件系统,就是所谓的“软件元素”,基于粒度的不同可以是函数、类、模块、组件和服务等。这些软件元素相对简单,然而彼此之间的相互作用却导致了软件系统的复杂行为。软件系统符合复杂系统的定义,不过是进一步证明了软件系统的复杂度。然而该如何控制软件系统的复杂度呢?恐怕还要从复杂度的成因开始剖析。
Jurgen Appelo从理解能力与预测能力两个维度分析了复杂度的成因[2]39。这两个维度各自分为不同的复杂层次:
- 理解能力维度——简单的(simple)和复杂的(complicated);
- 预测能力维度——有序的(ordered)、复杂的(complex)和混沌的(chaotic)。
两个维度都蕴含了“复杂”的含义:前者与简单相对,意为复杂至难以理解,可阐释为“复杂难解”;后者与有序相对,意为它的发展规律难以预测,可阐释为“复杂难测”。在预测能力维度,“难测”还不是最复杂的层次,最高层次为混沌,即根本不可预测。两个维度交叉,可以形成6种代表不同复杂意义的层次定义,Jurgen Appelo通过图1-1形象地说明了各个复杂层次的特征。
图1-1 复杂系统的特征[1]
以下是Jurgen Appelo对这些例子给出的说明[2]39:
我的内衣很简单。我很容易理解它们的工作原理。我的手表是精密复杂的,如果把它拆开,我需要很长时间才能了解其设计原理和组件。但是我的手表或我的内衣都没有什么让人吃惊的(至少对我而言)。它们是有序的、可以预测的系统。
一个三人软件开发团队也是简单的,只需要开几次会议,提供一些晚餐,外加几杯啤酒,就可以了解这个团队的每一个人了。一座城市是不简单的、繁杂的,出租车司机需要几年时间才能熟悉这座城市的所有街道、胡同、宾馆和饭店。但同时,团队和城市又都是复杂的。不管你有多了解它们,总会有意想不到的事情发生它们身上。在某种程度上,它们是可预测的,但是你永远不清楚明天会发生什么。
双摆(两个摆锤互相连接)也是一个简单的系统,容易制作也很容易理解。但因为对钟摆的初始设置具有高度敏感性,所以它进行的是不可预测的混沌运动。股票市场也是混沌的,根据定义,它是不可预测的,否则每个人都知道怎么利用股票交易来赚钱,就会导致整个系统崩盘。但是,股票市场又不像钟摆那样,它是相当繁杂的。
软件系统属于哪一个复杂层次呢?
大多数软件系统需要实现的整体功能往往是难以理解的,同时,随着需求的不断演进,它又在一定程度具有未来的不可预测性,这意味着软件系统的“复杂”同时覆盖了“复杂难解”(complicated)与“复杂难测”(complex)两个层面,对标图1-1给出的案例,就是一座城市的复杂特征。无独有偶,Pete Goodliffe也将软件系统类比为城市,他说:“软件系统就像一座由建筑和后面的路构成的城市——由公路和旅馆构成的错综复杂的网络。在繁忙的城市里发生着许多事情,控制流不断产生,它们的生命在城市中交织在一起,然后死亡。丰富的数据积聚在一起、存储起来,然后销毁。有各式各样的建筑:有的高大美丽,有的低矮实用,还有的坍塌破损。数据围绕着它们流动,形成了交通堵塞和追尾、高峰时段和道路维护。”[5]33既然如此,那么设计一个软件系统就像规划一座城市,既要考虑城市布局,以便居民的生活与工作,满足外来游客或商务人员的旅游或出差需求,又要考虑未来因素的变化,例如“当居民对城市的使用方式有所变化,或者受到外力的影响时,城市就会相应地演化”[3]13。参考城市的复杂度特征,我们要剖析软件系统的复杂度,就可以从理解能力与预测能力这两个维度探索软件复杂度的成因。