软件架构之系统分析与设计方法(2)
8.4 面向对象的分析与设计
面向对象方法是一种非常实用的软件开发方法,它一出现就受到软件技术人员的青睐,现已成为计算机科学研究的一个重要领域,并逐渐成为软件开发的一种主要方法。面向对象方法以客观世界中的对象为中心,其分析和设计思想符合人们的思维方式,分析和设计的结构与客观世界的实际比较接近,容易被人们接受。在面向对象方法中,分析和设计的界面并不明显,它们采用相同的符号表示,能够方便地从分析阶段平滑地过渡到设计阶段。此外,在现实生活中,用户的需求经常会发生变化,但客观世界的对象及对象间的关系比较稳定,因此用面向对象方法分析和设计的结构也相对比较稳定。
8.4.1 面向对象的基本概念
1.对象和类
对象是系统中用来描述客观事物的一个实体,它由对象标识(名称)、属性(状态、数据、成员变量)和服务(操作、行为、方法)三个要素组成,它们被封装为一个整体,以接口的形式对外提供服务。
在现实世界中,每个实体都是对象,如学生、书籍、收音机等;每个对象都有它的操作,例如书籍的页数,收音机的频道、按钮等属性,以及收音机的切换频道等操作。
而类则是对具有相同属性和服务的一个或一组对象的抽象。类与对象是抽象描述和具体实例的关系,一个具体的对象被称为类的一个实例。在系统设计过程中,类可以分为三种类型,分别是实体类、边界类和控制类。
(1)实体类:实体类映射需求中的每个实体,实体类保存需要存储在永久存储体中的信息,例如,在线教育平台系统可以提取出学员类和课程类,它们都属于实体类。实体类通常都是永久性的,它们所具有的属性和关系是长期需要的,有时甚至在系统的整个生存期都需要。
实体类是对用户来说最有意义的类,通常采用业务领域术语命名,一般来说是一个名词,在用例模型向领域模型的转化中,一个参与者一般对应于实体类。通常可以从 SRS 中的那些与数据库表(需要持久存储)对应的名词着手来找寻实体类。通常情况下,实体类一定有属性,但不一定有操作。
(2)控制类:控制类是用于控制用例工作的类,一般是由动宾结构的短语(“动词+名词”或“名词+动词”)转化来的名词,例如,用例“身份验证”可以对应于一个控制类“身份验证器”,它提供了与身份验证相关的所有操作。控制类用于对一个或几个用例所特有的控制行为进行建模,控制对象(控制类的实例)通常控制其他对象,因此,它们的行为具有协调性。
控制类将用例的特有行为进行封装,控制对象的行为与特定用例的实现密切相关,当系统执行用例的时候,就产生了一个控制对象,控制对象经常在其对应的用例执行完毕后消亡。通常情况下,控制类没有属性,但一定有方法。
(3)边界类:边界类用于封装在用例内、外流动的信息或数据流。边界类位于系统与外界的交接处,包括所有窗体、报表、打印机和扫描仪等硬件的接口,以及与其他系统的接口。要寻找和定义边界类,可以检查用例模型,每个参与者和用例交互至少要有一个边界类,边界类使参与者能与系统交互。边界类是一种用于对系统外部环境与其内部运作之间的交互进行建模的类。常见的边界类有窗口、通信协议、打印机接口、传感器和终端等。实际上,在系统设计时,产生的报表都可以作为边界类来处理。
边界类用于系统接口与系统外部进行交互,边界对象将系统与其外部环境的变更(例如,与其他系统的接口的变更、用户需求的变更等)分隔开,使这些变更不会对系统的其他部分造成影响。通常情况下,边界类可以既有属性也有方法。
2.继承与泛化
继承是面向对象方法中重要的概念,用来说明特殊类(子类)与一般类(父类)的关系,而通常用泛化来说明一般类与特殊类的关系,也就是说它们是一对多关系。
如图 8-11 所示,“交通工具”是“自行车”和“小轿车”的泛化;“自行车”和“小轿
车”从“交通工具”中继承。
3.多态与重载
多态(即多种形式)性是指一般类中定义的属性或服务被特殊类继承后,可以具有不同的数据类型或表现出不同的行为,通常是使用重载和改写两项技术来实现的。一般有 4 种不同形式的多态,如表 8-4 所示。
虽然重载和改写都是在多种潜在的函数体中,选择和调用某一个函数或方法并对其进行执行,但它们的本质区别在于:重载是编译时执行的(静态绑定),而改写则是运行时选择的(动态绑定)
4.模板类
也称为类属类,它用来实现参数多态机制。一个类属类是关于一组类的一个特性抽象,它强调的是这些类的成员特征中与具体类型无关的那些部分,而用变元来表示与具体类型有关的那些部分。
5.消息和消息通信
消息就是向对象发出的服务请求,它通常包括提供服务的对象标识、消息名、输入信息和回答信息。消息通信则是面向对象方法学中的一个重要原则,它与对象的封装原则密不可分,为对象间提供了唯一合法的动态联系的途径。
8.4.2 面向对象分析
面向对象分析的目标是开发一系列模型,这些模型描述计算机软件,当它工作时以满足一组客户定义的需求。对象技术的流行,演化出了数十种不同的 OOA 方法,每个方法都引入了一个产品或系统分析的过程、一组过程演化的模型及使软件工程师能够以一致的方式创建每个模型的符号体系。其中比较流行的方法包括 OMT、OOA、OOSE、Booch 方法等,而OMT、OOSE、Booch 最后则统一成为 UML。
1.OOA/OOD 方法
这是由 Peter Coad 和 Edward Yourdon 提出的,OOA 模型中包括主题、对象类、结构、属性和服务 5 个层次,需经过标识对象类、标识结构与关联(包括继承、聚合、组合、实例化等)、划分主题、定义属性、定义服务 5 个步骤来完成整个分析工作。
OOD 中将继续贯穿 OOA 中的 5 个层次和 5 个活动,它由人机交互部件、问题域部件、任务管理部件、数据管理部件 4 个部分组成,其主要的活动就是这 4 个部件的设计工作。
设计问题域部分:OOA 的结果恰好是 OOD 的问题域部件,分析的结果在 OOD 中可以被改动或增补,但基于问题域的总体组织框架是长时间稳定的;
设计人机交互部件:人机交互部件在上述结果中加入人机交互的设计和交互的细节,包括窗口和输出报告的设计。可以用原型来帮助实际交互机制进行开发和选择;
设计任务管理部分:这部分主要是识别事件驱动任务,识别时钟驱动任务,识别优先任务和关键任务,识别协调者,审查每个任务并定义每个任务。设计数据管理部分:数据管理部分提供了在数据管理系统中存储和检索对象的基本结构,其目的是隔离数据管理方法对其他部分的影响。
2.Booch 方法
Booch 认为软件开发是一个螺旋上升的过程,每个周期中包括标识类和对象、确定类和对象的含义、标识关系、说明每个类的接口和实现 4 个步骤。它的模型中主要包括如表 8-5 所示的几种图形。
Booch 方法的开发过程是一个迭代的、渐进式的系统开发过程,它可以分为宏过程和微过程两类。宏过程用于控制微过程,是覆盖几个月或几周所进行的活动,它包括负责建立核心需求的概念化,为所期望的行为建立模型的分析,建立架构的设计,形成实现的进化,以及管理软件交付使用的维护等 5 个主要活动。
而微过程则基本上代表了开发人员的日常活动,它由 4 个重要、没有顺序关系的步骤组成:在给定的抽象层次上识别出类和对象,识别出这些类和对象的语义,识别出类间和对象间的关系,实现类和对象。
3.OMT 方法
OMT 是对象建模技术的缩写,它是由 Jam Rambaugh 及其同事合作开发的,它主要用于分析、系统设计和对象设计。包括对象模型(静态的、结构化的系统的“数据”性质,通常采用类图)、动态模型(瞬时的、行为化的系统“控制”性质,通常使用状态图)和功能模型(表示变化的系统的“功能”性质,通常使用数据流图)。OMT 方法的三大模型如表 8-6 所示。
4.OOSE 方法
OOSE 是面向对象软件工程的缩写,它是由 Ivar Jacobson 提出的。它在 OMT 的基础上,对功能模型进行了补充,提出了“用例”的概念,最终取代数据流图进行需求分析和建立功能模型。
8.4.3 统一建模语言
统一建模语言(Unified Modeling Language,UML)是用于系统的可视化建模语言,它将OMT、OOSE 和 Booch 方法中的建模语言和方法有机地融合在一起,是国际统一的软件建模标准。虽然它源于 OO 软件系统建模领域,但由于其内建了大量扩展机制,也可以应用于更多的领域中,例如工作流程、业务领域等。
1.UML 是什么
-
UML 是一种语言:UML 在软件领域中的地位与价值就像“1、2、3、+、 、…”等符号在数学领域中的地位一样。它为软件开发人员之间提供了一种用于交流的词汇表和一种用于软件蓝图的标准语言。
-
UML 是一种可视化语言:UML 只是一组图形符号,它的每个符号都有明确语义,是一种直观、可视化的语言。UML 是一种可用于详细描述的语言:UML 所建的模型是精确的、无歧义和完整的,因此适合于对所有重要的分析、设计和实现决策进行详细描述。
-
UML 是一种构造语言:UML 虽然不是一种可视化的编程语言,但其与各种编程语言直接相连,而且有较好的映射关系,这种映射允许进行正向工程、逆向工程。
-
UML 是一种文档化语言:它适合于建立系统架构及其所有的细节文档。
2.UML 的结构
UML 由构造块、公共机制和架构三个部分组成。
(1)构造块。构造块也就是基本的 UML 建模元素(事物)、关系和图。
建模元素:包括结构事物(类、接口、协作、用例、活动类、组件、节点等)、行为事物(交互、状态机)、分组事物(包)、注释事物。关系:包括关联关系、依赖关系、泛化关系、实现关系。图:UML 2.0 包括 14 种不同的图,分为表示系统静态结构的静态模型(包括类图、对象图、包图、构件图、部署图、制品图),以及表示系统动态结构的动态模型(包括对象图、用例
图、顺序图、通信图、定时图、状态图、活动图、交互概览图)。
(2)公共机制。公共机制是指达到特定目标的公共 UML 方法,主要包括规格说明、修饰、公共分类和扩展机制 4 种。规格说明:规格说明是元素语义的文本描述,它是模型的重要组成部分。修饰:UML 为每一个模型元素设置了一个简单的记号,还可以通过修饰来表达更多的信息。公共分类:包括类元与实体(类元表示概念,而实体表示具体的实体)、接口和实现(接口用来定义契约,而实现就是具体的内容)两组公共分类。扩展机制:包括约束(添加新规则来扩展元素的语义)、构造型(用于定义新的 UML建模元素)、标记值(添加新的特殊信息来扩展模型元素的规格说明)。
(3)架构。UML 对系统架构的定义是:系统的组织结构,包括系统分解的组成部分、它们的关联性、交互、机制和指导原则,这些提供系统设计的信息。而具体来说,就是指 5 个系统视图。
- 逻辑视图:以问题域的语汇组成的类和对象集合。
- 进程视图:可执行线程和进程作为活动类的建模,它是逻辑视图的一次执行实例。
- 实现视图:对组成基于系统的物理代码的文件和组件进行建模。
- 部署视图:把组件物理地部署到一组物理的、可计算的节点上。
- 用例视图:最基本的需求分析模型。
3.用例图基础
用例是什么呢?Ivar Jacobson 是这样描述的:“用例实例是在系统中执行的一系列动作,这些动作将生成特定参与者可见的价值结果。一个用例定义一组用例实例。”首先,从定义中得知用例是由一组用例实例组成的,用例实例也就是常说的“使用场景”,就是用户使用系统的一个实际的、特定的场景。其次,可以知道,用例应该给参与者带来可见的价值,这点很关键。最后,用例是在系统中的。
而用例模型描述的是外部参与者所理解的系统功能。用例模型用于需求分析阶段,它的建立是系统开发者和用户反复讨论的结果,表明了开发者和用户对需求规格达成的共识。图8-12 就是一个用例图的例子。
(1)参与者。参与者代表与系统接口的任何事物或人,它是指代表某一种特定功能的角色,因此,参与者都是虚拟的概念。在 UML 中,用一个小人表示参与者。
图 8-12 中的“图书管理员”就是参与者。对于该系统来说,可能可以充当图书管理员角色的有多个人,由于他们对系统均起着相同的作用,扮演相同的角色,因此只用一个参与者来表示。切忌不要为每一个可能与系统交互的真人画出一个参与者。
(2)用例。用例是对系统行为的动态描述,它可以促进设计人员、开发人员与用户的沟通,理解正确的需求,还可以划分系统与外部实体的界限,是系统设计的起点。在识别出参与者之后,可以使用下列问题帮助识别用例。
- 每个参与者的任务是什么?
- 有参与者将要创建、存储、修改、删除或读取系统中的信息吗?
- 什么用例会创建、存储、修改、删除或读取这个信息?
- 参与者需要通知系统外部的突然变化吗?
- 需要通知参与者系统中正在发生的事情吗?
- 什么用例将支持和维护系统?
- 所有的功能需求都对应到用例中了吗?
- 系统需要何种输入/输出?输入从何处来?输出到何处?
- 当前运行系统的主要问题是什么?
(3)包含和扩展。两个用例之间的关系可以主要概括为两种情况。一种是用于重用的包含关系,用构造型<>或者<
-
包含关系:当可以从两个或两个以上的原始用例中提取公共行为,或者发现能够使用一个组件来实现某一个用例的部分功能是很重要的事时,应该使用包含关系来表示。所提取出来的公共行为称为抽象用例。包含关系的例子如图 8-13 所示。
-
扩展关系:如果一个用例明显地混合了两种或两种以上的不同场景,即根据情况可能发生多种事情。可以将这个用例分为一个主用例和一个或多个辅用例,描述可能更加清晰。扩展关系的例子如图 8-14 所示。
此处介绍的包含和扩展关系属于用例之间所特有的关系,因为用例也是 UML 的一种结构事物,因此,事物之间的 4 种基本关系对用例也是适用的。
4.类图和对象图基础
在面向对象建模技术中,将客观世界的实体映射为对象,并归纳成一个个类。类、对象和它们之间的关联是面向对象技术中最基本的元素。对于一个想要描述的系统,其类模型和对象模型揭示了系统的结构。在 UML 中,类和对象模型分别由类图和对象图表示。类图技术是 OO 方法的核心。图 8-15 是一个类图的实例。
(1)类和对象。对象与人们对客观世界的理解相关。人们通常用对象描述客观世界中某个具体的实体。所谓类是对一类具有相同特征的对象的描述。而对象是类的实例。在 UML 中,类的可视化表示为一个划分成三个格子的长方形(下面两个格子可省略)。图 8-15 中,“书籍”、“借阅记录”等都是一个类。
-
类的获取和命名:最顶部的格子包含类的名字。类的命名应尽量用应用领域中的术语,应明确、无歧义,以利于开发人员与用户之间的相互理解和交流。
-
类的属性:中间的格子包含类的属性,用以描述该类对象的共同特点。该项可省略。图 8-15 中“书籍”类有“书名”、“书号”等属性。UML 规定类的属性的语法为: “可见性 属性名:类型 = 默认值 {约束特性}”。
可见性包括 Public、Private 和 Protected,分别用+、-、#号表示。类型表示该属性的种类:它可以是基本数据类型,例如整数、实数、布尔型等,也可以是用户自定义的类型。一般它由所涉及的程序设计语言确定。约束特性则是用户对该属性性质的一个约束说明。例如“{只读}”说明该属性是只读属性。 -
类的操作(Operation):该项可省略。操作用于修改、检索类的属性或执行某些动作。操作通常也被称为功能,但是它们被约束在类的内部,只能作用到该类的对象上。操作名、返回类型和参数表组成操作界面。UML 规定操作的语法为:“可见性:操作名(参数表):返回类型 {约束特性}”。 类图描述了类和类之间的静态关系。定义了类之后,就可以定义类之间的各种关系了。
类图描述了类和类之间的静态关系。定义了类之后,就可以定义类之间的各种关系了。
(2)类之间的关系。在建立抽象模型时,会发现很少有类会单独存在,大多数都将会以某种方式互相协作,因此还需要描述这些类之间的关系。关系是事物间的连接,在面向对象建模中,有 4 个很重要的关系。
① 依赖关系。有两个元素 X、Y,如果修改元素 X 的定义可能会引起对另一个元素 Y 的定义的修改,则称元素 Y 依赖于元素 X。在 UML 中,使用带箭头的虚线表示依赖关系。在类中,依赖由多种原因引起,如:一个类向另一个类发消息;一个类是另一个类的数据成员;一个类是另一个类的某个操作参数。如果一个类的界面改变,它发出的任何消息可能不再合法。
② 泛化关系。泛化关系描述了一般事物与该事物中的特殊种类之间的关系,也就是父类与子类之间的关系。继承关系是泛化关系的反关系,也就是说子类是从父类中继承的,而父类则是子类的泛化。在 UML 中,使用带空心箭头的实线表示,箭头指向父类。
在 UML 中,对泛化关系有 3 个要求:
子类应与父类完全一致,父类所具有的关联、属性和操作,子类都应具有。
子类中除了与父类一致的信息外,还包括额外的信息。可以使用子父类实例的地方,也可以使用子类实例。
③ 关联关系。关联表示两个类之间存在某种语义上的联系。例如,一个人为一家公司工作,一家公司有许多办公室。就认为人和公司、公司和办公室之间存在某种语义上的联系。关联关系提供了通信的路径,它是所有关系中最通用的、语义最弱的。在 UML 中,用一条实线来表示关联关系。
聚合关系:聚合是一种特殊形式的关联。聚合表示类之间的关系是整体与部分的关系。例如一辆轿车包含四个车轮、一个方向盘、一个发动机和一个底盘,就是聚合的一个例子。在 UML 中,用一个带空心菱形的实线表示,空心菱形指向的是代表“整体”的类。
组合关系:如果聚合关系中的表示“部分”的类的存在,与表示“整体”的类有着紧密的关系,例如“公司”与“部门”之间的关系,那么就应该使用“组合”关系来表示。
在 UML 中,用带有实心菱形的实线表示,菱形指向的是代表“整体”的类。聚合关系是指部分与整体的生命周期可以不相同,而组合关系则是指部分与整体的生命周期是相同的。
④ 实现关系。实现关系是用来规定接口和实现接口的类或组件之间的关系的。接口是操作的集合,这些操作用于规定类或组件的服务。在 UML 中,用一个带空心箭头的虚线表示。
(3)多重性问题。重复度又称多重性,多重性表示为一个整数范围 n…m,整数 n 定义所连接的最少对象的数目,而 m 则为最多对象数(当不知道确切的最大数时,最大数用号表示)。最常见的多重性有:0…1;0…;1…1;1…;。
多重性是用来说明关联的两个类之间的数量关系的,例如:
书与借书记录之间的关系,就应该是 1 对 0…1 的关系,也就是一本书可以有 0 个或 1 个借书记录。
经理与员工之间的关系,则应为 1 对 0…*的关系,也就是一个经理可以领导 0 个或多个员工。
学生与选修课程之间的关系,就可以表示为 0…*对 1…*的关系,也就是一个学生可以选择1 门或多门课程,而一门课程可以有 0 个或多个学生选修。
(4)类图。对于软件系统,其类模型和对象模型类图描述类和类之间的静态关系。与数据模型不同,它不仅显示了信息的结构,同时还描述了系统的行为。类图是定义其他图的基础。
(5)对象图。UML 中对象图与类图具有相同的表示形式。对象图可以看作是类图的一个实例。对象是类的实例;对象之间的链(Link)是类之间的关联的实例。对象与类的图形表示相似,均为划分成两个格子的长方形(下面的格子可省略)。上面的格子是对象名,对象名下有下画线;下面的格子记录属性值。链的图形表示与关联相似。对象图常用于表示复杂类图的一个实例。
5.交互图基础
交互图是表示各组对象如何依某种行为进行协作的模型。通常可以使用一个交互图来表示和说明一个用例的行为。在 UML 中,包括 3 种不同形式的交互图,强调对象交互行为顺序的顺序图,强调对象协作的通信图(UML1.X 版本中称为“协作图”),强调消息的具体时间的定时图,它们之间没有什么本质不同,只是排版不尽相同而已。
(1)顺序图。顺序图用来描述对象之间动态的交互关系,着重体现对象间消息传递的时间顺序。顺序图允许直观地表示出对象的生存期,在生存期内,对象可以对输入消息做出响应,并且可以发送信息。图 8-16 是一个顺序图的示例。
如图 8-16 所示,顺序图存在两个轴,水平轴表示不同的对象,即图中的 Client、Factory、Product 等;而垂直轴表示时间,表示对象及类的生命周期。
对象间的通信通过在对象的生命线间画消息来表示。消息的箭头指明消息的类型。顺序图中的消息可以是信号、操作调用或类似于 C++中的 RPC(Remote Procedure Calls)和 Java 中的 RMI(Remote Method Invocation)。当收到消息时,接收对象立即开始执行活动,即对象被激活了。通过在对象生命线上显示一个细长矩形框来表示激活。 消息可以用消息名及参数来标识,消息也可带有顺序号。消息还可带有条件表达式,表示分支或决定是否发送消息。如果用于表示分支,则每个分支是相互排斥的,即在某一时刻仅可发送分支中的一个消息。
(2)通信图。通信图用于描述相互合作的对象间的交互关系和链接关系。虽然顺序图和通信图都用来描述对象间的交互关系,但侧重点不一样。顺序图着重体现交互的时间顺序,通信图则着重体现交互对象间的静态链接关系。图 8-17 就是与图 8-16 相对应的通信图,可以从图 8-17 中很明显地发现它与顺序图之间的异同点。
(3)定时图。如果要表示的交互具有很强的时间特性(例如,现实生活中的电子工程、实时控制等系统中),在 UML 1.X 中是无法有效地表示出来的。而在 UML 2.0 中引入了一种新的交互图来解决这类问题,这就是着重表示定时约束的定时图。 根据 UML 的定义,定时图实际上是一种特殊形式的顺序图(即一种变化),它与顺序图的区别主要体现在以下几个方面。
坐标轴交换了位置,改为从左到右来表示时间的推移。用生命线的“凹下凸起”来表示状态的变化,每个水平位置代表一种不同的状态,状态的顺序可以有意义、也可以没有意义。生命线可以跟在一根线后面,在这根线上显示一些不同的状态值。可以显示一个度量时间值的标尺,用刻度来表示时间间隔。
图 8-18 是一个定时图的实际例子,其中小黑点加曲线表示的是注释。它用来表示一个电子门禁系统的控制逻辑,该门禁系统包括门(物理的门)、智能读卡器(读取用户的智能卡信息)、处理器(用来处理是否开门的判断)。
在这个例子中,它所表示的意思是一开始读卡器是启用的(等用户来刷卡)、处理器是空闲的(没有验证的请求)、门是关的;接着,当用户刷卡时,读卡器就进入了“等待校验”的状态,并发一个消息给处理器,处理器就进入了校验状态。如果校验通过,就发送一个“禁用”消息给读卡器(因为门开的时候,读卡器就可以不工作),使读卡器进入禁用状态;并且自己转入启用状态,这时门的状态变成了“开”。而门“开”了 30 秒钟(根据时间刻度得知)之后,处理器将会把它再次“关”上,并且发送一个“启用”消息给读卡器(门关了,读卡器开始重新工作),这时读卡器再次进入启用状态,而处理器已经又回到了空闲状态。
从上面的例子中,不难看出定时图所包含的图元并不多,主要包括生命线、状态、状态变迁、消息、时间刻度,可以根据自身的需要来使用它。
6.状态图基础状态图
用来描述一个特定对象的所有可能状态及其引起状态转移的事件。大多数面向对象技术都用状态图表示单个对象在其生命周期中的行为。一个状态图包括一系列的状态及状态之间的转移。图 8-19 是一个数码冲印店的订单状态图实例。
状态图包括以下部分。
- 状态:又称为中间状态,用圆角矩形框表示;
- 初始状态:又称为初态,用一个黑色的实心圆圈表示,在一张状态图中只能够有一个初始状态;
- 结束状态:又称为终态,在黑色的实心圆圈外面套上一个空心圆,在一张状态图中可能有多个结束状态;
- 状态转移:用箭头说明状态的转移情况,并用文字说明引发这个状态变化的相应事件是什么。
一个状态也可能被细分为多个子状态,那么如果将这些子状态都描绘出来的话,那这个状态就是复合状态。
状态图适合用于表述在不同用例之间的对象行为,但并不适合用于表述包括若干用例协作的对象行为。通常不会需要对系统中的每一个类绘制相应的状态图,而通常会在业务流程、控制对象、用户界面的设计方面使用状态图。
7.活动图基础
活动图的应用非常广泛,它既可用来描述操作(类的方法)的行为,也可以描述用例和对象内部的工作过程。活动图是由状态图变化而来的,它们各自用于不同的目的。活动图依据对象状态的变化来捕获动作(将要执行的工作或活动)与动作的结果。活动图中一个活动结束后将立即进入下一个活动(在状态图中状态的变迁可能需要事件的触发)。
(1)基本活动图。图 8-20 给出了一个基本活动图的例子。
如图 8-20 所示,活动图与状态图类似,包括了初始状态、终止状态,以及中间的活动状态,每个活动之间,也就是一种状态的变迁。在活动图中,还引入了以下几个概念。
判定:说明基于某些表达式的选择性路径,在 UML 中使用菱形表示。
分支与组合:由于活动图建模时,经常会遇到并发流,因此在 UML 中引入了如上图 8-20 所示的粗线来表示分支和组合。
(2)带泳道的活动图。在前面说明的基本活动图中,虽然能够描述系统发生了什么,但没有说明该项活动由谁来完成。而针对 OOP 而言,这就意味着活动图没有描述出各个活动由哪个类来完成。要想解决这个问题,可以通过泳道来解决这一问题。它将活动图的逻辑描述与顺序图、协作图的责任描述结合起来。图 8-21 是一个使用了泳道的例子。
(3)对象流。在活动图中可以出现对象。对象可以作为活动的输入或输出,对象与活动间的输入/输出关系由虚线箭头来表示。如果仅表示对象受到某一活动的影响,则可用不带箭头的虚线来连接对象与活动。
(4)信号。在活动图中可以表示信号的发送与接收,分别用发送和接收标识来表示。发送和接收标识也可与对象相连,用于表示消息的发送者和接收者。
8.构件图基础
构件图是面向对象系统的物理方面进行建模要用的两种图之一。它可以有效地显示一组构件,以及它们之间的关系。构件图中通常包括构件、接口及各种关系。图 8-22 就是一个构件图的例子。
通常构件指的是源代码文件、二进制代码文件和可执行文件等。而构件图就是用来显示编译、链接或执行时构件之间的依赖关系的。例如,在图 8-22 中,就是说明 QueryClient.exe 将通过调用 QueryServer.exe 来完成相应的功能,而 QueryServer.exe 则需要 Find.exe 的支持, Find.exe 在实现时调用了 Query.dll。
通常来说,可以使用构件图完成以下工作。
- 对源代码进行建模:这样可以清晰地表示出各个不同源程序文件之间的关系。
- 对可执行体的发布建模:如图 8-22 所示,将清晰地表示出各个可执行文件、DLL 文件之间的关系。
- 对物理数据库建模:用来表示各种类型的数据库、表之间的关系。
- 对可调整的系统建模:例如对应用了负载均衡、故障恢复等系统的建模。
在绘制构件图时,应该注意侧重于描述系统的静态实现视图的一个方面,图形不要过于简化,应该为构件图取一个直观的名称,在绘制时避免产生线的交叉。
9.部署图基础
部署图,也称为实施图,它和构件图一样,是面向对象系统的物理方面建模的两种图之一。构件图是说明构件之间的逻辑关系,而部署图则是在此基础上更进一步地描述系统硬件的物理拓扑结构及在此结构上执行的软件。部署图可以显示计算结点的拓扑结构和通信路径、结点上运行的软件构件,常用于帮助理解分布式系统。
图 8-23 就是与图 8-22 对应的部署图,这样的图示可以使系统的安装、部署更为简单。在部署图中,通常包括以下一些关键的组成部分。
(1)节点和连接。节点代表一个物理设备及其上运行的软件系统,如一台 UNIX 主机、一个 PC 终端、一台打印机、一个传感器等。
如图 8-23 所示,“客户端:个人 PC”和“服务器”就是两个节点。在 UML 中,使用一个立方体表示一个节点,节点名放在左上角。节点之间的连线表示系统之间进行交互的通信路径,在 UML 中被称为连接。通信类型则放在连接旁边的“《》”之间,表示所用的通信协议或网络类型。
(2)构件和接口。在部署图中,构件代表可执行的物理代码模块,如一个可执行程序。逻辑上它可以与类图中的包或类对应。例如,在图 8-23 中,“服务器”结点中包含“QueryServer.exe”、“Find.exe”和“Query.dll”3 个构件。
在面向对象方法中,类和构件等元素并不是所有的属性和操作都对外可见。它们对外提供了可见操作和属性,称之为类和构件的接口。界面可以表示为一头是小圆圈的直线。在图8-23 中,“Query.dll”构件提供了一个“查询”接口。
8.5 用户界面设计
接口设计主要包括三个方面的内容:一是设计软件构件间的接口;二是设计模块和其他非人的信息生产者和消费者(如外部实体)的接口;三是人(如用户)和计算机间界面设计。
软件构件间接口的设计与架构的设计紧密相关,而设计模块和外部实体的接口则与详细设计相关,人机界面接口是相当容易被忽视的环节,在此就对其重点内容进行一个概要性描述。
8.5.1 用户界面设计的原则
用户界面设计必须考虑软件使用者的体力和脑力,根据 Theo Mandel 的总结,设计时必须遵从三个黄金法则。
置用户于控制之下:具体来说就是以不强迫用户进入不必要的或不希望的动作的方式来定义交互模式、提供灵活的交互、允许用户交互可以被中断和撤销、当技能级别增长时可以使交互流水化并允许定制交互、使用户隔离内部技术细节、设计应允许用户和出现在屏幕上的对象直接交互。
减少用户的记忆负担:具体来说就是减少对短期记忆的要求、建立有意义的默认、定义直觉性的捷径、界面的视觉布局应该基于对真实世界的隐喻、以不断进展的方式提示信息。保持界面的一致:具体来说,就是允许用户将当前任务放入有意义的语境、在应用系列内保持一致性,如果过去的交互模型已经建立了用户期望,除非有不得已的理由,否则不要改变它。
除此之外,还应该考虑表 8-7 所示的设计原则。
8.5.2 用户界面设计过程
用户界面的设计过程也应该是迭代的,它通常包括 4 个不同的框架活动,如图 8-24所示。
(1)用户、任务和环境分析:着重于分析将和系统交互的用户的特点。记录下技术级别、业务理解及对新系统的一般感悟,并定义不同的用户类别。然后对用户将要完成什么样的任务进行详细的标识和描述。最后对用户的物理工作环境进行了解与分析。
(2)界面设计:主要包括建立任务的目标和意图,为每个目标或意图制定特定的动作序列,按在界面上执行的方式对动作序列进行规约,指明系统状态,定义控制机制,指明控制机制如何影响系统状态,指明用户如何通过界面上的信息来解释系统状态。
(3)实现:就是根据界面设计进行实现,前期可以通过原型工具来快速实现,减少返工的工作量。
(4)界面确认:界面实现后就可以进行一些定性和定量的数据收集,以进行界面的评估,以调整界面的设计。
8.6 工作流设计
工作流技术的发展,经过多年的努力,取得了一定的成果。但在实际应用中,应用的企业还是较少,应用的范围窄,效果不理想。
流程的设计是对设计者更高的挑战,现实中对计算机所管理的流程需要灵活的定义、方便的路径修改、容易使用,可是这几个目标是矛盾的。更严重的是,如何分析现实中的流程本身就是个困难的问题,更不用谈如何来设计实现了。流程设计的主要困难实际上也就是软件的主要困难:现实复杂性。
任何对现实的描述(图形也罢,文字也罢)都是不完美的,“不识庐山真面目”是设计面临的共同难题。设计者不得不意识到所有的流程模型都是对现实的简化,计算机只根据确定的信息作判断,而现实中的流程存在大量的不确定性,虽然计算机专家们自信地告诉企业管理者这是管理的问题,信誓旦旦地保证可以用计算机系统来“完善”企业的管理,但他们似乎没有意识到企业管理已经发展了几百年,而计算机还没有百年的历史。
人们常常抱怨计算机系统的流程设计太过刻板,因为许多时候,标准流程是先于应用构造的且由一些集中的权威强制执行的,所以这种刻板性是不可避免的。同时,对参与者而言缺乏自由度导致工作流管理系统显得很不友好。结果是它们经常被忽略或绕过,甚至最终被放弃。
另外的困难是:对于流程处理,不但名称众多,例如,动态模型、工作流等,而且对流程的定义也是千姿百态。面对这些困难,设计者无疑需要巨大的勇气来进行流程设计。
8.6.1 工作流设计概述
限于篇幅,这里只列出工作流管理联盟对于工作流的定义:“工作流是一类能够完全或者部分自动执行的经营过程,根据一系列过程规则、文档、信息或任务在不同的执行者之间传递、执行”。
(1)工作流。简单地说,工作流是现实中的具体工作从开始到结束过程的抽象和概括。这个过程包括了众多因素:任务顺序、路线规则、时间时限约束等。
(2)流程定义。流程定义是指对业务过程的形式化表示,它定义了过程运行中的活动和所涉及的各种信息。这些信息包括过程的开始和完成条件、构成过程的活动及进行活动间导航的规则、用户所需要完成的任务、可能被调用的应用、工作流间的引用关系,以及工作流数据的定义。这个定义的过程可能是由设计者用纸和笔来完成的,但越来越多的设计者倾向于使用流程定义工具来完成这个工作。
(3)流程实例。也常常称为工作,是一个流程定义的运行实例。例如客户的一次订购过程,客服中心受理的一次客户投诉过程等。
(4)工作流管理系统。和数据库管理系统类似,是一个软件系统。这个程序存储流程的定义,按照所使用的流程定义来触发流程状态的改变,推动流程的运转。这个推动的依据常常称为工作流引擎。
(5)流程定义工具。同样是一套软件系统,这个软件和工作流管理系统的关系就如同数据库设计工具和数据库管理系统的关系一样。它可能是独立的软件,也可能是工作流管理系统的一部分。如前所说,设计者常常使用流程定义工具来完成流程定义的工作。它提供一些常用的工作流元素素材,以提高设计者的效率。
(6)参与者。回答业务流程中“谁”这个问题。它可以是具体的人或者角色(企业内部有特别共同作用的多个人),也可以是自动化系统,甚至是其他系统。
(7)活动。活动是流程定义中的一个元素,一次活动可能改变流程处理数据的内容、流程的状态,并可能将流程推动到其他活动中去。活动可以由人来完成,也可以是系统自动的处理过程,典型的自动处理是当活动超过了这个活动可以容忍的时限时,自动过程将向流程定义中指定的参与者发出一条消息。
(8)活动所有者。参与者之一,他有权决定该活动是否结束,当他决定活动结束时,将活动推动到其他活动中,可能是下一个活动,也可能是前一个活动。
(9)工作所有者。工作所有者是有权整体控制流程实例执行过程的参与者。
(10)工作项。代表流程实例中活动的参与者将要执行的工作。要分析现实中的处理流程,必须首先描述目标系统的流程,这个过程也可以称为建模。
流程是个复杂的事务,必须从多方面才可以描述一个流程,包括:“谁”,流程的参与者;“什么”,参与者做什么工作;“何时”,工作完成的时间限制,还需要说明工作的数据流和完成工作的控制流。人们认为自然语言在描述如此复杂的事务时容易引起歧义,所以人们定义了一些形式化语言试图在自然语言中挑选一个子集,这个子集既可以真正描述流程,又能够摆脱自然语言的复杂和多变,实际上想在人和机器在理解处理流程上架起一座桥梁,如同其他
计算机语言及后来发展的统一建模语言一样,这些形式化的语言也称为“工作流定义语言”。
同样,为了描述实际中的处理流程,人们也想到了图形的方式。有限状态自动机是一种分析状态和改变状态的良好工具,这种方法需要完全列出流程中所有状态及这些状态的组合,当处理流程变得庞大时,自动机所对应的状态图膨胀得太厉害。由于 Petri 网有严格的数学基础和图形化的规范语义,在描述离散事件动态系统方面的能力已经得到公认,具有较强的模型分析能力,在工作流的描述和分析中已经是人们广泛采用的一种方法。虽然有人认为图
形并非工作流的最佳表示方法,但由于图形的直观性,大多数设计者都愿意采用图形的描述方式。有关有限状态自动机和 Petri 网的论述请参考其他书籍。
8.6.2 工作流管理系统
根据工作流管理联盟(Workflow Management Coalition,WFMC)的定义,工作流管理系统是一种“在工作流形式化表示的驱动下,通过软件的执行而完成工作流定义、管理及执行的系统”,其主要目标是对业务过程中各活动发生的先后次序及与活动相关的相应人力或信息资源的调用进行管理,而实现业务过程的自动化。 如同关系数据库一样,现在已经出现了专门的工作流管理系统,这些系统经过专门的设计,从不同的角度负责解决设计者在流程设计中遇到的共同问题:节点定义、路径选择、数据流动等。不幸的是,和关系数据库共同基于关系代数、支持标准的 SQL 不同,这些工作流管理系统基于不同的数学模型,提供完全不同的接口。所以这些工作流管理系统各具特色,但在通用性和其他系统相互协作上的不足使得这些系统的应用受到了限制。 WFMC 给出了包含六个基本模块的参考模型,这六个模块被认为是工作流管理系统的最基本组成,这个参考模型同时包括了这些模块之间的接口标准。
(1)流程定义工具。这部分软件提供图形化或者其他方式的界面给设计者。由设计者将实际工作流程进行抽象,并将设计者提交的流程定义转换为形式化语言描述,提供给计算机工作流执行服务进行流程实例处理的依据。
(2)工作流执行服务。这个服务程序是工作流管理系统的核心,它使用一种或者多种数据流引擎,对流程定义进行解释,激活有效的流程实例,推动流程实例在不同的活动中运转。和客户应用程序、其他工作流服务执行程序及其他应用程序进行交互,从而完成流程实例的创建、执行和管理工作。同时这部分软件为每个用户维护一个活动列表,告诉用户当前必须处理的任务。如果有必要,还可以通过电子邮件甚至是短消息的形式提醒用户任务的到
达。
(3)其他工作流执行服务。大型的企业工作流应用,往往包括多个工作流管理系统。这就需要这些工作流管理系统之间进行有效的交互,避免画地为牢、信息孤岛的现象出现。
(4)客户应用程序。这是给最终用户的界面,用户通过使用这部分软件对工作流的数据进行必要的处理,如果用户是当前活动的拥有者,还可通过客户应用程序改变流程实例的活动,将流程实例推动到另外一个活动中。
(5)被调用应用程序。这常常是对工作流所携带数据的处理程序,用得很多的是电子文档的处理程序。它们由工作流执行服务在流程实例的执行过程中调用,向最终用户展示待处理数据。在流程定义中应该定义这些应用程序的信息,包括名称、调用方式、参数等。
(6)管理和监控工具。如同数据库管理系统或多或少地提供一些方式告诉管理员当前数据库的使用状态一样,工作流管理系统也应该提供对流程实例的状态查询、挂起、恢复、销毁等操作,同时提供系统参数、系统运行情况统计等数据。 看到这里,没有处理流程设计经验的设计者一定已经云里雾里了。确实,流程设计是系统设计中最困难的一部分,它的复杂性直接来源于现实世界的复杂性。而且直到现在,人们对流程的设计,仍然是在探索之中。
8.7 简单分布式计算机应用系统的设计
网络极大地扩展了计算机的应用范围,同时,由于升级到更强的服务器的费用常常远远高于购买多台档次稍低的机器,更何况虽然计算机有了长足的发展,可是单台计算机的功能仍然十分有限,利用联网的计算机协同工作,共同完成复杂的工作成为相对成本较低的选择,而且可以完成单台计算机所无法完成的任务。分布式系统使得这一目标成为可能。另外,网络本质上并不可靠,特别是远程通信,分布式系统还带来了并发和同步的问题。
分布式系统可以由两种完全不同的方式来进行协同和合作,第一种是基于实例的协作。这种方式所有的实例都处理自己范围内的数据,这些对象实例的地位是相同的,当一个对象实例必须要处理不属于它自己范围的数据时,它必须和数据归宿的对象实例通信,请求另外一个对象实例进行处理。请求对象实例可以启动对象、调用远程对象的方法,以及停止运行远程实例。基于实例的协作具有良好的灵活性,但由于实例之间的紧密联系复杂的交互模型,使得开发成本提高,而且,由于实例必须能够通过网络找到,所以通信协议必须包括实例的生存周期管理,这使得基于实例的协作大多只限于统一的网络,对于复杂的跨平台的系统就难以应付。所以基于实例的协作适用于比较小范围内网络情况良好的环境中,这种环境常常被称为近连接。这种情况下对对象的生存周期管理所带来不寻常的网络流量是可以容忍的。 使用基于实例的协作常常使用被称为“代理”的方法,某个对象实例需要调用远程对象
时,它可以只和代理打交道,由代理完成和远程对象实例的通信工作:创建远程对象,提交请求、得到结果,然后把结果提交给调用的对象实例。这样,这个对象实例甚至可以不知道自己使用了远程对象。当远程对象被替换掉(升级)时,对本地代码也没有什么需要修改的地方。
另外一种方式是基于服务的协作,该方法试图解决基于实例的协作的困难。它只提供远程对象的接口,用户可以调用这些方法,却无法远程创建和销毁远程对象实例。这样减少了交互,简化了编程,而且使得跨平台协作成为可能。同样由于只提供接口,这种协作方式使得对象间的会话状态难以确定,而且通信的数据类型也将有所限制,基本上很难使用自定义的类型。基于服务的协作适用于跨平台的网络,网络响应较慢的情况,这种环境常称为远连
接,这时,简化交互性更为重要,而频繁的网络交换数据会带来难以容忍的延时。
基于服务的协作往往采用分层次的结构,高层次的应用依赖于低层次的对象,而低层次对象实例的实现细节则没有必要暴露给高层次对象,这种安排使得高层次的实现不受低层次如何实现的影响,同时,当低层次服务修改时,高层次的服务也不应该受到影响。
设计者在进行设计时,通常会倾向于比较细致的设计,对象往往提供了大量的操作和方法,响应许多不同的消息,以增加达到系统的灵活性、可维护性等。这在单个系统中没有什么问题,当考虑分布式系统的设计时,这种细致的设计所带来对对象方法的大量调用会比较严重地影响性能,所以在分布式系统中,倾向于使用大粒度的设计方式,往往在一个方法中包含了许多参数,每个方法基本上代表了一个独立的功能。当然这样的设计使得参数的传递变得复杂,当需要修改参数时,需要对比较大范围的一段过程代码进行修改,而不是像小粒度设计一样,只需要修改少量的代码。
8.8 系统运行环境的集成与设计
在设计一个新的系统时,设计者必须考虑目标系统的运行环境问题,人们往往认为软件应该能够在任何环境中运行,常常看到这样的系统,硬件已经升级了多次,而软件还是原来的软件。软件的运行环境是指系统运行的设备、操作系统和网络配置。
本节给出软件运行的几个典型环境,设计者可以从这几种典型环境中选择适合自己的目标系统的环境,也可以将这些典型环境做一些组合,来满足自己设计的系统的特殊要求。
1.集中式系统
早期的计算机系统没有什么可以选择的,除了集中式系统。所有的操作都集中于一台主机中,而操作员必须在主机的附近操作,结果也在附近给出。这种系统仍然广泛地应用于批处理应用系统及更大的分布式系统的一部分。集中式系统常见于银行、保险、证券行业,它们含有大规模的处理应用。而现在流行的电子商务又给大型处理机注入了新的活力,人们发现电子商务要面对大量的事务,需要大型处理机来处理。但是,实践中很少单独使用集中式
系统,因为大量的系统需要处理在地理上分布得很远的连接请求,这些请求有的需要实时响应,并可能要发送到其他某个地方的一个集中式系统。所以,在现代的系统中,集中式系统通常是某个分布式系统的一个环节。
集中式系统由以下几个部分组成。
(1)单计算机结构:这种结构简单、容易维护,但是处理能力受到限制。
(2)集群结构:由多个计算机组成,这些计算机具有类似的硬件平台、操作系统等。通常采用负载均衡、资源共享等方式实现更大的处理能力和容量。
(3)多计算机结构:由多个计算机组成,这些计算机之间操作环境可能不同。适用于当系统可以分解成多个不同的子系统时。
2.分布式系统
在 7.9 节中,已经简单介绍了分布式系统。分布式系统由于网络的普遍延伸,费用的不断降低而越来越成为大型系统的首选环境。分布式系统必须基于网络,这个网络可以是在一个地域内的局域网,也可以是跨越不同城市乃至国家的广域网。对比集中式的计算机环境,分布式系统有着多种多样的形式。这也给设计者在确定系统运行环境时带来一定的烦恼。
3.C/S 结构
系统由提供服务的服务器和发起请求、接受结果的客户机构成。这种结构是一种可以使用很多方式实现的通用结构模型。并非只限于数据库的 C/S 结构,典型的还有网络打印服务系统,现在流行的网络游戏也显然是基于这种结构的。
4.多层结构
这种结构是 C/S 结构的扩展,典型的分为由存储数据的数据库服务器作为数据层、实现商业规则的程序作为逻辑层、管理用户输入输出的视图层所组成的三层结构。当系统更复杂时,可以再增加其他层次构成多层结构。
多层结构形式复杂,功能多样。实现多层结构常常需要来实现不同层次间通信的专门程序——管件,也称为中间件。中间件大多数实现远程程序调用、对象请求调度等功能。
现代企业级的计算机系统大量地基于分布式结构。支持分布式系统的软件也曾经如同雨后春笋。系统如何分层、如何处理分布带来的同步等问题也就同样在考验设计者。
5.Internet、Intranet 和 Extranet
Internet 是全球的网络集合,使用通用的 TCP/IP 协议来相互连接。Internet 提供电子邮件、文件传输、远程登录等服务。Intranet 是私有网络,只限于内部使用,也使用 TCP/IP 协议。Extranet 是一个扩展的 Intranet。它包括企业之外的和企业密切相关合作的其他企业。
Extranet 允许分离的组织交换信息并进行合作,这样就形成了一个虚拟组织。现在的 VPN 技术允许在公用网络上架构只对组织内部开发服务。
Web 同样基于 C/S 结构,实际上 Web 接口是一个通用的接口,不是只能使用浏览器的协议,它同样能够在普通的程序中使用。Internet 和 Web 已经给设计者提供了一个非常富有吸引力的选择方案。它的优势在于:它们已经成为网络的事实上的标准,支持它们的软件已经广泛地存在于全世界的计算机中,而且通信费用已经下降到很有竞争力的水平。从某种程度上来说,企业可以把 Internet 当作自己廉价的广域网。没有它们,电子商务还是水中月。
当然,事物有相反的一面,当设计者试图采用 Internet 时,必须考虑其不利的一面。Internet 的安全性过去是,现在是,以后仍然是设计者头痛的问题。其他诸如可靠性、系统吞吐量、不断发展的技术和标准都是影响系统选择它们作为运行环境的不利因素。 设计者应该根据目标系统的实际需要来选择不同的运行环境。不过,已经有越来越多的公司提供支持 Internet 和电子商务的接口。
8.9 系统过渡计划
当新系统似乎开发完毕,要取代原来的系统时,系统过渡就是设计者不得不面对的问题。这个问题,不幸的是,比许多人想象得要复杂,和软件开发一样,存在着许多冲突和限制。
例如,费用、客户关系、后勤保证和风险等。设计者需要考虑的问题也很多,其中比较重要的几个问题是:
如果同时运行两个系统,会给客户造成多大的开销;
如果直接运行新系统,客户面对的风险有多大;
对新系统试运行时的查错和纠错,以及出现严重错误而导致停止运行时的应急措施;
客户运行新系统将面临的不利因素有哪些;
人员的培训。
使用不同的系统过渡方案意味着不同的风险,不同的费用及不同的复杂度。
1.直接过渡
这是一种快速的系统过渡方式,当新系统运行时,立即关闭原来的系统。这种过渡方式非常简单,没有后勤保障的问题,也不要消耗很多资源。同时,它也意味着大风险,目标系统的特性决定了风险的大小。设计者主要要权衡当新系统失败时,系统停止运行或者勉强运行给客户带来的损失有多大。由于这种过渡方式简单而费用低廉,对于可以容忍停机一段时间的系统的实践者,可以采用这种方式。
2.并行过渡
设计者采用并行过渡方式,让新系统和旧系统在一段时间里同时运行,通过这样的旧系统作为新系统的备份,可以大大降低系统过渡的风险。可是并行过渡显然比直接过渡要消耗更多的资源:现有的硬件资源必须保证能同时跑两套系统,这常常意味着增加服务器和额外的存储空间,需要增加人员来同时使用两套系统,或者增加现有员工的工作量,让他们同时操作两套系统。这种方式同时也增加了管理和后勤保障的复杂度。据统计,并行过渡时期的
开销是旧系统单独运行时的 2.5~3 倍。
设计者还会发现有些系统无法使用并行过渡的方式,主要是客户没有足够的资源来维持两个系统同时运行,另外一种情况是新、旧系统差别太大,旧系统的数据无法为新系统采用。当客户无法使用并行过渡,又想尽可能地减少风险,设计者可以使用部分并行过渡的策略,使并行的开销减少到客户能够接受的范围内。
3.阶段过渡
通常在系统非常复杂、过于庞大以至于无法一次性进行过渡时采用,也适用于分阶段开发的系统。设计者需要设计一系列步骤和过程来完成整个系统的过渡,这种过渡方式和系统的复杂程度相关,随着系统的不同往往有很大的不同。和并行过渡一样,阶段过渡也能够减少风险,显然局部的失败要比全体的失败更容易接受,带来的损失更小。阶段过渡也带来了复杂性,有时候比并行过渡更加复杂。