283.软件体系结构描述

 

 

 4.6 使用“4+1”模型描述软件体系结构

  对于同一座建筑,住户、建筑师、内部装修人员和电气工程师有各自的视角。这些视角反映了建筑物的不同方面,但它们彼此都有内在的联系,而且合起来形成了建筑物的总体结构。
  软件体系结构反映了软件系统的总的结构,它和建筑物一样,存在不同的角度来反映系统的体系结构。
  当面对一个复杂的系统时,必须从多个角度来考虑问题。在处理体系结构时我们通常只考虑系统功能方面的需求,而实际上除了功能,物理分布、过程通信和同步等也必须在体系结构一级加以考虑。这些来自不同方面的需求就形成了软件体系结构的不同视角。每种不同的视角说明了系统中不同角色或参与者(Stakeholder)各自所关注的焦点。每个视角都可以看成是一幅软件蓝图,同时具有自己的标记方法,可以选择自己的体系结构风格。
  当然,所有视角并不是完全独立的,不同视角之间的元素在一定的规则下是相关联的。
  从1990年开始,Rational公司的Philippe Kruchten对软件体系结构的不同视角进行了专门的研究,并于1995年在IEEE提出了用于体系结构描述的“4+1”视图模型(The 4+1 View Model of Architecture)。它们是逻辑视图(Logical View)、过程视图(Process View)、物理视图(Physical View)、开发视图(Development View),另外加上场景(Scenarios)。“4+1”视图模型为理解复杂系统的软件体系结构提供了一个简单和易于理解的方式。它从 5个不同的角度来描述软件,每个角度都显示了模型系统的一个具体方面。下面对该模型进行较详细的
介绍。
  “4+1”模型由5个视图组成,如图4-17所示。

图4-17 “4+1”视图模型
  其中:
  ● 逻辑视图:当采用面向对象的设计方法时,逻辑视图即是对象模型。
  ● 过程视图:描述系统的并发和同步方面的设计。
  ● 物理视图:描述软件到硬件之间的映射关系,反映系统在分布方面的设计。
  ● 开发视图:描述软件在开发环境下的静态组织结构。
  对体系结构进行的描述是围绕着以上4个视图展开的。然后,通过选择出的一些用例对体系结构加以说明。这些用例被称做场景,它们构成了第5个视图。实际上,体系结构在某种程度上是由场景演化而来的。
  体系结构的概念在每个视图里面都可以独立应用。这就是说,可以在每个视图里面定义体系结构的各种组成元素,如构件、连接件等。对于不同的视图,还可以选择不同的体系结构风格,因此在同一个系统结构中可以使用多种风格。此外,在每一种视图里,我们使用该视图特定的符号。这避免了符号用法和意义的混乱。“4+1”视图模型是一个十分通用的模型:可以使用其他的符号表示法,也可以使用其他的设计方法,尤其是逻辑视图和过程视图的分解。
  “4+1”模型实际上使得有不同需求的人员能够得到他们对于软件体系结构想要了解的东西。系统工程师先从物理视图,然后从过程视图靠近体系结构;最终使用者、客户、数据专家从逻辑视图看体系结构;项目经理、软件配置人员从开发视图看体系结构。
  要指出的是,不是所有的软件体系结构都需要完整的“4+1”视图。没有用的视图在体系结构描述中可以被省略,例如对于非常小的系统,逻辑视图和开发视图有可能非常相似,以至于没有必要把它们分开描述。场景视图在各种环境下都是有用的。
  下面将分别讨论这5种视图,考察每种视图所涉及的方面,所使用的符号表示,以及在描述和管理该视图时要用到的工具。下文中,将以简化了的专用自动交换分机系统和航空交通管制系统为例进行讨论。
4.6.1 逻辑视图的体系结构:面向对象的分解
  逻辑视图主要支持功能需求——系统应当向用户提供什么样的服务。从问题域出发,采用面向对象的方法,按照抽象、封装、继承的原则进行分解,得到代表着系统的关键抽象表示的集合。这些抽象表示的具体形式就是对象和对象的类。这种分级不仅是为了功能分析,而且还担负着在系统的各部分中确定公共机制和设计元素的作用。
  使用Rational/Booch方法,通过类图(Class Diagram)和类模板(Class Template)来表示逻辑体系结构。类图显示了类的集合和它们的逻辑关系:关联(Association)、组合(Composition)、使用(Usage)、继承(Inheritance)等。类模板则着眼于每个类的个体,强调类的主要操作,并确定对象的关键特征。当十分需要定义一个对象的内部行为时,要使用状态转换图(State Transition Diagram),或者是状态表(State Chart)。相关类的集合可以归到一起,称作类的种属(Class Category)。
  正如前面介绍的,“4+1”视图模型是一个十分通用的模型。除了面向对象的方法,还可以使用其他形式的逻辑体系结构。例如,当所面对的应用具有很明显的数据驱动的特征时,可以使用E-R图。
  1.逻辑视图的符号表示法
  逻辑体系结构的符号表示法(见图4-18)是从Booch方法派生而来的。它被极大地简化了,尤其大量简化了在这个设计阶段作用不大的各种修饰,只考虑对于体系结构有重要意义的元素。在设计工具上,可以使用Rational Rose等UML建模工具。公共的机制和服务在类设施(Class Utilities)中定义。

图4-18 逻辑视图的符号表示法
  2.逻辑视图的风格
  逻辑视图也可以采用面向对象的风格。逻辑视图设计的主要准则是,要设法在整个系统中保持一个单一的、连贯的对象模型,避免类和相关机制按照场地或处理器过早地分化。
  3.逻辑视图的例子
  图4-19(a)显示了一个专用自动交换分机的例子。
  专用自动交换分机用于在通信终端之间建立连接。通信终端可能是电话机、中继线(连接到中心室的线路)、专用线(专用自动交换分机和一般的交换分机之间的线路)、数据线、ISDN线等。不同的线路需要不同的线路接口卡的支持。线路控制器对象负责从线路接口卡接收信号,以及向它发送信号,并完成信号和一系列的事件(如开始、结束、计数等)之间的转换。控制器还必须受到严格的实时要求的约束。

图4-19 逻辑视图举例
(a) 专用自动交换分机的逻辑设计图; (b) 航空交通管制系统的逻辑设计图
  为了适应不同的接口,这个类有许多子类。终端对象负责维护终端的状态,并代表所在的线路提供通信服务。会话对象代表在一个对话中涉及的终端的集合。会话对象使用转换服务(逻辑地址和物理地址之间的映射、路由等)和连接服务建立两个终端之间的语音连接。
  和前一个系统相比,航空交通管制系统是一个规模大得多的系统。图4-19(b)中显示的是一个包括8个类种属(即类的分组)的航空交通管制系统的最顶层的类图。
4.6.2 过程视图的体系结构:过程分解
  过程体系结构考虑的是一些非功能性的需求,诸如性能、可用性等。它所要面对的问题有并发、分布、系统的完整性、容错能力等。它还要考虑怎样把过程体系结构与逻辑视图体系结构的要点相适应——对某个对象的某个操作实际上是在哪个控制线程上发生的。
  可以把过程体系结构分为几个抽象层次来描述,每个层次考虑不同的方面。在最高层次上,过程体系结构可以被视为一个逻辑网络的集合。每个独立执行的逻辑网络都是由通信程序(即“过程”)构成的。这些逻辑网络分布在一个通过LAN或WAN连接起来的硬件资源集合上。多个逻辑网络可能同时存在,并共享同样的物理资源。例如,逻辑网络的概念可用于区分在线处理系统和离线处理系统。
  这里所说的过程,是指构成一个可执行单元的一组任务。过程代表了在何种层次上过程体系结构可以进行策略控制,如启动、恢复、重新配置和关闭。
  软件被分为独立的任务的集合。每个任务是一个独立的控制线程,可以在一个处理节点上独立单独调度。因此可以将任务分为主任务和辅任务。主任务是需要单独解决的体系结构元素。辅任务是由于实现原因而在本地加入的附加任务(缓冲、超时等),例如可以将它们实现为轻量级的线程。
  主任务通过一套完善定义的任务间通信机制进行通信:同步的或异步的基于消息的通信服务、远程过程调用、时间广播等。不应当假设通信中的主任务处于同一个过程中或处在同一个处理节点上。辅任务的通信可以采用共享内存的方式或其他双方约定的方式。
  基于过程的体系结构设计图可以估计出消息流和过程负荷。
  1.过程视图的符号表示法
  这里介绍的过程体系结构符号表示法是从Booch为Ada任务分配提出的符号表示法扩展而来的。与逻辑视图的符号表示法类似,它也被极大地简化了,只考虑对于体系结构有重要意义的元素,如图4-20所示。

图4-20 过程视图的符号表示法
  在辅助工具的选择上,可以考虑使用TRW提供的UNAS(Universal Network Achitecture Services)产品。它可用于把各种过程和任务构建并实现为过程的逻辑网络。UNAS里面包含的一个工具SALE(Software Architecture Lifecycle Environment)支持这样的符号表示法。SALE允许过程体系结构的图形化描述,包括对可能的任务间通信路径的规格说明。然后,从这种规格说明可以自动生成相应的Ada或C++语言源代码。
  2.过程视图的风格
  有多种风格适合过程体系结构。例如管道-过滤器、客户/服务器及其变体(多客户/单服务器、多客户/多服务器等)。
  3.过程视图的例子
  在图4-21所示的例子中,所有的终端是由单一的一个终端过程处理的。这个终端过程由输入队列中的消息驱动。控制过程由3个任务组成,控制对象在其中之一上执行。低速循环任务扫描所有的非激活终端(200 ms),它将所有变为激活的终端放入高速循环扫描 (10 ms)的扫描列表中;高速循环扫描探测扫描列表里终端的重要的状态改变,并将这种改变传输给主控任务;主控任务解读这种状态改变并通过消息与相关终端通信。这里,控制过程内部的消息通信是通过共享内存的方式实现的。

图4-21 专用自动交换分机的过程设计图
4.6.3 开发视图的体系结构:子系统分解
  开发视图关注的是在软件开发环境中软件模块的实际组织。软件被打包成可以由单个或少量程序员开发的各种小的部分:程序库或子系统。子系统被组织成层次化的体系,每层为上一层提供一个严密的、明确定义的接口。
  系统的开发体系结构用模块图和子系统图来表示,在图中可以显示出“导入”和“导出”关系。完整的开发体系结构只有在软件系统的所有元素被识别出来之后才能被描述。控制开发体系结构的原则是:分割、编组、可视。
  开发体系结构主要考虑的是内部需求,这些需求的目的是要使开发相关的活动更易于进行,如软件管理、软件复用、开发工具集所造成的约束、编程语言等。开发体系结构是许多开发活动的基础,包括需求配置、团队组织和工作分配、成本估算和成本规划、项目进度监控、软件可重用性和可移植性分析、软件安全分析等。它是建立软件产品线的基础。
  1.开发视图的符号表示法
  与前面类似,开发视图的符号表示法采用Booch表示法的变体,并且只考虑对于体系结构有重要意义的元素,如图4-22所示。
  Rational公司的Apex Development Environment 支持对开发视图的定义和实现,也支持上面描述的分层策略和对设计规则的执行。在Rational Rose中,可以绘制模块层和子系统层的开发体系结构图,还可以在逆向工程中从已经开发的源代码(Ada或C++)中得出系统的开发体系结构图。

图4-22 开发视图的符号表示法
  2.开发视图的风格
  对于开发视图,我们建议采用分层风格,定义4~6层的子系统。每一层都有明确定义的责任。设计规则是,某一层的子系统只能依赖于本层或其下层的子系统。这样做的目的是使模块间相互依赖而构成的复杂网络最小化,并使得系统可以采用逐层的策略完成释放。
  3.开发视图的例子
  图4-23用5个层次表示了航空交通管制系统产品线的开发组织。此开发体系结构是与图4-19(b)中描述的逻辑体系结构相对应的。
  第1、2层是在软件产品线中常见的分布式系统基础结构。这两层独立于应用域,并将上层系统遮蔽起来,防止其受到硬件平台、操作系统、数据库等变化的影响。在这两层的基础上,第3层增加了一个航空交通管制(ATC)框架,成为一个用于特定应用领域的软件系统结构。使用这一框架,第4层构造了一系列的功能模块。第5层与用户和产品相关,包括大多数的用户界面与外部系统的接口。在这5层中,共分布着72个子系统,每层大约包括10~50个模块。

图4-23 航空交通管制系统的5个层次
4.6.4 物理视图的体系结构:从软件到硬件的映射
  物理体系结构主要考虑的是非功能性的系统需求,如系统的可用性、可靠性(容错性)、性能(信息吞吐量)和可扩展性。软件系统在计算机网络的各个处理节点上运行。各种被确定出的元素——网络、过程、任务和对象——需要映射到各种节点上去,将用到不同的物理配置,有些用于开发和测试,有些用于不同场所或不同用户。因此从软件到处理节点的映射需要高度灵活,并且最小限度地影响其本身的源代码。
  1.物理视图的符号表示法
  图4-24所示为物理视图的符号表示法。大型系统中的物理视图可能非常凌乱。
  TRW公司的UNAS允许使用者采用数据驱动的方式将过程体系结构映射到物理体系结构,并允许在不修改源代码的情况下对这种映射做出多种改动。

图4-24 物理视图的符号表示法
  2.物理视图的例子
  图4-25显示了大型专用自动交换分机的一种可能的硬件配置。


图4-25 专用自动交换分机的物理体系结构
4.6.5 场景视图的体系结构:汇总
  通过使用一些重要场景,4个视图中的元素可以协调地共同工作。尽管这些场景是一个小集合,但是它们很重要。场景是更通用的概念——用例的实例。从某种意义上讲,场景是最重要的需求的抽象。场景的设计使用对象场景图(Object Scenario Diagram)和对象交互图来表示。
  相对于其他的4个视图,场景视图是多余出来的(所以称为“4+1”),但是它承担着两个任务:
  (1) 在下面要讲到的体系结构设计中,将以此视图为驱动来发现体系结构元素。
  (2) 在体系结构设计结束后,此视图承担验证和描述的角色。它不仅用于书面记录,并且是体系结构原型测试的起始点。
  1.场景视图的符号表示法
  场景视图的符号表示法中,构件的表示与逻辑视图非常相似,但是连接件的表示使用过程视图中的方法。注意,对象的实例用细实线表示。在工具的使用方面,和逻辑体系结构类似,可以使用Rational Rose绘制和管理对象场景图。
  2.场景视图的例子
  图4-26显示了用于小型专用自动交换分机的场景的片段。
  (1) 小王的电话控制器检测和验证电话从挂机到摘机状态的转变,并且发送一个消息来唤醒相关的终端对象。
  (2) 终端分配一定的资源,并通知控制器发出拨号音。
  (3) 控制器收到所拨号码并将它们发送给终端。
  (4) 终端使用编号计划分析号码。
  (5) 当一个有效的拨号序列进入时,终端打开一个会话。

图4-26 场景的雏形——本地呼叫选择阶段
  从以上分析可知,逻辑视图和开发视图描述系统的静态结构,而进程视图和物理视图描述系统的动态结构。对于不同的软件系统来说,侧重的角度也有所不同。例如,对于管理信息系统来说,比较侧重于从逻辑视图和开发视图来描述系统,而对于实时控制系统来说,则比较注重于从进程视图和物理视图来描述系统。
   4.7 使用UML描述软件体系结构

4.7.1 UML简介
  1.UML的概念
  UML(Unified Modeling Language)是一种统一建模语言,下面对它进行解释。
  统一:表示是一种通用的标准,它被OMG(Object Management Group)认可,成为软件工业界的一种标准。UML表述的内容能被各类人员所理解,包括客户、领域专家、分析师、设计师、程序员、测试工程师及培训人员等。他们可以通过UML充分理解和表达自己所关注的那部分内容。
  建模:即建立软件系统的模型。为说明建模的价值,Booch给出一个类比:盖一个宠物窝棚、修一个乡间别墅和建一座摩天大楼。建立一个简单的系统,例如盖一个宠物窝棚,模型可有可无;建立一个比较复杂的系统,例如修一个乡间别墅,模型的必要性增大;建立一个高度复杂的系统,例如建一座摩天大楼,模型必不可少。
  语言:表明它是一套按照特定规则和模式组成的符号系统,它用半形式化方法定义,即用图形符号、自然语言和形式语言相结合的方法来描述定义的。
2.UML的发展历史
  公认的面向对象建模语言出现于20世纪70年代中期,到了80年代末发展极为迅速。据统计,1989年到1994年,面向对象建模语言的数量从不到10种增加到50多种。各位语言的创造者极力推崇自己的语言,并不断地发展完善它。但由于各种建模语言所固有的差异和优缺点,使得使用者不知道该选用哪种语言。
  其中比较流行的有Booch、Rumbaugh(OMT)、Jacobsom(OOSE)、Coad-Yourdon等方法。OMT擅长分析,Booch擅长设计,OOSE擅长业务建模。 Rumbaugh于1994年离开GE加入Booch所在的Rational公司,他们一起研究一种统一的方法,一年后,Unified Method 0.8诞生,同年,Rational收购了Jacobson所在的Objectory AB公司。经过三年的共同努力,UML0.9和UML0.91于1996年相继面世。
  此后,UML的创始人Booch等邀请计算机软件工程界的著名人士和著名的企业如IBM、HP、DEC、Microsoft、Oracle等对UML进行评论,提出修改意见。1997年1月,Rational公司向OMG递交了UML1.0标准文本。1997年11月,OMG宣布接受UML,认定为标准的建模语言。UML目前还在不断发展和完善。
4.7.2 UML基本图符
  UML包含了一些图形元素,在进行系统分析和设计时需要这些图。UML通过提供这些图,使得可以通过多个视图从不同角度来描述一个系统。
  1.用例图(Use Case Diagram)
  用例(Use Case)是从用户的观点对系统行为的一个描述。它从用户角度搜集系统需求,这样既可靠又不易遗漏需求。
这里先举一个简单的例子,假设一个人使用洗衣机来洗衣服,用UML用例图来描述洗衣过程如图4-27所示。
  其中,小人表示参与者(Actor),它代表拟建系统外部和系统进行交互的某类人或系统;椭圆代表用例。用例定义一组相关的由系统执行的动作序列。

图4-27 UML用例图
  2.类图(Class Diagram)
  一个类是一组具有类似属性和共同行为的事物。例如,属于洗衣机类的事物都有诸如品牌(Brand Name)、型号(Model Name)、序列号(Serial Number)和容量(Capacity)等属性,它们的行为包括加衣物(Add Clothes)、加洗涤剂(Add Detergent)、取出衣物(Remove Clothes)等操作。
  图4-28是一个用UML表示法表示的洗衣机属性和行为的例子。矩形方框是UML中表示类的图标,它被分为3个区域:最上面是类名,中间是属性,最下面是操作。类图由这些类框和表明类之间关联的连线所组成。

图4-28 UML类图标
  3.对象图(Object Diagram)
  对象是一个类的实例,是具有具体属性和行为的一个具体事物。如洗衣机品牌为海尔或小天鹅,一次最多洗涤重量为5 kg。
  图4-29说明了如何用UML来表示对象。使用UML描述对象时和类图类似,但在对象名下要加下划线,对象名后加冒号加类名。

图4-29 UML对象图标
  4.顺序图(Sequence Diagram)
  类图和对象图表达的是系统的静态结构。在一个运行的系统中,对象之间要发生交互,并且这些交互要经历一定的时间。UML顺序图所表达的正是这种基于时间的动态交互。
  仍以洗衣机为例,洗衣机的构件包括一个注水的进水管(Water Pipe)、一个用来装衣物的洗涤缸(Drum)和一个排水管(Drain)。这些构件也是对象。
  当“洗衣服”这个用例被执行时,假设已完成了“加衣物”、“加洗涤剂”和“开机”操作,那么应执行以下步骤:
(1) 通过进水管向洗涤缸中注水。
(2) 洗涤缸保持静止状态。
(3) 水注满,停止注水。
(4) 洗涤缸往返旋转15分钟。
(5) 通过排水管排掉洗涤后的脏水。
(6) 重新开始注水。
(7) 洗涤缸继续往返旋转洗涤。
(8) 停止向洗衣机中注水。
(9) 通过排水管排掉漂洗衣物的水。
(10) 洗涤缸加快速度单方向旋转5分钟。
(11) 洗涤缸停止旋转,洗衣过程结束。
  图4-30用一个顺序图说明了进水管、洗涤缸和排水管(由顺序图顶端的矩形图标代表)之间随时间变化所经历的交互过程。
  对象符号下方垂直的虚线,称为对象生存线。沿对象生存线上展开的细长矩形称为激活,表示该对象正在执行某个操作,矩形的长度表示执行操作的持续时间。
  带箭头的水平实线表示发送消息,消息可以发往其他对象或自身对象。图中对象之间发送的消息有6个,发往自身的消息有5个。 消息可以是简单的(Simple)、同步的(Synchronous)或异步的(Asynchronous)。消息的图符可以用图4-31来表示。

图4-30 UML顺序图

图4-31 顺序图的消息图符
  5.协作图(Collaboration Diagram)
  系统的工作目标是由系统中各组成元素相互协作完成的,建模语言必须具备这种协作关系的表达方式。UML协作图就是为此目的设计的。图4-32是协作图的一个例子。该图仍以洗衣机为例,在洗衣机构件的类集中又增加了一个内部计时器(Internal Timer)。在经过一段时间后,内部计时器控制进水管停止注水,然后启动洗涤缸往返旋转。图中的序号代表命令消息的发送顺序,内部计时器先向进水管对象发送停止注水消息,后向洗涤缸对象发送往返旋转消息。

图4-32 UML协作图
  6.状态图(Statechart Diagram)
  在任一给定的时刻,一个对象总是处于某一特定的状态。一个人可以是新生儿、婴儿、儿童、少年、青年、中年或老年。一个电梯可以处于上升、下降或停止状态。一台洗衣机可处于浸泡(Soak)、洗涤(Wash)、漂洗(Rinse)、脱水(Spin)或关机(Off)状态。UML状态图如图4-33所示,说明洗衣机可以从一个状态转移到另一个状态。
  状态在图中表述为圆角矩形,有两种比较特殊的状态:初始状态(实心圆点)和结束状态(实心圆点外加一个圆圈)。只能有一个初始状态,可能有多种结束状态。

图4-33 UML状态图
  7.活动图(Activity Diagram)
  活动图类似于流程图,用于描述用例中的事件流结构。图4-34显示了顺序图中步骤4到步骤6之间按顺序的UML活动图。


图4-34 UML活动图
  8.构件图(Component Diagram)
  构件图和下一个要介绍的部署图将不再使用洗衣机作为例子来做说明,因为它们和整个计算机系统密切相关。
  用图4-35来说明如何用UML表示软件构件。构件是软件系统的一个物理单元,例如数据表、可执行文件、动态链接库、文档等。

图4-35 UML构件图
  9.部署图(Deployment Diagram)
  部署图显示了基于计算机系统的物理体系结构。它可以描述计算机和设备,展示它们之间的连接,以及驻留在每台机器中的软件。每台计算机用一个立方体来表示,立方体之间的连线表示这些计算机之间的通信关系。图4-36是部署图的一个例子。

图4-36 UML部署图
  10.其他特征图
  (1) 包(Package)。当需要将图中的组织元素分组,或者在图中说明一些类或构件是某个特定子系统的一部分时,可以将这些元素组织成包。包的表示法如图4-37所示。
  (2) 注释(Note)。注释可以作为图中某部分的解释,其图标是一个带折角的矩形,矩形框中是解释性文字,如图4-38所示。
  (3) 构造型(Stereotype)。构造型可以让用户能使用现有的UML元素来定制新的元素。构造型用双尖括号(Guillemets)括起来的一个名称来表示,如图4-39所示。
  以上3种图都可以用来组织和扩展模型图的特征。

图4-37 包图

图4-38 注释

图4-39 构造型
4.7.3 UML的静态建模机制
  UML的静态建模机制包括用例图、类图、对象图、包、构件图和部署图。
  1.用例图
  (1) 用例模型(Use Case Model)描述的是外部角色(Actor)所理解的系统功能。 用例模型适用于需求分析阶段,它是经过系统开发者和用户反复讨论后而建立的,说明了开发者和用户对系统功能和需求规格达成的共识。
  用例模型描述了待开发系统的功能需求,它将系统看作黑盒,从系统的外部用户角度出发,对系统进行抽象表示。用例模型驱动了需求分析之后各阶段的开发工作,不仅在开发过程中保证了系统所有功能的实现,而且被用于测试系统是否满足用户的需求和验证系统的有效性,从而影响到开发工作的各个阶段和UML的各个模型。用例视图是其他视图的核心和基础,其他视图依靠用例视图中所描述的内容来构造。
  用例模型基本组成包括:用例、角色和系统。用例用于描述系统的功能,即从外部用户的角度观察系统应该支持的功能。用例宏观描述了系统功能,帮助分析人员理解系统的行为。每个系统中的用例都具体说明系统所具有的基本功能。角色是与系统进行交互的外部实体,可以是系统用户,也可以是与系统交互的任何其他系统或硬件设备。系统边界线以内的区域(即用例的活动区域)抽象表示系统能够实现的基本功能。
  用例模型可以由若干个用例图组成。用例图用于显示若干角色以及这些角色与系统提供的用例之间的连接关系。通常一个实际的用例采用普通的文字描述,作为用例符号的文档性质。当然,实际的用例图也可以用活动图描述。用例图仅仅从角色使用系统的角度描述系统中的信息,也就是站在系统外部查看系统功能,它并不描述系统内部对该功能的具体操作方式。
  (2) 用例(Use Case)。用例的表示法见图4-27。从本质上讲,一个用例是用户与计算机之间的一次典型交互作用。在UML中,用例被定义成系统执行的一系列动作,动作执行的结果能被指定角色察觉到。
  用例的特点如下:
  ● 用例捕获某些用户可见的需求,实现一个具体的用户目标。
  ● 用例由角色激活,并提供确切的值给角色。
  ● 用例可大可小,但它必须是对一个具体的用户目标实现的完整描述。
  (3) 角色(Actor)。角色是与系统交互的人或事。所谓与系统交互,指的是角色向系统发送消息,从系统中接收消息,或是在系统中交换信息。只要使用用例,与系统互相交流的任何人或事都是角色。
  角色是一个群体概念,表示一类能使用某个功能的人或事,并不是指某个个体。一个具体的个体在系统中可以具有多种不同的角色。角色都有名字,它的名字反映了该角色的身份和行为,但是不能将角色的名字表示成角色的某个实例,或表示成角色所需完成的功能。
  角色与系统进行通信的收、发消息机制,类似于面向对象编程中的消息机制。角色是启动用例的前提条件。首先,角色发送消息给用例,当初始化用例后,用例再开始执行,在执行过程中该用例也可能向一个或多个角色发送消息。
  (4) 用例之间的关系,包括扩展和使用等关系。
  ① 扩展关系。如果一个用例中加入一些新的动作后构成另一个用例,那么这两个用例之间的关系就是扩展关系。后者通过集成前者的一些行为得来。前者通常称为通用化用例,后者常称为扩展用例。扩展用例可以根据需要有选择地集成通用化用例的部分行为。
  ② 使用关系。一个用例使用另一个用例时,这两个用例之间就构成了使用关系。通常,可以把用例中相同的行为提取出来单独做成一个用例,这个用例称为抽象用例。当某个用例使用该抽象用例时,就像这个用例包含了抽象用例的所有行为。
  2.类图、对象图和包
  (1) 类图。在面向对象建模技术中,将客观世界的实体映射为对象,并归纳成类。类、对象和它们之间的关联是面向对象技术中最基本的元素。系统的类模型和对象模型描述了系统的结构。在UML中,类和对象模型分别由类图和对象图表示。
  类图表示类和类之间的静态关系。不同于数据模型,它不仅显示了信息的结构,同时还描述了系统的行为。类图是定义其他图的基础,状态图、协作图等在这个基础上进一步描述了系统其他方面的特性。
  类图是一种用类和它们之间的关系描述系统的图示。通常,类用长方形表示,分为上、中、下3个区域,如图4-28所示。上面的区域内标识类的名字,中间的区域内标识类的属性,下面的区域内标识类的操作(行为),这3部分作为一个整体描述某个类。如果要描述有关约定规则,就有了额外的分栏。如果类图中存在多个类时,类与类之间的关系可以用表示某种关系的连线将它们连接起来。类图的另一种表示方法是用类的具体对象代替类,这种表示方法称作对象图。
  类图必须含有公有属性或私有属性。公有属性用加号(+)表示,私有属性用减号(-)表示,在属性名称的左侧标识它们。当属性名称旁没有标识任何符号时,则表示该属性的可见性尚未定义。类图可以指定属性的默认值,这样当创建该类的对象时,对象的属性值便自动被赋以该默认值。
  UML规定类的属性的语法格式为:
   可见性 属性名:类型 = 默认值 {性质串}
其中,属性名和类型是必需的。性质串列出该属性所有可能的取值,是用户对该属性性质的约束说明,例如“{只读}”说明该属性是只读属性。
  类图描述了类和类之间的静态关系。在定义类之后,就可以定义类之间的各种关系。
  (2) 关系。类之间的关系通常有关联、泛化(继承)、依赖等。
  关联关系:关联用于描述类与类之间的连接。因为对象是类的实例,所以类与类之间的关联也就是其对象之间的关联。虽然类与类之间有含义各不相同的多种连接方式,但外部表示形式相似,统称为关联。关联关系通常都是双向的,即关联的对象双方彼此都能与对方通信。也就是,当某两个类的对象之间存在要互相通信的关系时,这两个类之间就存在关联关系。
  泛化关系:又称继承关系,是指一个类(称为一般元素、基类元素或父元素)的所有信息(属性和操作)能被另一个类(称为特殊元素或子元素)继承。继承某个类的类中不仅可以有属于自己的信息,而且还拥有被继承类中的信息。泛化的优点是通过把一般的公共信息放在基类元素中,使得在处理具体情况时只需定义该情况的特殊信息即可,公共信息则从通用元素中继承得来,从而增强了系统的灵活性、易维护性和可扩充性,大大缩短了系统的维护时间。
  具有泛化关系的两个类之间,继承通用类所有信息的具体类称为子类,被继承类称为父类。可以从父类中继承的信息有属性、操作和所有的关联关系。
  (3) 对象图。类图表示类以及类和类之间的关系,对象图则表示在某一时刻这些类的实例之间的具体关系。由于对象是类的实例,因此,UML对象图中的概念与类图中的概念完全一致,对象图可以帮助理解一个比较复杂的类图,也可以用于显示类图中的对象在某一点的连接关系。
  对象的图示方法与类的图示方法几乎一样,主要差别在于对象的名字下面要加下划线(见图4-29)。
  (4) 包。包是一种组合机制,把各种模型元素通过内在的语义连在一起成为一个整体,形成一个高内聚、低耦合的集合,UML中将这种分组机制称为包。构成包的模型元素称为包的内容。包通常用于对模型的组织管理,因此有时又将包称为子系统。
  模型元素的分组方法可以是任意的。在UML中,最有用和强调最多的分组原则是依赖。包图主要显示模型元素的包以及这些包之间的依赖关系,有时还显示包和包之间的继承关系和组成关系。
  3.构件图和部署图
  构件图和部署图显示系统实现的一些特性,包括源代码的静态结构和运行时刻的实现结构。构件图显示代码本身的结构,部署图显示系统运行时刻的结构。
  (1) 构件图。构件图的表示法如图4-35所示。构件图显示系统构件之间的依赖关系,如图4-40所示。一般来说,系统构件就是一个实际文件,可以是源代码文件、二进制代码和可执行文件等,可以用来显示编译、链接或执行时构件之间的依赖关系。

图4-40 构件图
  (2) 部署图。部署图描述系统硬件的物理拓扑结构以及在此结构上执行的系统。部署图可以显示计算节点的拓扑结构和通信路径、节点上运行的系统构件、系统构件包含的逻辑单元(对象、类)等。部署图常常用于帮助理解分布式系统。
  ① 节点和连接。节点代表一个物理设备以及其上运行的系统。节点表示为一个立方体,节点名放在左上角。与类和对象一样,节点可以用于表示类型和实例。当用该符号表示实例时,需要名字下面有一条下划线。节点之间的连线表示系统之间进行交互的通信路径,称为连接。通信类型放在连接旁边的<< >>之间,表示所用的通信协议或网络类型。
  ② 构件和界面。在部署图中,构件代表可执行的物理代码模块,它在逻辑上与类图中的包或类对应。因此,部署图中显示运行时各个包或类在节点中的分布情况。在面向对象方法中,类和构件等元素并不是所有的属性和操作都对外可见。它们对外提供了可见操作和属性,称为类和构件的界面。界面表示为一头是小圆圈的直线。
  ③ 对象。一个面向对象系统中可以运行很多对象。因为构件可以看做与包或类对应的物理代码模块,所以构件中应包含一些运行的对象。如图4-36所示的部署图中的对象与对象图中的对象表示法一致。
4.7.4 UML的动态建模机制
  在面向对象技术中,对象间的交互是通过在对象间传递消息完成的。在UML的所有动态图(顺序图、协作图、状态图、活动图)中,消息被当作对象间的一种通信表示方式。一般情况下,当一个对象调用另一个对象中的操作时,即完成了一次消息传递。当操作执行后,控制便返回到调用者。对象通过相互间的通信(消息传递)进行合作,并在其生命周期中根据通信的结果不断改变自身的状态。
  在UML中,消息的图形表示是用带有箭头的线段将消息发送者和接收者联系起来,箭头的类型表示消息的类型,如图4-30和图4-31所示。
  简单消息(Simple Message):表示普通的控制流。它描述控制是如何在对象间进行传递的,不考虑通信的具体细节。这种消息类型主要用于通信细节未知或不需要考虑通信细节的场合。
  同步消息(Synchronous Message):表示嵌套的控制流。操作的调用便是一种典型的同步消息。调用者发出消息后必须等待消息返回,只有当处理消息的操作执行完毕后,调用者才可继续执行自己的操作。
  异步消息(Asynchronous Message):表示异步控制流。调用者发出消息后不用等待消息的返回即可继续执行自己的操作。异步消息在实时系统中常用来描述其中的并发行为。
  1.顺序图
  顺序图用来描述对象间的动态交互关系,侧重体现对象间消息传递的时间顺序。顺序图用横坐标轴表示对象,用纵坐标轴表示时间。顺序图横坐标轴上的对象用一个带有垂直虚线的矩形框表示,矩形框中写有对象名和/或类名。垂直虚线是对象的生命线,用于表示在某段时间内对象是否存在。对象间的通信用对象的生命线之间的水平消息线来表示。消息的箭头表示消息的类型,如同步消息、异步消息或简单消息。
  如果收到消息,那么对象就立即开始执行活动,即对象被激活了。激活用对象生命线上的细长矩形框表示。消息可以用消息名称和参数来表示。消息可带有条件表达式,用以表示分支或决定是否发送消息。当条件表达式用于表示分支时,分支是互斥的,也就是说一次只能发送分支中的一个消息。
  顺序图的左边可以有注释,用以说明消息发送的时刻、描述动作的执行情况以及约束信息等,如图4-30所示。
  2.协作图
  协作图用于描述相互合作的对象间的交互和链接关系(链接是关联的实例化)。尽管顺序图和协作图都用来描述对象间的交互关系,但侧重点并不一样。顺序图强调交互的时间顺序,而协作图则强调交互对象间的静态链接关系。
  协作图表示对象与对象间的链接以及链接间如何发送消息。协作图中对象的外观与顺序图中的一样。对象间链接的表示方法类似于类图中的关联。通过链接上标以用消息串表示的消息(简单、异步或同步消息)来表达对象间的消息传递。
  (1) 链接。链接用于表示对象间的各种关系,协作图中的各种链接关系与类图中的定义相同,在链接的断点位置可以显示对象的角色名和模板信息。
  (2) 消息流。在协作图的链接线上,可通过用消息串表示的消息来描述对象间的交互,如图4-32所示。消息的箭头指明消息的流动方向。消息串中包含了发送的消息、消息的参数、消息的返回值以及消息的序列号等信息。
  (3) 对象的生命周期。如果一个对象在消息的交互中被创建,则可在对象名称之后标以{new}。类似地,如果一个对象在交互期间被删除,则可在对象名称之后标以{destroy}。
  3.状态图
  状态图描述一个特定对象的所有可能状态以及引起状态转移的事件。状态图由一系列状态和状态之间的转移构成,通过状态图可以表示单个对象在其生命周期中的行为。
  (1) 状态。每个对象都具有状态,状态是对象执行某个活动的结果。当发生某些事情后,结果将引起对象的状态的变化。通常将这些引起对象状态变化的事情称为“事件”。状态图可以有一个起点(初态)和多个终点(终态)。状态图的起点用一个黑圆点来表示,终点用黑圆点外加一个圆表示,状态用一个圆角矩形表示。
  一个状态可以进一步细化为多个子状态,进一步细化的状态称作复合状态。子状态又可分为两种:“或子状态”和“与子状态”。或子状态指在某一时刻仅可到达一个子状态,与子状态指在某一时刻可同时到达多个子状态(称为并发子状态)。具有并发子状态的状态图称为并发状态图。
  (2) 转移。状态图中用状态间带箭头的连线来表示状态的转移。状态的变化通常由事件触发,此时应在状态转移线上标出触发转移的事件表达式。如果状态转移线上未标明事件,则表示在源状态的内部活动执行完毕后自动触发转移,如图4-33所示。
  一般情况,状态图是对类图的补充。实际上,并不需要为所有的类画状态图,仅需要为那些有多个状态且其行为受外界环境的影响而发生改变的类画状态图。
  4.活动图
  活动图可以描述操作(类的方法)中完成的工作,也可以描述用例和对象内部的工作过程。活动图由状态图变化而来,但它们的目的有所不同。活动图的主要目的是描述动作(将要执行的工作或活动)以及对象状态变化的结果。在活动图中,当一个活动结束后将立即进入下一个活动。但在状态图中,状态的变迁可能需要由事件触发。
  (1) 活动和转移。一项操作可以用一系列相关的活动来描述。活动只有一个起始点,但结束点可以有多个。一个活动可以顺序地跟在另一个活动之后,这是简单的顺序关系。如果在活动图中使用一个菱形的判断标志,则表达条件关系,判断标志可以有多个输入和输出转移,但在活动的运作中只触发其中的一个输出转移。
  活动图也可以表示并发行为。在活动图中,使用一个称为同步条的水平粗线可以将一条转移分为多个并发执行的分支,或将多个转移合为一条转移。此时,只有当输入的转移全部有效,同步条才会触发转移,进而执行后面的活动。
  (2) 泳道。泳道用纵向矩形框表示,放在该矩形框内均属于某个泳道的所有活动;将对象和名称放在矩形框的顶部,表示该对象对泳道中的活动负责。所以,通过泳道可以将活动图的逻辑描述与顺序图、协作图的责任描述结合起来。
  (3) 对象。在活动图中可以出现对象。对象可以作为活动的输入或输出,也可以仅表示某一活动对对象的影响。如果对象是一个活动的输入,那么用一个从对象指向活动的虚线箭头表示;如果对象是一个活动的输出,那么用一个从活动指向对象的虚线箭头表示;如果仅表示对象受到某一活动的影响,则可用不带箭头的虚线来连接对象与活动。
  (4) 信号。在活动图中可以表示信号的发送与接收,分别用发送符号和接收符号表示。发送符号和接收符号也可与消息的发送对象和消息的接收对象相连。
4.7.5 UML在软件体系结构建模中的应用实例
  下面以浏览器/服务器的软件体系结构为例子,用UML的建模机制对简单的B/S体系结构进行建模,并说明该结构的构件交互及其交互模式的重用技术。
  1.用UML对构件交互模式进行静态建模
  前面已经介绍UML的静态建模机制包括用例图、类图、对象图、包、构件图和部署图。在本节主要通过用例图和部署图两种图来对B/S体系结构进行静态建模。
  经过对B/S风格的软件体系结构的分析可知,用户通过浏览器与服务器端的交互用UML的部署图来表示,如图4-41所示。
  浏览器是运行在客户端的应用程序,与网络上的服务器连接并请求获取信息页。当请求被满足,即浏览器得到所请求的信息页,连接就终止。浏览器指导怎样通过HTTP与Web服务器通信,以及怎样显示由Web服务器返回的格式化的信息(即以网页的形式返回)。

图4-41 浏览器与服务器交互的部署图
  服务器端的Web服务器接收网页(静态的HTML或服务器页)的请求,根据请求,Web服务器可能启动某个服务器端的处理(例如向数据库服务器发出SQL查询,然后将查询结果返回),再将得到的信息以网页(如HTML格式的网页)的形式返回,在客户端的浏览器中显示出来。
  在B/S体系结构中,有各种构件和连接件。构件分为形成客户浏览器和服务器端的构件,服务器端构件包括Web服务器端和数据库服务器构件。
  构件在这里可以看做是进行一定运算或其他操作的体系结构的实体,而连接件是用于提供构件间交互的体系结构实体。通过构件和连接件加上由构件之间形成的交互,就形成了一个完整的体系结构。其中,构件间的信息交互有同步和异步两种;而内部构件的通信分为同步、异步、代理和组通信等。连接件不但表示一个简单的交互操作(例如过程调用、共享变量的使用),而且还表示复杂的交互(例如TCP/IP协议、数据库使用协议、异步事件列表、网络安全协议等)。
  用UML的静态建模机制与扩展机制的构造型对构件间交互进行静态建模,如图4-42所示,其中<<构件>>、<<资源>>和<<连接件>>是构造型的。

图4-42 浏览器/服务器类图
  构件用来描述终端客户的浏览器类和用于建立数据库连接并负责数据库存储和检索,响应请求数据查询、处理的服务器类。
  资源代表支持构件与连接件的通信,而Internet就是一种资源,使得浏览器的连接件可以通过网络与服务器建立连接。
  连接件可以表示简单的交互,也可以表示复杂的交互,它隐藏构件间的内部交互细节(例如同步或异步信息的传递)。从图4-42中描述可知,每一个服务器构件与浏览器端构件间是一对多关系,浏览器与浏览器连接件和服务器与服务器连接件都是一对一的关系,而网络资源与浏览器连接件、服务器连接件都是一对多的关系。
  在B/S体系结构中,还可对连接件进一步细化为浏览器连接件和异步客户连接件。浏览器连接件也就是客户连接件,可以分为同步客户连接件和异步客户连接件。异步客户连接件是一个组合类,它由客户消息输入缓存类、客户请求端类和客户返回端类构成。用UML的类图表示如图4-43所示。
  服务器连接件可以分为单线程和多线程服务器连接件。用UML类图表示如图4-44所示。

图4-43 客户连接件类图

图4-44 服务器连接件类图
  2.用UML对构件交互模式进行动态建模
  如前面所讲,UML中动态图有顺序图、协作图、状态图、活动图。在本节中,主要利用协作图对B/S体系结构的构件之间的交互进行建模。
  图4-45中显示了客户端浏览器与服务器端的构件的动态交互的协作图。
  首先,用户通过浏览器向浏览器连接件发出消息请求,浏览器连接件将请求进行打包形成消息包(消息包中包含相应的服务参数),再通过网络资源(例如传输协议软件)将消息包发给服务器连接件,服务器连接件接收器将消息包进行检查,如果无错,就将它提交给服务器,服务器根据请求包中的请求完成相应的处理或服务,并将服务结果装配成一个响应包,再沿原路返回到浏览器端(中间服务器连接与浏览器连接件都将消息包进行处理),最后提交给用户。
  前面已经提出,浏览器连接件有同步与异步之分,那么它们如何请求与接收信息的程序?请参见图4-46与图4-47。

图4-45 浏览器与服务器的协作图

图4-46 浏览器/服务器的单线程的同步消息通信协作图

图4-47 浏览器/服务器的多线程服务器连接件的通信协作图
  图4-46描述了简单的浏览器/服务器的同步消息通信的协作图。同步客户构件通过静态绑定与一个单线程服务器构件通信。同步客户构件与一个同步客户连接件相连,单线程服务器构件与一个单线程服务器连接,其中客户连接件与单线程服务器里面都封装着与服务器交互的细节。同步客户连接件主要是整理打包消息后把消息包送给服务器连接件,同时也接收来自服务器的响应消息包,并解包后发给客户浏览器。
  如果是多线程服务器端则比较复杂些,由于多线程服务器连接件与多线程服务器都是一个复杂的构件。客户可以静态或动态地绑定与它同步或异步的通信。当服务器连接件接收到消息包后就存入消息缓存中,然后由服务器端接收消息包(可以是单线程也可以是多线程)。
  如果服务器是单线程,就将消息送给单线程服务器构件并等待响应;如果服务器端是多线程,就把消息放入分配器缓存中,再继续处理下一个消息包。当分配器接收到来自缓存的消息后,就逐步地将消息队列分配给空闲的服务器;服务器处理完毕,再打包形成消息响应包,按原路发送回给客户,详细情况请见图4-47。
  在图4-46中,当同步客户变成异步客户时,同步客户连接件也相应地变成异步客户连接件。它的通信复杂得多,就如同多线程通信比单线程通信复杂一样。主要的不同点是:异步客户连接件在接收响应前还可以处理其他请求。异步客户连接件采用了并行端,客户请求端用来处理输出消息,客户返回端处理输入的响应,响应处理完后存入客户消息输入缓存,供异步客户构件读取。其通信协作图如图4-48所示。

图4-48 异步客户连接件的通信协作图

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2019-09-12 23:08  Zander_Zhao  阅读(997)  评论(0编辑  收藏  举报