第12章控制驱动部分的设计•12.1什么是控制驱动部分•12.2相关技术问题•12.3如何设计控制驱动部分•控制驱动部分是OOD模型的一个外围组成部分。该部分由系统中全部主动类构成。这些主动类描述了整个系统中所有主动对象,每个主动对象是系统中一个控制流动驱动者。12.1什么是控制驱动部分•控制流(controlflow)是一个在处理机上顺序执行的动作序列。在目前的实现技术中,一个控制流就是一个进程或者一个线程,在UML的文献中称之为控制流。•在OOD中,把系统中所有的主动对象表示清楚,就抓住了系统中每个控制流的源头,就可以把并发执行的所有的控制流梳理出清晰的脉络,所有的主动对象都用主动类描述,所有的主动类构成OOD模型的控制驱动部分。12.2相关技术问题•本节将从系统总体方案、软件体系结构、分布式系统的体系结构风格以及系统的并发性这几方面探讨控制驱动部分的设计中的技术问题。12.2.1系统总体方案•要开发一个较大的计算机应用系统,首先要制定一个系统总体方案。系统总体方案的内容包括:(1)项目的背景、目标与意义。(2)系统的应用范围。(3)对需求的简要描述,采用的主要技术。(4)使用的硬件设备、网络设施和商品软件。(5)选择的软件体结构风格。(6)规划中的网络拓扑结构。(7)子系统划分。(8)系统分布方案。(9)经费预算、工期估计、风险分析。(10)售后服务措施,对用户的培训计划。•对于OOD模型中控制驱动部分的设计而言,总体方案中所决定的下述问题是它的基本实现条件:(1)计算机硬件。(2)操作系统。(3)软件体系结构。(4)网络方案。(5)编程语言。(6)其他商品软件。12.2.2软件体系结构•软件体系结构是对系统的组成与组织结构较为宏观的描述,它按照功能部件和部件之间的联系与约束来定义系统,着重于软件系统自身的整体结构和部件间的交互。•部件和连接器被公认为体系结构的两大类构成部分。部件是软件系统的组成单元,在系统框架中起结构块的作用,是软件功能设计和实现的承载体。连接器是建立部件和部件之间连接的部件。•以下是几种典型的软件体系结构风格:(1)管道与过滤器风格(2)客户-服务器风格(3)面向对象风格(4)隐式调用风格(5)仓库风格(6)进程控制风格(7)解释器模型(8)黑板风格(9)层次风格(10)数据抽象风格12.2.3分布式系统的体系结构风格•主机+仿真终端体系结构。以一台计算机为主机,其他计算机只作为它的远程仿真终端。从应用系统的角度看,其软件体系结构和集中式的系统没有本质性差别,因为其功能和数据都集中在主机上,其他计算机只相当于一些终端设备而已。•文件共享体系结构。在这种体系结构中,系统功能分布到网络的各个节点上,数据存放在一个被称作文件服务器的主机上。在某些系统中也可以把数据分布到各个节点上。•客户-服务器体系结构。这种体系结构把分布在不同节点上的系统组成部分之间的关系处理为请求服务和提供服务的关系,提供服务的计算机称作服务器,请求服务的计算机称作客户机。客户-服务器体系结构衍出生了一些特点各异的变种:(1)两层客户-服务器体系结构这是早期最典型的客户-服务器体系结构。其特点是明显地区分客户机和服务器,把提供给多个节点共享的公共服务集中在一台服务器上,客户机则只配备与本地业务处理有关的功能和数据。客户机和服务器构成两个界限分明的层次,这就是两层客户-服务器结构。(2)对等式客户-服务器体系结构这种体系结构观点把客户机和服务器看成是相对的。根据实际需要,系统中的每一台计算机既可以作为客户机,又可以作为服务器,即每一台计算机既可以请求其他节点提供服务,又可以向其他节点提供服务。实际上,这是一种更具一般性的客户-服务器体系结构形式,其他形式都可以看作这种形式的受限的特例。(3)三层客户-服务器体系结构这种体系结构是在两层客户-服务器体系结构基础上改进和发展的结果。其中包括数据服务器、应用服务器和客户机三个层次。数据服务器存储和管理被整个系统共享的数据,提供对这些数据进行查询、更新、一致性维护等操作的服务。(4)瘦客户-服务器体系结构这种体系结构的思想是把分布到客户机上的功能尽可能减少。其目的是使客户机上软件的安装、维护和升级变得很容易。在一个分布区域较广的大型系统中,末端的客户机数量最多,分布范围也最广,往往延伸到维护力量薄弱的边远地区。(5)浏览器-服务器体系结构瘦客户-服务器的思想发展到极端,应用系统分布到客户机上的软件成分就只剩下了一个浏览器。用户在浏览器上进行人机交互操作,浏览器把用户命令转换为对服务器的请求,并把得到的处理结果向用户显示。12.2.4系统的并发性•在本小节关于并发系统的讨论中将使用“任务”、“进程”、“线程”、“控制流”、“主动对象”等一系列含义相近的术语。按以下的约定来使用这些术语:(1)在OOA和OOD中用主动对象的一个主动服务来描述一个任务,用主动类来描述一类主动对象。(2)在从用户需求的角度或者在较高的抽象层次上讨论和认识系统的并发性时,使用任务的概念,以明确系统中客观上要求有哪些任务并发执行。(3)从逻辑上看问题,忽略实现细节,可以说OOD模型中的一个主动对象的主动服务描述了一个控制流。(4)在实现阶段,主动对象、主动类的概念仍然存在,但是已被实现为程序代码中的对象和类,它们的每个主动服务将被具体地实现为进程或者线程。(5)把“任务”和“控制流”作为讨论问题、解释概念或陈述设计策略时使用的词汇,而把“主动对象”、“主动类”、“进程”作为模型或程序中的元素或技术术语。•顺序程序和并发程序:(1)顺序程序中只有一件事在进行处理,即使程序中包括多项工作,也不会在一个时间段同时做两项(或以上)工作。程序中可以有分支、循环、子程序调用等各种复杂情况,但是一切都按确定的逻辑进行。(2)如果说系统要在同一段时间内执行多个任务,而这些任务之间又没有确定的时间关系,这种系统就是并发系统。描述并发系统的程序叫做并发程序。并发程序要执行的多个任务在时间上没有确定的逻辑关系,但是又相互影响。•进程和线程:(1)进程是W.Dijkstra、C.A.R.Hoare和P.B.Hansen等人在20世纪60年代中期以后的一系列文章中提出并逐渐完善的,它的全称是顺序进程。采用进程的基本思想是:把一个并发程序分解成若干能够顺序执行的程序单位。每一个这样的程序单位的一次执行就叫做一个顺序进程。(2)线程在进程之后出现,它可以看作是并发程序设计技术的进一步发展,然而更重要的原因是由于并行计算技术的需要。进程既是处理机资源的分配单位又是其他资源的分配单位;而线程只是处理机资源的分配单位。一个进程可以包含一个或者多个线程。(3)从应用的角度看,进程的概念适合于解决系统固有的并发性问题。(4)从编程技术来看,线程概念的出现还有更重要的逻辑上的理由,那就是:一个进程的数据空间被该进程内的多个线程共享,使这些线程可以方便地交换信息。•当前应用系统的并发性。有些程序员虽然已经成功地开发出许多并发的应用系统,但是他们并没有觉察到自己曾经面对并发程序设计的挑战性问题。他们觉得,自己编写的程序和一个顺序程序没有什么两样。原因在于当前的开发环境和运行环境无形中已经帮助,甚至代替这些程序员解决了系统的并发问题。12.3如何设计控制驱动部分•设计OOD模型中控制驱动部分的关键,是识别系统中所有并发执行的任务,然后用主动对象来表示这些任务。12.3.1选择软件体系结构风格•分布式系统的设计中,除了采用面向对象风格以外,还需要在其他几种体系结构中做出选择。主要的选择是客户-服务器体系结构的几个变种,选择这些体系结构风格所考虑的因素包括:(1)被开发系统的特点。(2)网络协议。(3)可用的软件产品。(4)成本及其他,包括购置相应硬件及软件的成本、新开发软件的成本、系统的安装与维护成本。12.3.2确定系统分布方案•随着软件体系结构风格的选择,系统中的每个节点采用何种计算机以及它们之间如何连接也都将逐一明确。被开发的软件将分布到这些节点上。面对一个分散的计算环境,要考虑如何把对象分布到通过网络相连的各台计算机上。本小节围绕这一目标,讨论对象的分布、类的分布以及如何在模型中表示这种分布方案。•对象的分布。这里首先针对一般情况讨论对象分布策略:1)由数据决定对象分布,这又包括以下几点:(1)当应用系统中一个类的对象实例需要在文件或关系数据库中存储时,则定义与这个类的数据结构一致的文件或数据库表。(2)该类的每个对象实例用文件的一个记录或者用数据库的一个元组保存。当一个类有大量的对象实例时,通常只把当前正在被处理的对象读到内存,所以一般只需要为该类定义少量的内存空间的对象。(3)需要设计一个名为“对象存取器”的对象类,其功能是负责把内存中的对象实例保存到文件或数据库表中以及把文件或数据库表中的对象数据恢复成内存中的一个对象。2)由功能决定对象分布3)追踪消息4)UseCase•类的分布。关于类的分布,具体做法如下:(1)如果整个系统只需要在一个节点上创建某个类的对象实例,那么这个类就分布在这个节点上。(2)如果系统需要在多个节点上创建同一个类的对象实例,那么这个类主要分布在每个需要它的节点上。可以把其中一个节点上的这个类作为正本,而把其他节点上出现的这个类表示为副本。作为副本的类可以采用如图12-1所示的表示法。classname《副本》图12-1•类图的划分。为了表明对象和类在各个节点上的分布情况,需要在类图上采取相应的组织措施,把描述整个系统的集中式的类图分散到各个节点上,以分别描述分布在各个节点上的对象;最后要把每个节点上的类组织成一个主题。具体策略有以下两种:(1)把每个节点的主题看成是在整个系统的类图上划分出来的一个局部。(2)把每个节点上的主题看成一个独立的子系统,用一个定义完整的类图表示。•在类描述模板中的表示。下面给出类描述模板的描述格式:对象实例:{处理机:节点名{,节点名};内存对象:{名称[n元数组][文字描述]};外存对象:{名称[文字描述]};}12.3.3识别控制流•以节点为单位识别控制流。以每个节点为单位考虑在每个节点上运行的程序还需要如何并发,需要设计哪些控制流以及各个节点之间如何相互通信。以节点为单位识别控制流是本小节讨论的前提。•从用户需求出发认识控制流。现在需要考虑的是,每一个节点上的功能,还有哪些任务必须在同一台计算机上并发地执行。•从UseCase认识控制流。在以下情况下应考虑针对一个UseCase设计相应的控制线程:(1)用户希望一个UseCase所描述的功能在必要时能够与系统的其他功能同时进行处理。(2)一个UseCase所描述的功能是对系统中随机发生的异常事件(例如某一种中断信号)进行异常处理的。(3)对一个UseCase所描述的功能,用户可以在未经系统提示的情况下随时要求执行,这样的UseCase一般应由一个专门的控制流去处理。•为改善性能而增设的控制流。除了满足系统固有的并发要求之外,为了改善性能,可能需要增设执行以下几类任务的控制流:(1)低优先级任务(2)高优先级任务(3)紧急任务•参照OOA模型中的主动对象。主动对象的一个主动服务,是在创建之后不必接收其他对象的消息就可以主动执行的服务,从系统运行的角度看,这意味着主动对象的一个主动服务是一个控制流的源头,在OOD中,通过考察OOA模型中的主动对象可帮助确定这些控制流。•实现并行计算的控制流。如果被开发的系统包含并行计算问题,那么由一个任务分解成的每个可并行计算的子任务都应被设计为一个控制流。通常是用一个重量级的控制流——进程实现一个任务,用若干轻量级的控制流——线程实现各个子任务。•对其他控制流进行协调的控制流。当一个节点上有多个控制流存在时,往往需要设计一个对这些控制流进行协调和管理的控制流。•实现节点之间通信的控制流。在有些情况下可能不需要设计专门负责节点之间通信的控制流。但是在有些情况下,为了实现的方便,可能要设计一些专门负责与其他节点通信的控制流。12.3.4用主动对象表示控制流•确定了系统中需要设立哪些控