1、基于UML的 软件设计和建模(2),上海交通大学 电子信息与电气工程学院 2006.10,2018/10/14,2,Agenda,软件开发流程简介 需求捕获工作流简介 软件分析工作流简介,2018/10/14,3,统一开发工程(RUP)基本流程,四次迭代 初始 精化 构建 产品化,2018/10/14,4,RUP核心工作流,需求捕获工作流 分析工作流 设计工作流 实现工作流 测试工作流,2018/10/14,5,Agenda,软件开发流程简介 需求捕获工作流简介 分析工作流简介,2018/10/14,6,需求分析的主要任务,获取需求 明确功能性需求 明确非功能性需求 需求按优先级分类 将需求转
2、化为用例模型 找到参与者与用例 用例细化 结构化用例模型,2018/10/14,7,获取需求,需求是所有软件开发项目的基础 需求分析根据用户对产品的功能的期望, 提取出产品外部功能的描述。需求分为两类: 1). 功能需求: 系统应该提供什么样的功能 2). 非功能需求: 系统的某种特别性质或者限制,2018/10/14,8,举例: ATM系统,功能需求: ATM系统可以检查插入的ATM卡的合法性 验证用户输入的密码正确与否 用户可以查询对应帐户余额 用户可以取款,取款限额不超过帐户余额 非功能需求 用 C+实现 与银行数据库通信时采用256位密钥加密 验证ATM卡的时间不超过3秒钟 验证密码的
3、时间不超过3秒钟,2018/10/14,9,用例建模,用例建模是需求工程的一种形式,用于引出并文档化需求 用例建模流程:- 找到系统边界 system boundary- 明确参与者actors- 明确用例 use cases: A. 明确用例明细; B. 建立场景scenarios.,2018/10/14,10,用例图的组成元素,四种元素: 参与者 Actors: 使用系统的人或事物 用例 Use case: 一组系统行为- 关系 Relationships: 参与者与用例之间的 关联、泛化和实现关系 - 系统边界System boundary: 区分系统内部和外部,2018/10/14,1
4、1,外部实体与系统交互时扮演的角色 可以是用户,也可以是与这个系统交互的另外一个系统注意:参与者总是在系统之外的,students,什么是参与者 actors,2018/10/14,12,如何找到参与者 actors,考虑谁或者什么使用这个系统,并且他们在交互过程中扮演一个什么样的角色 可以问自己这样一些问题: 谁或者什么使用这个系统? 他们在交互过程中扮演什么角色? 谁安装这个系统? 谁启动或者关闭这个系统? 谁维护这个系统? 有其他系统与这个系统交互么? 谁或什么从这个系统取得或者提供信息? 这些事情是不是在某个确定时间发生的? ,2018/10/14,13,需要注意的几点:,参与者总是在
5、系统之外的也在你的控制之外 参与者直接与系统交互用于定义系统边界 参与者代表用户或事物与系统交互过程中扮演的角色,而不是某一个人或者特定的事物 同一个人或者事物可能在某一时刻或在不同时刻扮演多个角色 每个参与者要有不同的名字,而且简明扼要 每个参与者需要有一个简单描述. 像类的表示一样,参与者也可以有属性或是事件,2018/10/14,14,时间作为参与者,当在建模的时候发现系统某一事件是在特定时刻发生的,而不是被人触发的 可以引入一个参与者叫做Time举例: 数据库系统每天晚上12点自动备份,2018/10/14,15,什么是用例,用例描述了当系统作用者和软件系统进行交互时,软件系统所执行的
6、一系列的动作序列。 这些动作序列包含 正常使用的各种动作序列, 对非正常使用时软件系统的动作序列的描述 注意 用例总是由参与者引发的 用例总是从参与者的角度描述的,2018/10/14,16,什么是用例(续),用例视图中用例的设置,就代表了软件系统的功能的划分。 为了得到得合理而方便的软件系统的功能设置,必须仔细考虑每个用例代表的动态行为的内容,使得每个用例都能产生一个有价值的结果。 在通过用例考虑软件系统的功能划分时,应使得功能的分布较为均衡、易于理解和使用,2018/10/14,17,如何来找用例,最佳方法:从每个参与者开始,考虑每个参与者是如何与系统交互的 可以考虑如下问题: 这个参与者
7、要求系统提供什么功能? 这个系统存储或者获取信息么?如果是的话,谁触发这个行为? 系统状态变化时,要通知某个参与者么? 有没有外部事件影响系统? 什么事物产生这个影响?,2018/10/14,18,用例的组织和用例图,在UML里, 用例图是表达用例和系统作用者及其之间关系的的载体 用例图可包含 用例 系统作用者 它们之间的关系 这些关系可以是 关联关系(某种联系,e.g. 参与,影响,使用) 依赖关系(include, extend) 实现关系(一般-特殊) 泛化关系(参与者泛化、用例泛化),2018/10/14,19,用例图示意,Course registration system,Enqu
8、ire courses,Register courses,Cancel courses,student,Use case,System name,actor,relationship,System boundary,FindStudent,FindCourse,2018/10/14,20,用例明细,用例明细Use case specification 每个用例都应该有它的名字和明细specification. 用例明细包括:- 前置条件 Preconditions- 事件流 Flow of events- 后置条件 Postconditions,2018/10/14,21,用例名,标识符,相关
9、的参与者,用例开始前的系统状态,用例的实际步骤,用例结束时的系统状态,包含的用例(可选),次要事件流(可选),2018/10/14,22,事件流的描述,用例代表系统和系统作用者之间发生的一系列的事件 事件流构成了用户对系统功能的一次使用。 对事件流的描述包括四种形式,即: 形式文本 非形式文本 交互图 状态图 有相应的UML成员作为这些描述的载体 文本和正式文本可用注标(note)表示 交互图和活动图本身即是一个标准的UML成员。,2018/10/14,23,主事件流和次要事件流,主事件流(main flow of events)和次要事件流(alternative flow of event
10、s)。 用来区分对系统功能的合法使用和非法使用 主事件流(main flow of events) 合法使用 只有一个 次要事件流(alternative flow of events) 可包含若干个 在描绘事件流时,必须用足够清晰的语言以使得一个普通的用户能够理解。,2018/10/14,24,场景(Scenario),一个用例可以有多个事件流,每一个事件流是一个完整的用户对系统的功能的使用。 它们出于同一个目的,但出于事件流不同,使得系统产生的响应不同。 它是对系统功能使用的特例(合法或非法的)每一个完整的事件流在UML中被称为场景,2018/10/14,25,高阶用例建模,参与者泛化 A
11、ctor Generalization 用例泛化 Use Case Generalization 包含 扩展,2018/10/14,26,参与者泛化,从特殊的参与者到一般的参与者的泛化关系 找到参与者泛化:- 找到一种公共的行为;- 找到parent actors (abstract actors) 和 child actors (concrete actors). 注意:- 参与者泛化中的父参与者并不一定是抽象的(abstract )。但是好的建模风格要求父参与者是抽象的.- 如果两个参与者与同一组用例有相同的交互,我们就可以用泛化的形式表示. 如下图所示,2018/10/14,27,Buy
12、er,Seller,Online Sales System,Login,Logout,Register,PublishNewItem,2018/10/14,28,Logout,Register,泛化,Buyer,Seller,User,PublishNewItem,Login,Online Sales System,2018/10/14,29,用例泛化,从特殊的用例到一般的用例之间的泛化关系 子用例是父用例的更详细的描述 如何确定用例泛化:- 将一个或多个公共行为抽象到一个父用例中 注意:- 子用例自动继承父用例的所有特征- 子用例可以增加新的特征;- 子用例可以覆盖(override)或改变
13、父用例的特征.例子见后面图,2018/10/14,30,包含关系 ,位于两个用例之间的包含关系意味着基用例显式地在其指定位置将另一个用例包含进来, 使其成为自己的行为的一部分。 包含关系可用于提取共用的用例。 在具有包含关系的两个用例中,被包含的那个用例不能单独存在,它只能以实例的形式存在于包含它的用例之中。,2018/10/14,31,扩展关系,两个用例之间的扩展关系,代表基用例(base use case)可以隐式地包含另一个用例作为其行为的一部分。 基用例可以独立于扩展用例单独存在。 当一个用例有多个子流程时,可以用扩展关系对其进行扩展,使得此基用例的不同子流程能在不同的情形下以扩展用例
14、的形式被激活,2018/10/14,32,注意:UML把包含关系和扩展关系表示为依赖关系的变体 在任何一种图形表示中,箭头所指的模型元素分别代表被包含的用例或被扩展用例(基用例), 而包含关系和扩展关系的变体标记分别是和(下页图)。,2018/10/14,33,2018/10/14,34,Agenda,软件开发流程简介 需求捕获工作流简介 分析工作流简介,2018/10/14,35,分析和设计阶段的建模工作,分析类(Analysis classes): 业务模型的核心概念 类图 用例实现(Use case realization): 描述某个用例中的分析类的实例是如何交互来完成用例明细中的事件
15、流的 交互图,2018/10/14,36,分析流程,Architectural Analysis,Analyze Use Cases,Analyze Classes,Analyze Packages,2018/10/14,37,分析建模经验方法,The analysis model is always in the language of the business. Create models that “tell a story”. Capture the big picture. Distinguish clearly between the problem domain and solu
16、tion domain. Always focus on abstractions that exist in the problem domain. Always try to minimize coupling: focus on classes and associations Explore inheritance where there is a natural hierarchy of abstractions Always ask “ is the model useful to all the stakeholders?” Do not make implementation
17、decisions Keep the model simple,2018/10/14,38,分析类,什么是分析类 分析类明细 寻找类 Noun/Verb and CRC 什么是好的分析类,2018/10/14,39,什么是分析类,分析类是在分析阶段产生的,用于解决用例视图定义的问题的解决方案中必须具备的对象的抽象 经过细化和完善后变成设计类,2018/10/14,40,8.2. 分析类明细,分析类一般包含以下信息: Name: 必要的 Attributes: 在这一阶段不一定完整,但尽量写. Operations: 操作的参数和返回类型可选. Visibility:一般按缺省即可(Att:pr
18、ivate Op: public) Stereotypes: 必要时显示 Tagged values: 必要时显示,2018/10/14,41,分析类的经验方法,Rules: 类要保持尽量简单 保持3到5个主要功能 每个类都不是独立的:应该与其他一些类有关联 注意那些很小的类:是否应该合并? 主要那些特别大的类:是否应该分割? ,2018/10/14,42,寻找类,使用名词/动词分析方法来找类 从问题描述直接分析的方法简单有效 尝试找到 classes, attributes 和operations 名字或名词短语暗示着 类或者类的属性(attributes) 动词或动词短语暗示 类的方法(o
19、perations),2018/10/14,43,名词/动词分析法的流程,第一步:收集尽可能多的信息 合适的信息包括:- 需求明晰(requirement specification);- 用例;- 项目术语表数据字典- 任何其他的( 架构, 说明文档, etc) 注意以下信息: 名词 e.g. course 名词短语 e.g. course number 动词 e.g. register 动词短语 - e.g. find course,2018/10/14,44,注意: 如果你对某些术语不了解,及时与领域专家沟通,并将该术语加入项目的术语表(Glossary) 从这些名词、名词短语、动词和动
20、词短语构建候选类、属性和方法的列表 有个这个候选列表,可以尝试划分类、属性和方法,2018/10/14,45,使用CRC方法寻找类,CRC Class, Responsibilities, and Collaborators 充分调动人的主观能动性,将找到的类写在即时帖上,然后粘在白板上。 协作类(Collaborators)是与当前研究的类相关的其他一些类,这些类一起来实现某个系统功能 分析类之间的关系,并在白板上将记有类的即时贴用线连起来 CRC分析方法应该与名词/动词分析法一起使用,2018/10/14,46,Phase 1: Brainstorm 收集信息,参与人员: OO analy
21、sts, stakeholders, domain experts 步骤 所有的idea都认为是好idea 所有的idea都被记录下来而暂时不讨论它们待以后分析 给问题分析中出现的事物命名 e.g. customer, product 把每个事物都记录在即时帖上它们就是候选类或属性 大家讨论这些事物的功能(responsibility),并将其记录在事物的operations栏内 最后将这些事物组织在一起修正完善,2018/10/14,47,Phase 2: 分析信息,参与人员: OO analysts and domain experts 决定哪些即时帖上的事物是类,哪些是属性。 如果对某个
22、即时帖存在疑问,就暂时把它当作一个类 最重要一点:能自圆其说,2018/10/14,48,其他来源,不要忘记还有很多方面值得考虑 实际的对象 文件 接口 概念实体等,2018/10/14,49,建立最初的分析模型,为了建立最初的分析模型,我们需要综合前面名词/动词分析,CRC分析和其他来源分析的结果,并组织生成一个模型 对比模型信息的三种来源,仔细考虑并解决不相同的部分。 明确分析类、属性和方法,之后用建模工具表现出来。 改进类、属性和方法的命名,使他们符合命名规范,2018/10/14,50,什么是好的抽象类,名称反映内容 是问题中某种明确对象的抽象 具有少数几个定义良好的功能(respon
23、sibility) 功能是这个类对客户类提供的承诺 功能表现为一组语义相关的操作 每个类最好只有3到5种职责 (简单原则,经验) 高内聚(high cohesion) all features of the class should help to realize its intent. 低耦合(low coupling) a class should only collaborate with a small number of other classes to realize its intent.,2018/10/14,51,什么是不好的抽象类,功能太单一的:一个类只有一个操作 万能类
24、检查那个名字是“system”或“controller”的类 继承层次很深 实际对象中的继承关系层次一般较浅 低耦合 高内聚,2018/10/14,52,类的组织 类图,UML中,类之间的语义连接定义为关系。 类之间的关系的建模,为其对象之间的交互提供了实现支持。 对象之间的交互,可以对应到类之间的关系,而这些关系,又可以被映射到大多数的程序设计语言,从而使得对象之间交互得到最终的实现。 在类之间的关系中,最常用的是 关联关系 依赖关系 泛化关系 它们在面向对象的建模中,起着十分重要的作用。,2018/10/14,53,依赖关系,依赖关系的定义: 两个类之间的依赖关系,表明其中 的一个类(客户
25、类)依赖于另一个 类(供应类)所提供的某些服务。 图形表示: 依赖关系被图形化地表示为一个带虚线的箭头 箭头所指的类是供应类(被依赖的类) 箭头的出发点是客户类(图7.2)。 两个类之间存在着依赖关系,意味着客户类的语义依赖于服务类的语义。服务类的语义的变化,将会导致客户类的语义的变化。,2018/10/14,54,依赖关系(续),如果两个类的对象之间存在着下面的情形,且两个类之间不存在结构方面的联系(例如:供应类以成员变量的形式作为客户类的一部分),就可以建模成为具有依赖关系,这些情形是: 客户类访问定义在供应类内部的值(常量或 变量)。 客户类的操作启动了定义在供应类内的操作。 客户类的返
26、回类或参数是供应类的实例。 序列图中的两个对象,如果存在着消息的发送。且它们之间又没有结构方面的连接,就可以在类图上用依赖关系对它们建模。,2018/10/14,55,泛化关系,泛化关系的定义 在UML中,泛化关系表示子类共享定义在一个或多个超类(parent)里的结构或行为。 泛化关系表示类之间的一般和特殊的关系 在一组类中,如果它们都有一组相同的属性和操作,那么可以把这组属性和操作定义在一个超类中,并把其它类与超类的关系定义为泛化关系 如果两个类被定义为具有泛化关系就意味着在任何超类的对象出现的地方,都可以用子类来代替。,2018/10/14,56,泛化关系(续),泛化关系的图形化表示 在
27、UML中,泛化关系被图形化地表示为一个带有空心三角形的箭头的线段 箭头所指的方向是超类,箭头起始端是子类。 在泛化关系中一个类可以有零个、一个或多个多个超类 如果一个类只有一个超类,那么就称为是单继承 如果一个类有多个超类,就称为是多重继承 如果一个类没有超类但有一个或多个子类,则这个类成为基类(base class) 如果一个类没有任何子类,则成为叶子类 继承的多态性 在子类中,如果存在一个操作和其超类中的操作具有相同的署名(signature), 则子类中的此操作的动态行为将替代超类的动态行为。,2018/10/14,57,关联关系,关联关系的定义 在UML里,关联关系表示两个类或类和接口
28、之间的语义连接。 关联关系可以是双向的。 它在所有的关系中间语义最弱 从关联关系的定义可以看出,如果两个类之间存在着依赖关系或泛化关系,那么它们一定也隐含着具有关连关系 一般不必再对这种关联关系描述,或者说它已被取代 这就是“语义最弱”的含义所在,2018/10/14,58,关联关系(续),关联关系是一种结构关系 如果两个类之间存在着关联关系 则它们的对象是互相连接的(对象之间存在着连接关系) 即其中的一个对象可以访问另一个对象 它可以 访问另一个对象的属性, 或启动另一个对象的操作。,2018/10/14,59,关联关系(续),关联关系并不是仅仅一个抽象的概念 它在实现为程序设计语言源代码时
29、,会有对应的映射。 通常,当把两个有关联关系的类映射为特定的程序设计语言代码时,每一个类都会被定义为一个可以引用对方的类的对象的成员变量 这个成员变量视对关联关系的修饰的不同,可能会采取不同的形式,如: 它可以指向对方的类的指针 也可能是对方类的对象。,2018/10/14,60,关联关系(续),关联关系的图形表示 在UML中,关联关系的图形化表示的基本形式是连接两个类的直线 由于关联关系的语义弱,所以可以对关联关系及其图形表示进行修饰,以表达更为特指的情形 聚合关联和组合关联,2018/10/14,61,2018/10/14,62,组合关联、聚合关联,组合,2018/10/14,63,用例图
30、示意,Course registration system,Enquirecourses,Register courses,Cancel courses,student,Use case,System name,actor,relationship,System boundary,FindStudent,FindCourse,2018/10/14,64,2018/10/14,65,分析和设计阶段的建模工作,分析类(Analysis classes): 业务模型的核心概念 类图 用例实现(Use case realization): 描述某个用例中的分析类的实例是如何交互来完成用例明细中的事件流
31、的 交互图,2018/10/14,66,用例实现 Use Case Realization,主要内容 交互图 时序图 协作图 什么时候使用交互图,2018/10/14,67,分析一个用例,用例和分析类为系统作静态建模 用例实现描述类的实例在实现系统功能时是如何交互的 用例实现包含以下元素: 交互图(主体) 用例完善Use case refinement: 在用例实现过程中可能会发现新信息,需要更新用例明细(spec),2018/10/14,68,什么是用例实现,在找到分析类之后,主要的分析工作就是用例实现 用例实现是描述一组类及其实例如何交互,实现用例明细中的功能. 举例:比如你有一个用例:
32、BorrowBook,参与者 Librarian和如下分析类: Book, Borrower, ticket。 你需要建立一个用例实现来描述这些类、类的实例是如何交互来实现用例明细中所规定的行为的 用例实现一般用交互图表示,2018/10/14,69,交互图Interaction Diagrams,交互图描述用例或用例的一部分之中对象的协作与交互. 一般来说,一个交互图描述单个用例的行为。 交互图分为两种:时序图 和 协作图 它们在语义上是等价的意味着可以互相转换 时序图 强调的是为实现此行为系统在时序方面的特性; 协作图 强调系统在结构方面的特性,2018/10/14,70,协作图,协同图描
33、述参加一个交互的各对象的组织 协同图的组成元素 对象Object:类的实例 参与者 消息Message 消息的表示:序号:返回值:=消息名称(参数1,参数2 ),2018/10/14,71,标准约束Standard constraints,Table 12.5,UML 提供标准约束用于指示对象或者连接的建立和销毁,2018/10/14,72,2018/10/14,73,从这个用例,我们获得如下元素:,RegistrationManager,Course,1,*,2018/10/14,74,Multiobject,2018/10/14,75,自调用(Self-delegation)和程序分支,S
34、elf-delegation 是一个对象自己调用自己的操作我们可以通过在消息前添加条件condition来给分支建模 condition 是一个布尔(boolean)表达式. 对象根据条件的真假发送不同的消息,2018/10/14,76,用例举例: registerCourse,2018/10/14,77,程序分支举例,Figure 12.12,2018/10/14,78,时序图,时序图描述对象间按时间序列交互的关系 时序图的时间表示是从上到下,从左到右 每个参与者或者对象下面的虚线代表它们的生命周期 用符号 X 代表生命周期结束,2018/10/14,79,消息类型、表示法和语义,2018/
35、10/14,80,2018/10/14,81,2018/10/14,82,时序图与协作图的比较,不同的开发者会有不同的使用偏好 协作图适合展示实际的对象和他们的结构性关系,但是不适合描述这些对象间按时间序列的交互。 一些人喜欢时序图,因为可以从它很容易看出事件发生的顺序。 另一些人喜欢协作图,因为从它的布局可以看出这些对象是如何组织和联系的。,2018/10/14,83,什么时候用这两种交互图,当想要了解参与某个用例的所有对象的行为时. 交互图适合描述对象间的协作 但不适合精确描述某个对象的行为 如果要了解单个对象在多个用例中的行为,可以使用状态图(自学) 如果要了解系统或系统一部分的工作流,可以使用活动图(自学),