UML(统一建模语言)一出现,以融合了多种面向对象建模方法,简洁的图形与符号,直观的表示和强大的表示能力,得到工业界与学术界认可。它通过统一的表示法,使不同知识背景的领域专家、系统分析和开发人员以及用户可以方便地交流。
UML 成了实际上的工业标准。1996 年,一个由建模专家组成的国际性队伍"UML伙伴组织"开始同"三友"一起工作,计划将 UML提议作为 OMG(Object Management Group)的标准建模语言。最终草案,并于 1999年 6 月提交了一份最终报告。被推荐的规范随后被提交给组织委员会和平台技术委员会以获得批准。
元模型的体系结构模式已被证明可以用来定义复杂模型所要求的精确语义,这种复杂模型通常需要被可靠地保存、共享、操作以及在工具之间进行交换。它的特点如下∶
在元模型层,UML 元模型又被分解为三个逻辑子包;基础包、行为元素包和模型管理包。
UML1.3 解决UML1.1的遗留问题
UML 是在多种面向对象建模方法的基础上发展起来的建模语言,主要用于软件密集型系统的建模。总的来说目前的UML语言是一个庞大且一直在发展壮大的标准建模语言,能够在许许多多不同的领域提供各种不同的建模能力,当然UML目前也是存在一系列的缺点的,概括起来为:
UML 通过图形化的表示机制从多个侧面对系统的分析和设计模型进行刻画。它共定义了10种视图,并将其分为以下4类:
用例有两个比较具有代表性的定义:
用例分析可以支持领域建模(domaim modeling),以确保定义正确的需求(right requirements),是保证OO(面向对象)软件开发成功的基础。本质上,用例分析是一种功能分解(functional decomposition)的技术,并未使用到面向对象的思想。但用例是 UML 的重要部分,确定一个系统的用例是开发 OO 系统的第一步,用例分析这步做得好,接着的交互图分析、类图分析等才有可能做得好,整个系统的开发才能顺利进行。编写用例的人必须识别以下的元素:
参与者
角色(actor)是指系统以外的、需要使用系统或与系统交互的东西,包括人、设备、外部系统等。actor有很多不同的译名,包括参与者、活动者、执行者和行动者等。
用例除了与参与者有关联(association)关系外,用例之间也存在着一定的关系(relationship),如泛化(generalization)关系、包含(include)关系、扩展(extend)关系等。
用例图(use case diagram)是显示一组用例、参与者以及它们之间关系的图。在 UML中,一个用例模型由若干个用例图描述。如图所示,是一个电话系统使用的用例图:
用例的描述才是用例的核心部分,用例采用自然语言插述参与者与系统进行交互时双方的行为,不追求形式化的语青表达。以下是一种典型的描述的方式。
交互图{interaction diagram)是用来描述对象之间以及对象与参与者(actor)之间的动态协作关系以及协作过程中行为次序的图形文档。它通常用来描述一个用例的行为,显示该用例中所涉及的对象和这些对象之间的消息传递。交互图包括顺序图〈sequencediagram)和协作图(collaboration diagram)两种形式:
顺序图
顺序图也称时序图。Rumbaugh 对顺序图的定义是∶顺序图是显示对象之间交互的图,这些对象是按时间顺序排列的。特别地,顺序图中显示的是参与交互的对象及对象之间消息交互的顺序。
协作图是用于描述系统的行为是如何由系统的成分协作实现的图,协作图中包括的建模元素有对象〔包括参与者实例、多对象、主动对象等)、消息,链等。
关联关系
关联(association)是模型元囊间的一种语义联系,它是对具有共同的结构特性、行为特性、关系和语义的链(ink) 的描述。通过关联类(association clas)可以进一步描述关联的属性、操作以及其他信息。关联类通过一条虚线与关联连接。如图
所示Contract 类是一个关联类,Contract 类中有属性 salary,这个属性描述的是 Corpany 类和Person 类之间的关联的属性,而不是描述Company 类或 Person类的属性。
自返关联(reflexive association)又称递归关联(recursive Engnepert association),是一个类与自身的关联,即同一个类的两个对象间的关系。
聚集和组合
聚集(aggregation)是一种特殊形式的关联。聚集表示类之间整体与部分的关系,在对系统进行分析和设计的时候,需求中描述的“包含”、“组成”、“分为……部分”等词语都意味着存在聚集关系。
组合(composition)表示的也是类之间的整体与部分的关系,但组合关系中的整体与部分具有同样的生存期。也就是说,组合是一种特殊形式的聚集。
泛化关系
泛化(generalization)定义了一般和特殊元素之间关系,如果从面向对象程序设计语言的角度来说,类与类之间的泛化关系就是平常所说的类与类之间的继承关系。
UML中用一头为空心三角形的连接线表示泛化关系。
依赖关系
假设有两个元素 X、Y,如果修改元素 X 的定义可能会导致对另一个元素 Y 的定义的修改,则称元素 Y 依赖于元素 X。
类图
类图以直观、抽象形式展示了不同对象之间关系。例如下面的学校关系的类图的案例:
UML 中的状态图(state chart diagram)主要用于描述一个对象在其生存期间的动态行为,表现一个对象所经历的状态序列,引起状态转移的事件(event),以及因状态转移而伴随的动作(action)。。状态图是 UML 中对系统的动态行为建模的5个图之一,状态图在检查、调试和描述类的动态行为时非常有用。一般可以用状态机对一个对象的生命周期建模,状态圈是用予显示状态机的,重点在于描述状念之间的控制流。下面是一个简单的状态图的切换过程的例子:
活动图是对系统的动态行为建模的 5 个图之一。活动图可以用于描述系统的工作流程和并发行为。活动图其实可看作状态图的特殊形式,活动图中一个活动结束后将立即进入下一个活动(在状态图中状态的转移河能需要事件的触发)。下面是一些关于活动图中的一些基本概念的描述和介绍:有活动、泳道、分支、分叉和汇合、对象流。
活动
活动(activity)表示的是某流程中的任务的执行,它可以表示某算法过程中语句的执行。在活动图中需要注意区分动作状态(action stat)和活动状态(activity state)这两个概念。动作状态是原子的,不能被分解,没有内部转移,没有内部活动,动作状态的工作所占用的时间是可忽略的。动作状态的目的是执行进入动作(enty action),然后转向另一个状态。活动状态是可分解的,不是原子的,其工作的完成需要一定的时间。可以把动作状态看作活动状态的特例。
泳道
泳道(swimlane)是活动图中的区域划分,根据每个活动的职责对所有活动进行划分,每个泳道代表一个贵任区。泳道和类并不是——对应的关系,泳道关心的是其所代表的职责,一个泳道可能由一个类实现,也可能由多个类实现。
分支
在活动图中,对于同一个触发事件,可以根据不同的警戒条件转向不同的活动,每个可能的转移是一个分支(branch)。
分叉和汇合
分支表示的是从多种可能的活动转移中选择一个,如果要表示系统或对象中的并发行为,则可以使用分叉(fork)和汇合(jom)这两种建模元囊。分叉表示两个或多个控制流经过分叉后,这些控制流并发进行;汇含正好与分叉相反。
对象流
在活动图中可以出现对象。对象可以作为活动的输入或输出。活动圈中的对象流表示活动和对象之间的关系,如一个活动创建对象〈作为活动的输出)或使用对象(作为活动的输入)等。
构件(componcnt)是系统中遵从一组接口且提供其实现的物理的、可替换的部分。构件图(componentdiagram)则显示一组构件以及它们之间的相互关系,包括编译、链接或执行时构件之间的依赖关系。下图是一个构件图的例子,表示.html文件、.exe文件、.dll文件这些构件之间的关系。
构件图可以从以下几个方面进行建模:
部署图也称为配置图、实施图,它可以用来显示系统中计算节点的拓扑结构和通信路径与节点上运行的软件构件等。一个系统只有一个部署图,部署图通常用于帮助理解分布式系统。下图是一个部署图的例子:
UML是独立于软件开发过程的,即 UML 能够在几乎任何一种软件开发过程中使用。迭代的渐进式软件开发过程包含 4 个阶段,即初启、细化、构建和部署。
初启
在初启阶段,软件项目的发起人确定项目的主要目标和范围,并进行初步的可行性分析和经济效益分析。
细化
细化阶段的开始标志着项目的正式确立。软件项目组在此阶段需要完成以下工作∶
综上所述,在细化阶段可能需要使用的 UML 语言机制包括描述用户需求的用例及用例图、表示领域概念模型的类图、表示业务流程处理的活动图、表示系统高层结构的包图和表示用例内部实现过程的交互图。
构建
在实际开始构造软件系统之前,有必要预先制定迭代计划。计划的制定需遵循如下两项原则∶
在迭代计划中,要确定迭代次数、每次迭代所需时间以及每次迭代中应完成(或部分完成)的用例。每次迭代过程由针对用例的分析、设计、编码、测试和集成5个子阶段构成。在集成之后,用户可以对用例的实现效果进行评价,并提出修改意见。
综上所述,在构建阶段可能需要使用的 UML 语言机制包括∶
部署
在部署阶段,开发入员将构造阶段获得的软件系统在用户实际工作环境(或接近实际的模拟环境)中试运行,根据用户的修改意见进行少量调整。
在初步的业务需求描述已经形成的前提下,基于UML 的需求分析过程大致可分为以下步骤:
生成用例
从外部用户的视角看,一个用例是执行者(actor)与目标软件系统之间的一次典型的交互作用。从软件系统内部的视角出发,一个用例代表系统执行的一系列动作,动作执行的结果能够被外部的执行者所察觉。例如我们可以参考如下的用例:
针对前面所述的"传感器监测"用例,其活动图表示如图所示。
生成用例图
执行者与用例之间的关系有两种∶触发执行与信息交换。执行者与用例之间可能兼具这两种关系。在 UML 用例图中,从执行者指向用例的边表示触发执行和/ 或信息交换,从用例指向执行者的边则表示用例将其生成的信息传递给执行者。
建立顶层架构
顶层架构的主要目的是为后续的分析和设计活动建立一种结构和分划,以便开发人员在不同的开发阶段,以及同一开发阶段的不同开发人员,能够聚焦于系统的不同部分。
UML包图
包是 UML 对类进行分组的一种机制。可以从某种视角将具有比较密切的关联的一些类划分为一个包,分属于不同包的两个类之间的关联则比较松散。由此可见,对于大型软件系统而言,包的划分是实现"分而治之"的重要技术手段。包之间存在两种依赖关系:依赖和构成。包之间存在两种依赖关系∶依赖和构成。如果对类 A 的修改将导致类 B 的改变,则称B依赖于A。如果两个包中存在具有依赖关系的两个类,则认为这两个类分属的包之间存在依赖关系。
顶层架构设计
软件系统顶层架构的基本方法是,结合实际需求,从既往的架构设计经验模式中选取适当者,再进行微调或局部改造。目前有如下几种主要的架构模式:
事实上,大型软件的顶层架构往往需要符合使用多种架构样式,在确立顶层架构的过程中需要综合考虑一下因素:
建立概念模型
“家庭保安系统”的概念模型如下图所示:
面向对象的软件设计过程如图所示:
UML 的交互图(顺序图、协作图)适于用例实现方案的表示。该设计方法包含如下三个步骤:
边界类用于描述目标软件系统与外部环境之间的交互,并负责实现如下的功能:
在 UML 类图中,边界类往往附加 UAL 构造型<< boumdary >>作为特别标识。
UML 交互图,以交互图作为用例的精确实现方案。对于比较复杂的用例而言,仅仅依靠控制类、边界类和实体类并不能很好地解决问题,因为我们不能使单个控制类过于庞大和复杂,让它既承担控制、协调的任务,又承担复杂的计算任务。因此,在设计复杂用例的实施方案时,应考虑为控制类设置一些独立的辅助类,让控制类将一些任务委托给辅助类完成。那么,典型布局规则下的顺序图如图所示:
在 UM 交互图中,对每个类的对象都规定了它必须响应的消息以及类的对象之间的消息传递通道。前者对应于类的操作,后者则对应于类之间的连接关系。因此,可以利用交互图精化分析模型中的类图,将交互图中出现的新类添加到原有类图中,并日对相关的类进行精化,定义其属性和操作。
设计技术支撑方案
在许多软件项目中,应用功能往往都需要一组技术支撑机制为其提供服务。技术支撑方案应该为多个用例的软件实现提供技术服务,所以,它应该成为整个目标软件系统中全局性的公共技术平台。当用户需求发生变化时,技术支撑方案应具有良好的稳定性。这就要求软件设计者选用开放性和可扩充性较好的技术支撑方案。如果目标款件系统的顶层架构采用分层方式,那么技术支撑方案应该位于层次结构中的较低层次。技术支撑方案的设计一方面取决于目标软件系练对公共技术服务的需求。另一方面取决于设计人员对软件技术手段的把握和选取。
设计用户界面
用户界面设计的策略与步骤如下∶
利用快速原型演示,改进界面设计。为人机交互部分构造原型,是界面设计的基本技术之一。为用户演示界面原型,让他们直观感受目标软件系统的使用方法,并评判系统是否功能齐全、方便好用。
精细化设计模型
对模型进行改进的活动可以分为精化和合并两种,一般先从精化开始。首先,由干初始架构模型已经包括了总原则和层结构两部分的内容。现在要做的工作是根据需求和架构原则来划分不同的粗粒度组件。粗粒度组件来源于分析活动中的业务实体。把具有很强相关性业务实体组合起来,形成一个集合。集合内部存在错综复杂的关系,同时集合向外部提供服务接口。这样的集合就称为粗粒度组件。粗粒度组件对外的接口和内部的实现是相区分的。
在得到了粗粒度组件模型之后,我们需要对其进行进一步的分析,以得到细粒度的组件。细粒度的组件具有更好的重用性,并使得架构设计的精化工作更进一步。按Jacobgon推荐的面向对象软件工程(Object Oriented Software Enginerring,OOSE)的做法,我们需要从软件的目标领域中识别出关键性的实体,或者说是领域中的名词。
软件架构用来处理软件高层次结构的设计和实施。它以精心选择的形式将若干结构元素进行装配,从而满足系统主要功能和性能需求,并满足其他非功能性需求,如可靠性、可伸缩性、可移植性和可用性。Perry 和 Wolfe 使用一个精确的公式来衰达,该公式由 Boehm 做了进一步修改。
软 件 架 构 = 元 素 , 形 式 , 关 系 / 约 束 软件架构={元素,形式,关系/约束} 软件架构=元素,形式,关系/约束
软件架构涉及到抽象、分解和组合、风格和美学。我们用由多个视图或视角组成的模型来描述它。为了最终处理大型的、富有挑战性的架构,该模型包含 5个主要的视图如图所示:
架构的描述,即所做的各种决定,可以围绕着这 4个视图来组织,然后由一些用例(use cases)或场景(scenarios)来说明,从而形成了第 5个视图。正如将看到的,实际上软件架构部分从这些场景演进而来。
逻辑架构主要支持功能性需求,那在为用户提供服务方面系统所应该提供的功能。系统分解为一系列的关键抽象,(大多数)来自于问题域,表现为对象或对象类的形式。它们采用抽象、封装和继承的原理。分解并不仅仅是为了功能分析,而且用来识别遍布系统各个部分的通用机制和设计元囊。我们使用 Ratiomal/ooch 方法来表示逻辑架构,借助于类图和类模板的手段。类图用来显示一个类的集合和它们的逻辑关系,关联、使用、组合、继承等。相似的类可以划分成类集合,基本的逻辑蓝图表示法如图所示。
逻辑视图的风格采用面向对象的风格,其主要的设计准则是试图在整个系统中保持单一的、一致的对象模型,避免就每个场合或过程产生草率的类和机制的技术说明。
逻辑结构蓝图的样例
进程架构考虑一些非功能性的需求,如性能和可用性。它解决并发性、分布性、系统完整性、容错性的问题,以及逻辑视图的主要抽象如何与进程结构相配合在一起——即在哪个控制线程上,对象的操作被实际执行。
接着,我们可以区别主要任务、次要任务。主要任务是可以唯一处理的架构元素;次要任务是由于实施原因而引入的局部附加任务(如周期性活动、缓冲、暂停等)。主要任务的通讯途径是良好定义的交互任务通信机制∶基于消息的同步或异步通信服务、远程过程调用、事件广播等。次要任务则以会见或共享内存来通信。在同一过程或处理节点上,主要任务不应对它们的分配做出任何假定。消息流、过程负载可以基于过程蓝图来进行评估,同样可以使用哑负载来实现"中空"的进程架构,并测量在目标系统上的性能。正如Filarey etal 在他的 Eurocontrol实验中描述的那样。
开发架构关注软件开发环境下实际模块的组织。软件打包成小的程序块(程序库或子系统),它们可以由一位或几位开发人员来开发。子系统可以组织成分层结构,每个层为上一层提供良好定义的接口。系统的开发架构用模块和子系统图来表达,显示了"输出"和"输入"关系。完整的开发架构只有当所有软件元素被识别后才能加以描述。但是,可以列出热制开发架构的规则∶分块、分组和可见性。
大部分情况下,开发架构考虑的内部鹅求与以下几项因紊有关∶开发难度、软件管理、重用性和通用性及由工具集、编程语言所带来的限制。关于开发视图的风格,推荐使用分层(layered)的风格,定义 4~6个子系统层。每层均具有良好定义的职责。设计规则是某层子系统依赖同一层或低一层的子系统,从而最大程度地减少了具有复杂模块依赖关系的网络的开发量,得到层次式的简单策略。
第一层和第二层组成了独立于域的覆盖整个产品线的分布式基础设施,并保护其免受不同硬件平台、操作系统或市售产品(如数据库管理系统)的影响。第三层为该基础设施增加了 ATC(Adaptive Transfom Coding,自适应变换编码方法)框架,形成一个特定领域的软件架构(domain-specific sofware architecture)。使用该框架,可以在第四层上构建一个功能选择板。层次5则非常依赖于客户和产品,包含了大多数用户接口和外部系统接口。72 个子系统分布于5个层次上,每层包食了10~50个模块,并可以在其他蓝图上表示。
物理架构主要关注系统非功能性的需求,如可用性、可靠性(容错性),性能(吞吐量)和可伸缩性。物理蓝图的表示方法如上图所示:
TRW(Thompson Ramo Wooldridge Lnc)公司的 UNAS(Universal NetworkArchitecture Services)提供了数据驱动方法将过程架构映射至物理架构,该方法允许大量的映射的变更而无需修改源代码。
下面两个图显示了两种不同的物理架构上的进程映射,分别对应的是一个小型和一个大型PABX
4种视图的元素通过比较少的一组重要场景(更常见的是用例)进行无缝协同工作。关于场景的例子里,显示了对于小型PABX的场景片段,相应的脚本如下:
在进行文档化时,提倡一种更具有迭代性质的方法———架构先被原形化、测试、估量、分析,然后在一系列的迭代过程中被细化。该方法除了减少与架构相关的风险之外,对于项目而言还有其他优点∶团队合作、培训,加深对架构的理解,深入程序和工具等(此处提及的是演进的原形,逐渐发展成为系统,而不是一次性的试验性的原形)。这种迭代方法还能够使需求被细化、成熟化并能够被更好地理解。
场景驱动(scenario-driven)的方法
用心去感受你自己需要坚持的生活,未来慢慢会给你答案的。