1.4 有组织和无组织的复杂性
发现共同抽象和机制极大地促进了我们对复杂系统的理解。例如,只要通过几分钟的指导,一名有经验的飞行员就能够进入一架以前从未飞过的多引擎飞机并安全地驾驶它。认识到所有飞机的共同属性,如舵、副翼和节流阀的功能之后,飞行员主要需要了解哪些特性是这架飞机所特有的。如果飞行员已经知道如何驾驶一架飞机,那么学会驾驶类似的飞机就会容易很多。
1.4.1 复杂系统的规范形式
这个例子表明,我们前面对“层次结构”这个术语的使用方式是很宽泛的。大部分有趣的系统不只包含单一的层次结构,相反,我们发现同一个复杂系统中通常表现出许多不同的层次结构。例如,研究飞行器时我们可以将它分解为推进系统、飞行控制系统等。这种分解代表了结构上或“组成部分(part of)”的层次结构。
另外,我们可以按一种完全正交的方式来分解这个系统。例如,涡轮引擎是一种具体的喷气引擎,Pratt and Whitney TF30又是一种具体的涡轮引擎。换言之,喷气引擎代表了所有类型的喷气引擎的共同特性的抽象,涡轮引擎只是一种特殊类型的喷气引擎,它有一些特有的特征,可以和冲压喷气式引擎区分开来。
第二种层次结构代表了“是一种(is a)”的层次结构。根据我们的经验,从这两种观点来看系统都很重要,应该既研究它的“是一种”层次结构,也研究“组成部分”层次结构。我们把这些层次结构分别称为“类结构”和“对象结构”,原因将在第2章中解释[2]。
如果读者熟悉对象技术,我们要做一些澄清。在这个例子里,当我们提到类结构和对象结构时,并不是指在编写软件时创建的类和对象。我们指的是更高抽象层的类和对象,它们组成了复杂的系统,如喷气引擎、飞机骨架、不同类型的座位、自动导航子系统等。读者可以回顾前面关于复杂系统属性的讨论,什么是基础组件与观察者有关。
如图1-1所示为系统的两个正交的层次结构:它的类结构和它的对象结构。每个层次结构都是分层的,在许多基础类和对象之上构建了许多抽象类和对象。选择哪些类或对象作为基础类或对象,这与要解决的问题有关。深入每个层次,又会看到另一层的复杂性。特别是在对象结构的各个部件中,同一抽象层上的对象之间存在着紧密的协作。
图1-1 复杂系统的关键层次结构
将类结构和对象结构的概念与复杂系统的5种属性(层次结构、相对基础(如多层次的抽象)、关注点分离、模式和稳定的中间形式)结合起来,我们发现,基本上所有的复杂系统都具有相同的(规范的)形式,如图1-2所示。我们将系统的类结构和对象结构统称为它的“架构”。
图1-2 复杂系统的规范形式
还要注意的是,类结构和对象结构不是完全独立的,对象结构中的每个对象都代表了某个类的一个具体实例。(在图1-2中,注意类C3、C5、C7和C8和实例03、05、07和08。)正如在图中所看到的,复杂系统中对象的数量通常比类的数量要多很多。通过展示“组成部分”和“是一种”层次关系,我们明确地揭示了被研究系统的冗余性。如果不揭示系统的类结构,我们就不得不将属性方面的知识重复地放到每个部分中。通过类结构,我们在一个地方记录了这些共同的属性。
在同样的类结构中,对象实例化和组织的方式可以采取许多不同的方式。没有一种特定的架构可以真正被认为是“正确的”。这也是系统架构具有挑战性的原因——在可能的多种系统组件结构、复杂系统的5种属性及系统用户的需求之中寻找平衡。
经验表明,最成功的复杂软件系统就是在设计中包含了深思熟虑的类结构和对象结构,并具备了前一节所描述的复杂系统的5种属性。为了不让这个重要的结论被忽略掉,让我们说得再直接一些:如果不考虑这些因素,我们就不太可能准时地在预算范围之内交付满足需求的软件系统。
1.4.2 人在处理复杂性时的能力局限
既然我们知道复杂系统的设计应该是怎样的,那么为什么在开发它们时还是会遇到严重的问题呢?这涉及软件的组织复杂性的概念,它还是相对比较新的。但是,还存在另一个主宰因素,即人在处理复杂性时的能力局限。
在刚开始分析复杂软件系统时,我们发现许多部分必须以多种交错的方式进行交互,这些部分和它们的交互行为之间几乎没有什么显见的共性。这就是无组织的复杂性的例子。当我们通过设计的过程对这种复杂性进行组织时,必须同时考虑许多事情。例如,在一个航空交通控制系统中,我们必须同时处理许多不同飞机的状态,必须面对相当大的、交错的、有时是非确定性的状态空间。遗憾的是,一个人绝对没有办法同时追踪所有的细节。心理学家的一些实验(如Miller的实验)表明,一个人能够同时理解的最大信息数量是7个,上下浮动2个[14]。这种渠道能力似乎与短期记忆的能力有关。Simon补充说明,处理速度也是一个限制因素:大脑需要大约5秒钟才能接受一组新的信息[15]。
因此,我们面对的是一个根本难题:要开发的软件系统的复杂性在增加,而我们处理复杂性的能力却有局限。怎样才能解决这个困境?