作者 Grady Booch,UML三剑客(Three Amigos)。另外两位是James Rumbaugh和Ivar Jacobson。
第一篇 概念
第一章 复杂性
“系统越复杂,就越容易全面崩溃”
1.1 复杂的系统结构
1.1.1 个人计算机的结构
- 层次化
- 每层代表不同的抽象
1.1.2 植物和动物的结构
- 层次化
- 同一层的抽象之间以某种良定义的方式进行交互
- 抽象层的内外之间总有清晰的边界
- 每一部分都对许多高层的功能做出贡献。“整体行为大于部分之和”
1.2 软件固有的复杂性
“爱因斯坦认为自然界必定存在着简单的解释,因为上帝不是反复无常或者随心所欲地。软件工程师没有这样的信仰来提供安慰。许多必须控制的复杂性是随心所欲的复杂性。” —— Brooks
1.2.1 定义软件复杂性
某些软件系统并不复杂,是由一个人提出、构建、维护和是使用的。通常是编程新手或者独立工作的专业开发人员。目的通常有限,而且生命周期很短,所以可以扔掉他们、用全新的软件代替他们,不必尝试复用、修复或者扩展它们的功能。
工业级软件:
- 表现出丰富的行为
- 存在于反馈式系统中,
- 由真实世界的事件驱动或者发出驱动事件
工业级软件的特征是:单个开发者要理解其设计的所有方面非常困难,是几乎不可能的。武断地说,这些系统的复杂性超出了人类智能的范围。但几乎是所有大型系统的基本特征。
复杂性可以掌握,但不经消除。
1.2.2 为什么软件在本质上是复杂的
“软件的复杂性是一个基本特征,而不是偶然如此” —— Brooks
- 问题域的复杂性
- 管理开发过程的困难性
- 通过软件可能实现的灵活性
- 刻画离散系统行为
问题域的复杂性
试图解决的问题会存在无数竞争性需求甚至是相反的需求。
常常源自于系统用户和系统开发者之间的“沟通困难”:很难用开发者能够理解的形式对他们的需求给出准确地描述:
- 想法不清楚
- 对问题本质有不同看法
- 没有好的方法准确记录需求
- 对文档可能有不同的解读
软件开发过程中经常发生需求变更。
系统维护:
- 修正错误 —— 维护
- 应对改变的需求 —— 演化
- 保持古老和陈腐的软件继续工作 —— 保护
相当于部分软件开发资源被用在了保护上。
管理开发过程的困难性
软件开发团队的基本任务是创造简单的假象,让用户与大量的、通常是任意的外部复杂性隔离开。
软件规模逐渐变大,就需要团队开发。团队越小越好,但无论团队规模有多大,总会存在沟通挑战。
通过软件可能实现的灵活性
建筑行业对于原材料品质有着统一的编码和标准,但软件行业很少有这种标准。结果软件行业还是劳动密集型产业。
描述离散系统行为的问题
离散系统的不同状态组合导致无限可能的结果。
外部的事件可能破坏系统的状态的任何部分。
1.3 复杂系统的5个属性
1.3.1 层次结构
“复杂性常常以层次结构的形式存在,复杂的系统由一些相关的子系统构成,这些子系统又有自己的子系统,如此下去,直到到达某种最低层次的基本组件”。
1.3.2 相对本原
“选择哪些作为系统的基础组件相对来说比较随意,这很大程度上取决于系统观察者的判断”
1.3.3 关注点分离
层次系统是可分解的。
组件内部的联系通常比组件间更强。这一事实将组件中的高频率动作(组件内部)和低频率动作(组件间)分解开来。
这样我们可以以相对隔离的方式来研究每个部分。
1.3.4 共同模式
1.3.5 稳定的中间形式
“复杂系统毫无疑问都是从能工作的简单系统演变而来……从头设计的复杂系统根本不可能工作,也不可能从打补丁的方式使其工作。必须从头开始,从能工作的简单系统开始。”
1.4 有组织和无组织的复杂性
发现共同的抽象和机制能够极大地促进我们对复杂系统的理解。
1.4.1 复杂系统的规范形式
- part-of
- is-a
类结构和对象结构的概念与复杂系统的五种属性结合起来,基本所有的复杂系统都有规范的形式。系统的类结构和对象结构统称为他的架构。
1.4.2 人在处理复杂性时的能力局限
- 一个人能够同时理解的最大信息数是7个,上下浮动两个
- 大脑需要大约5秒才能接受一组新的信息
1.5 从混沌到有序
必须通过一些训练有素的方法来控制复杂性。
1.5.1 分解的作用
“分而治之”
- 算法分解
- 面向对象的分解
没办法同时使用两种方法,因为他们完全正交。
1.5.2 抽象的作用
如果不能够全面掌握一个复杂的对象,我们选择忽略其非本质的细节,转而处理这个对象的一般化、理想化的模型。
1.5.3 层次结构的作用
1.6 复杂系统的设计
2.2.1 面向对象编程
⾯向对象编程是⼀种实现的⽅法,在这种⽅法中,程序被组织成许多组相互协作的对象,每个对象代表某个类的⼀个实例,⽽类则属于⼀个通过继承关系形成的层次结构。
- (1)利⽤对象作为⾯向对象编程的基本逻辑构建块,⽽不是利⽤算法;
- (2)每个对象都是某个类的⼀个实例;
- (3)类与类之间可以通过继承关系联系在⼀起
2.2.2 面向对象设计
⾯向对象设计是⼀种设计⽅法,包括⾯向对象分解的过程和⼀种表⽰法,这种表⽰法⽤于展现被设计系统的逻辑模型和物理模型、静态模型和动态模型
- (1)⾯向对象设计导致了⾯向对象分解;
- (2)⾯向对象设计使⽤了不同的表⽰法,来表达系统逻辑设计(类和对象结构)和物理设计(模块和处理架构)的不同模型,以及系统的静态和动态特征
2.2.3 面向对象分析
⾯向对象分析是⼀种分析⽅法,这种⽅法利⽤从问题域的词汇表中找到的类和对象来分析需求
2.3 对象模型要素
- (1)⾯向过程 算法;
- (2)⾯向对象 类和对象;
- (3)⾯向逻辑 ⽬标,通常以谓词演算的⽅式表⽰;
- (4)⾯向规则 如果-那么规则;
- (5)⾯向约束 不变的关系。
主要要素
- (1)抽象;
- (2)封装;
- (3)模块化;
- (4)层次结构。
次要要素
- (1)类型;
- (2)并发;
- (3)持久。
抽象描述了⼀个对象的基本特征,可以将这个对象与所有其他类型的对象区分开来,因此提供了清晰定义的概念边界,它与观察者的视⾓有关
从那些准确地为问题域实体建模的对象到那些实际上没有什么理由存在的对象,存在着⼀系列的抽象。按最有⽤到最没有⽤的次序,这些抽象是:
- 实体抽象:⼀个对象,代表了问题域或解决⽅案域实体的⼀个有⽤的模型;
- 动作抽象:⼀个对象,提供了⼀组通⽤的操作,所有这些操作都执⾏同类的功能;
- 虚拟机抽象:⼀个对象,集中了某种⾼层控制要⽤到的所有操作,或者这些操作将利⽤某种更低层的操作集;
- 偶然抽象:⼀个对象,封装了⼀组相互间没有关系的操作。
3.1.1
对象是⼀个具有状态、⾏为和标识符的实体。结构和⾏为类似的对象定义在它们共同的类中。‘实例’和‘对象’这两个术语可以互换使⽤