抽象层次
抽象层次是面向对象方法中极其重要,但是又非常难以掌握的技巧。学 会站在不同的抽象层次考虑问题是建立好模型的基础,所以笔者不能不在这里说一些与技术无关的“废话”。
首先,抽象层次越高,具体信息越少,但是概括能力越强;反之,具体信息越丰富,结果越确定,但相应的概括能力越弱。从信息的表达能力上说,抽象层次越高表达能力越丰富,越容易理解。可能有人会对这个提出疑问,因为在人们的印象里,越是抽象的东西越难理解,相反越具体的事物越容易认识,难道不是吗?
笔者认为,越具体的事物越容易理解这个说法是一种误解,因为人们所认识的事物概念都是抽象的,具象只是一个相对的概念。比如人们会觉得一块石头很容易认识,因为它有颜色,有大小,有硬度。可 是你有没有想过这些用来描述石头的概念都是具象的还是抽象的呢?什么叫硬度?是手摸上去的感觉?还是用它砸玻璃的结果?还是一个数字后面跟个物理学单位?你肯定不会去想这些,但你不会感到石头是硬的这个概念难于理解。你觉得它们很容易理解是因为经过多年的积累,这个抽象的概念被你消化和吸收了。
事实上,这个你看来很具体的硬度是你从感觉、视觉、听觉、数字等综合起来以后得出的一个抽象概念。如果说它的硬度是摩氏5 级,非常具体,你却相反不能够很好地理解了。举例来说,对普通人很容易理解的颜色,对盲人来说就十分“抽象”。 再举一个例子,同样是长度的概念,天文学所用的光年相对于米、公里这些常见单位的概念要更抽象。但说太阳系距离银河系中心大约有27000 光年,就比说这个距离是255439722759681600000 米要容易理解,这是因为这个数字之大已经超过人们可以通过对比来理解的地步了。
实际上,由于人脑对信息的处理能力是有限度的,如果信息量超过了人脑的处理能力,人就会失去对这个事物的理解能力。因此,越是具体的表达信息量越大,越接近人脑的处理极限,人们的理解能力越是下降(这也是面向过程方法为什么困难的原因之一)。对面向对象方法来说,这时就需要提高抽象层次,用一个新的概念来概括一部分相关的信息,一 旦人们像接受了光年概念一样消化了这个新的概念,理解起来就变得容易了。同时,这个新的概念就屏蔽了(或者说封装了)更多具体的信息。抽象层次越高,被屏蔽的信息也就越多,信息量越少,也就越容易理解和处理。这就是面向对象比面向过程具有优势的原因。读者可以回顾一下本书开头引用的 Grady Booch 的那段话,相信会有进一步的认识。
但随之而来的另一个问题是如果抽象层次太高,信 息量过少的话,人们实施起来又会产生新的困难——信息量不足。因此,在面向对象的分析过程中,在适当的时候采用适当的抽象层次是十分重要的。几乎所有使用过UML 的朋友都会觉得选择用例的粒度是一件很困难的事,实际上用例粒度选择的困难本质上是由于没有找准抽象层次而产生的。
抽象有两种方法,一种是自顶向下,另一种是自底向上。自顶向下的方法适用于让人们从头开始认识一个事物。例如介绍汽车的工作原理时,从发动机、传动装置、变速器等较高层次的抽象概念来讲就比较容易明白。如果降一个层次,从发动机原理讲起,一大部分听众就会开始迷惑;再降一个层次,从热力学原理和力学原理讲起,那就更没人能搞懂汽车是怎么工作的了。自底向上的方法适用于在实践中改进和提高认识。例如在实践中发现了发动机的问题,因而改进发动机结构,甚至采用新的发动机原理,最终能够提升汽车的质量。
在软件开发过程中,主体上应当采用自顶向下的方法,用少量的概念覆盖系统需求,再逐步降低抽象层次,直到代码编写。同时应当辅以自底向上的方法,通过总结在较低抽象层次的实践经验来改进较高层次的概念以提升软件质量。现在请读者回忆一下建模公式,公式中所表达的也是一个自顶向下的方法。如果你在做设计或分析的时候总是觉得信息之间的关系太复杂,总是难以理清头绪,你需要思考一下是否不适当地采用了自底向上的分析方法。图2.3 展示了通常的统一过程抽象层次和分析过程。
图2.3 统一过程一般抽象层次 |
抽象层次的一个问题是什么时候选择什么样的层次,以及总共要抽象多少层的问题。如果是用UML 来建模的话,这个问题就直接反映到如何选择用例的粒度。这个问题我们将在第二部分中实践,并在第三部分中继续讨论。
与抽象层次相关的另一个问题是边界,实际上抽象层次与边界的选择总是相生相伴的。这个问题先按下不表,在3.4 边界一节中再详细阐述。