‘壹’ 在UML中,约束有哪两种表示方法它们分别是什么
当然,步痕旅游网想法:您的查询字词都已标明如下:商务信息 的 具体 定义 (点击查询词,可以跳到它在文中首次出现的位置)
如果打开速度慢,您可以尝试打开无图片的快照
(网络和网页的作者无关,不对其内容负责。网络快照谨为网络故障时之索引,不代表被搜索网站的即时页面。)
--------------------------------------------------------------------------------
设为首页 收藏 求助 用户名 密码 自动登录 - 快速注册 - 找回密码 - 使用手册
首页 圈子 活动 博客 炒饭 会员 相册 招贴 搜索 邀请 圈子 活动
写字楼圈·运动圈·球友圈·同学圈·同事圈·亲友圈·同乡圈·行业圈·主题圈·媒体圈·业主圈·情感圈·企业圈·其他圈
导航: 圈网首页>>我的管理中心>>IT圈>>北京程序社区 加入该圈子
功能区: 短留言 | 相册 | 活动 | 圈子日志 | 商务信息 | 成员列表 | 链接 | 邀请朋友 | 群发圈内消息 | 圈子管理
主题留言板: 软件工程 | 灌水区 | 项目管理 | .net技术 | 修身养性 |
解析UML的静态建模机制 2006-08-02 02:54 nuaalfm(方明) 推荐给好友
作者:51CMM 本文选自:51CMM 2002年12月10日任何建模语言都以静态建模机制为基础,标准建模语言UML也不例外。UML的静态建模机制包括用例图(Use case diagram)、类图(Class diagram)、对象图(Object diagram )、包(Package)、构件图(Component diagram)和配置图(Deployment diagram)。
用例图
用例模型(Use case model)
长期以来,在面向对象开发和传统的软件开发中,人们根据典型的使用情景来了解需求。但是,这些使用情景是非正式的,虽然经常使用,却难以建立正式文挡。用例模型由Ivar Jacobson在开发AXE系统中首先使用,并加入由他所倡导的OOSE和Objectory方法中。用例方法引起了面向对象领域的极大关注。自1994年Ivar Jacobson的着作出版后,面向对象领域已广泛接纳了用例这一概念,并认为它是第二代面向对象技术的标志。
用例模型描述的是外部执行者(Actor)所理解的系统功能。用例模型用于需求分析阶段,它的建立是系统开发者和用户反复讨论的结果,表明了开发者和用户对需求规格达成的共识。
首先,它描述了待开发系统的功能需求;
其次,它将系统看作黑盒,从外部执行者的角度来理解系统;
第三,它驱动了需求分析之后各阶段的开发工作,不仅在开发过程中保证了系统所有功能的实现,而且被用于验证和检测所开发的系统,从而影响到开发工作的各个阶段和UML的各个模型。在UML中,一个用例模型由若干个用例图描述,用例图主要元素是用例和执行者。
用例(use case)
从本质上讲,一个用例是用户与计算机之间的一次典型交互作用。以字处理软件为例,“将某些正文置为黑体”和“创建一个索引”便是两个典型的用例。在UML中,用例被定义成系统执行的一系列动作,动作执行的结果能被指定执行者察觉到。
在UML中,用例表示为一个椭圆。图1显示了一个金融贸易系统的用例图。其中,“风险分析”,“交易估价”,“进行交易”,“设置边界”,“超越边界的交易”,“评价贸易”,“更新帐目”等都是用例的实例。概括地说,用例有以下特点:
·用例捕获某些用户可见的需求,实现一个具体的用户目标。
·用例由执行者激活,并提供确切的值给执行者。
·用例可大可小,但它必须是对一个具体的用户目标实现的完整描述。
图1 金融贸易系统用例
执行者(Actor)
执行者是指用户在系统中所扮演的角色。其图形化的表示是一个小人。图1中有四个执行者:贸易经理、营销人员、售货员和记帐系统。在某些组织中很可能有许多营销人员,但就该系统而言,他们均起着同一种作用,扮演着相同的角色,所以用一个执行者表示。一个用户也可以扮演多种角色(执行者)。例如,一个高级营销人员既可以是贸易经理,也可以是普通的营销人员;一个营销人员也可以是售货员。在处理执行者时,应考虑其作用,而不是人或工作名称,这一点是很重要的。
图1中,不带箭头的线段将执行者与用例连接到一起,表示两者之间交换信息,称之为通信联系。执行者触发用例,并与用例进行信息交换。单个执行者可与多个用例联系;反过来,一个用例可与多个执行者联系。对同一个用例而言,不同执行者有着不同的作用:他们可以从用例中取值,也可以参与到用例中。
需要注意的是执行者在用例图中是用类似人的图形来表示,尽管执行的,但执行者未必是人。例如,执行者也可以是一个外界系统,该外界系统可能需要从当前系统中获取信息,与当前系统有进行交互。在图1中,我们可以看到,记帐系统是一个外界系统,它需要更新帐目。
通过实践,我们发现执行者对提供用例是非常有用的。面对一个大系统,要列出用例清单常常是十分困难。这时可先列出执行者清单,再对每个执行者列出它的用例,问题就会变得容易很多。
使用和扩展(Use and Extend)
图1中除了包含执行者与用例之间的连接外,还有另外两种类型的连接,用以表示用例之间的使用和扩展关系。使用和扩展是两种不同形式的继承关系。当一个用例与另一个用例相似,但所做的动作多一些,就可以用到扩展关系。例如图1中,基本的用例是"进行交易"。交易中可能一切都进行得很顺利,但也可能存在扰乱顺利进行交易的因素。其中之一便是超出某些边界值的情况。例如,贸易组织会对某个特定客户规定最大贸易量,这时不能执行给定用例提供的常规动作,而要做些改动。我们可在"进行交易"用例中做改动。但是,这将把该用例与一大堆特殊的判断和逻辑混杂在一起,使正常的流程晦涩不堪。图1中将常规的动作放在"进行交易"用例中,而将非常规的动作放置于"超越边界的交易"用例中,这便是扩展关系的实质。当有一大块相似的动作存在于几个用例,又不想重复描述该动作时,就可以用到使用关系。例如,现实中风险分析和交易估价都需要评价贸易,为此可单独定义一个用例,即"评价贸易",而"风险分析"和"交易估价"用例将使用它。
请注意扩展与使用之间的相似点和不同点。它们两个都意味着从几个用例中抽取那些公共的行为并放入一个单独用例中,而这个用例被其他几个用例使用或扩展。但使用和扩展的目的是不同的。
用例模型的获取
几乎在任何情况下都会使用用例。用例用来获取需求,规划和控制项目。用例的获取是需求分析阶段的主要任务之一,而且是首先要做的工作。大部分用例将在项目的需求分析阶段产生,并且随着工作的深入会发现更多的用例,这些都应及时增添到已有的用例集中。用例集中的每个用例都是一个潜在的需求。
1. 获取执行者
获取用例首先要找出系统的执行者。可以通过用户回答一些问题的答案来识别执行者。以下问题可供参考:
·谁使用系统的主要功能(主要使用者)。
·谁需要系统支持他们的日常工作。
·谁来维护、管理使系统正常工作(辅助使用者)。
·系统需要操纵哪些硬件。
·系统需要与哪些其它系统交互,包含其它计算机系统和其它应用程序。
·对系统产生的结果感兴趣的人或事物。
相关回复
解析UML的静态建模机制(2)
2. 获取用例
一旦获取了执行者,就可以对每个执行者提出问题以获取用例。
以下问题可供参考:
·执行者要求系统提供哪些功能(执行者需要做什么)?
·执行者需要读、产生、删除、修改或存储的信息有哪些类型。
·必须提醒执行者的系统事件有哪些?或者执行者必须提醒系统的事件有哪些?怎样把这些事件表示成用例中的功能?
·为了完整地描述用例,还需要知道执行者的某些典型功能能否被系统自动实现?
还有一些不针对具体执行者问题(即针对整个系统的问题):
·系统需要何种输入输出?输入从何处来?输出到何处?
·当前运行系统(也许是一些手工操作而不是计算机系统)的主要问题?
需要注意,最后两个问题并不是指没有执行者也可以有用例,只是获取用例时尚不知道执行者是什么。一个用例必须至少与一个执行者关联。还需要注意:不同的设计者对用例的利用程度也不同。例如,Ivar Jacobson说,对一个十人年的项目,他需要二十个用例。而在一个相同规模的项目中,Martin Fowler则用了一百多个用例。我们认为:任何合适的用例都可使用,确定用例的过程是对获取的用例进行提炼和归纳的过程,对一个十人年的项目来说,二十个用例似乎太少,一百多个用例则嫌太多,需要保持二者间的相对均衡。
类图、对象图和包
数千年以前,人类就已经开始采用分类的方法有效地简化复杂问题,帮助人们了解客观世界。在面向对象建模技术中,我们使用同样的方法将客观世界的实体映射为对象,并归纳成一个个类。类(Class)、对象(Object)和它们之间的关联是面向对象技术中最基本的元素。对于一个想要描述的系统,其类模型和对象模型揭示了系统的结构。在UML中,类和对象模型分别由类图和对象图表示。类图技术是OO方法的核心。图2显示了一个金融保险系统的类图。
图2 金融保险系统类图
类图
类图(Class Diagram)描述类和类之间的静态关系。与数据模型不同,它不仅显示了信息的结构,同时还描述了系统的行为。类图是定义其它图的基础。在类图的基础上,状态图、合作图等进一步描述了系统其他方面的特性。
类和对象
对象(Object)与我们对客观世界的理解相关。我们通常用对象描述客观世界中某个具体的实体。所谓类(Class)是对一类具有相同特征的对象的描述。而对象是类的实例(Instance)。建立类模型时,我们应尽量与应用领域的概念保持一致,以使模型更符合客观事实,易修改、易理解和易交流。
类描述一类对象的属性(Attribute)和行为(Behavior)。在UML中,类的可视化表示为一个划分成三个格子的长方形(下面两个格子可省略)。图1中,"客户"就是一个典型的类。
类的获取和命名 最顶部的格子包含类的名字。类的命名应尽量用应用领域中的术语,应明确、无歧义,以利于开发人员与用户之间的相互理解和交流。类的获取是一个依赖于人的创造力的过程,必须与领域专家合作,对研究领域仔细地分析,抽象出领域中的概念,定义其含义及相互关系,分析出系统类,并用领域中的术语为类命名。一般而言,类的名字是名词。
· 类的属性
中间的格子包含类的属性,用以描述该类对象的共同特点。该项可省略。图2中“客户”类有"客户名"、"地址"等特性。属性的选取应考虑以下因素:
*原则上来说,类的属性应能描述并区分每个特定的对象;
*只有系统感兴趣的特征才包含在类的属性中;
*系统建模的目的也会影响到属性的选取。根据图的详细程度,每条属性可以包括属性的可见性、属性名称、类型、缺省值和约束特性。UML规定类的属性的语法为:
可见性 属性名 : 类型 = 缺省值 {约束特性}
图2“客户”类中,"客户名"属性描述为"- 客户名 : 字符串 = 缺省客户名"。
可见性"-"表示它是私有数据成员,其属性名为"客户名",类型为"字符串"类型,缺省值为"缺省客户名",此处没有约束特性。
不同属性具有不同可见性。常用的可见性有Public、Private和Protected三种,在UML中分别表示为" "、"-"和"#"。
类型表示该属性的种类。它可以是基本数据类型,例如整数、实数、布尔型等,也可以是用户自定义的类型。一般它由所涉及的程序设计语言确定。
约束特性则是用户对该属性性质一个约束的说明。例如"{只读}"说明该属性是只读属性。
· 类的操作(Operation)
该项可省略。操作用于修改、检索类的属性或执行某些动作。操作通常也被称为功能,但是它们被约束在类的内部,只能作用到该类的对象上。操作名、返回类型和参数表组成操作界面。UML规定操作的语法为:
可见性 操作名 (参数表) : 返回类型 {约束特性}
在图2中,"客户"类中有"取客户地址"操作,其中" "表示该操作是公有操作,调用时需要参数"客户名",参数类型为字符串,返回类型也为字符串。
类图描述了类和类之间的静态关系。定义了类之后,就可以定义类之间的各种关系了。
关联关系
关联(Association)表示两个类之间存在某种语义上的联系。例如,一个人为一家公司工作,一家公司有许多办公室。我们就认为人和公司、公司和办公室之间存在某种语义上的联系。在分析设计的类图模型中,则在对应人类和公司类、公司类和办公室类之间建立关联关系。
在图2中最上部存在一个"属于"/"签定"关联:每个"保险单"属于一个"客户",而"客户"可以签定多个"保险单"。除了这个关联外,图1中还有另外两个关联,分别表示每个"保险单"包含若干个"保险单上的项目",而每个"保险单上的项目"涉及单一的"保险类别"。
· 关联的方向
关联可以有方向,表示该关联单方向被使用。关联上加上箭头表示方向,在UML中称为导航(Navigability)。我们将只在一个方向上存在导航表示的关联,称作单向关联 ( Uni-directional Association ),在两个方向上都有导航表示的关联,称作双向关联 ( Bi-directional Association )。图2中,"保险单"“保险单上的项目”是单向关联。UML规定,不带箭头的关联可以意味着未知、未确定或者该关联是双向关联三种选择,因此,在图中应明确使用其中的一种选择。
· 关联的命名
既然关联可以是双向的,最复杂的命名方法是每个方向上给出一个名字,这样的关联有两个名字。(见图2中最上部的"属于"/"签定"关联)。为关联命名有几种方法,其原则是该命名是否有助于理解该模型。
· 角色
关联两头的类以某种角色参与关联。例如图3中,"公司"以"雇主"的角色,"人"以"雇员"的角色参与的"工作合同"关联。"雇主"和"雇员"称为角色名。如果在关联上没有标出角色名,则隐含地用类的名称作为角色名。角色还具有多重性(Multiplicity),表示可以有多少个对象参与该关联。在图3中,雇主(公司)可以雇佣(签工作合同)多个雇员,表示为"*";雇员只能与一家雇主签定工作合同,表示为"1"。多重性表示参与对象的数目的上下界限制。"*"代表0~∞,即一个客户可以没有保险单,也可以有任意多的保险单。"1"是1..1的简写,即任何一个保险单仅来自于一个客户,可以用一个单个数字表示,也可以用范围或者是数字和范围不连续的组合表示。
图3 关联的角色
· 关联类
一个关联可能要记录一些信息,可以引入一个关联类来记录。图4是在图3的基础上引入了关联类。关联类通过一根虚线与关联连接。图5是实现上述目标的另外一种方法,就是使雇用关系成为一个正式的类。
图4 关联类
图5 另一种实现方法
· 聚集和组成
聚集(Aggregation)是一种特殊形式的关联。聚集表示类之间的关系是整体与部分的关系。一辆轿车包含四个车轮、一个方向盘、一个发动机和一个底盘,这是聚集的一个例子。在需求分析中,"包含"、"组成"、"分为……部分"等经常设计成聚集关系。聚集可以进一步划分成共享聚集(Shared Aggregation)和组成。例如,课题组包含许多成员,但是每个成员又可以是另一个课题组的成员,即部分可以参加多个整体,我们称之为共享聚集。另一种情况是整体拥有各部分,部分与整体共存,如整体不存在了,部分也会随之消失,这称为组成(Composition)。例如,我们打开一个视窗口,它就由标题、外框和显示区所组成。一旦消亡则各部分同时消失。在UML中,聚集表示为空心菱形,组成表示为实心菱形。需要注意的是,一些面向对象大师对聚集的定义并不一样。大家应注意其他面向对象方法与UML中所定义的聚集的差别。
继承关系
人们将具有共同特性的元素抽象成类别,并通过增加其内涵而进一步分类。例如,动物可分为飞鸟和走兽,人可分为男人和女人。在面向对象方法中将前者称为一般元素、基类元素或父元素,将后者称为特殊元素或子元素。继承(Generalization)定义了一般元素和特殊元素之间的分类关系。在UML中,继承表示为一头为空心三角形的连线。
如图2中,将客户进一步分类成个体客户和团体客户,使用的就是继承关系。
在UML定义中对继承有三个要求:
*特殊元素应与一般元素完全一致,一般元素所具有的关联、属性和操作,特殊元素也都隐含性地具有;
*特殊元素还应包含额外信息;
*允许使用一般元素实例的地方,也应能使用特殊元素。
依赖关系
有两个元素X、Y,如果修改元素X的定义可能会引起对另一个元素Y的定义的修改,则称元素Y依赖(Dependency)于元素X。在类中,依赖由各种原因引起,如:一个类向另一个类发消息;一个类是另一个类的数据成员;一个类是另一个类的某个操作参数。如果一个类的界面改变,它发出的任何消息可能不再合法。
发表者:nuaalfm(方明) - - 2006-08-02 02:56
解析UML的静态建模机制(3)
类图的抽象层次和细化(Refinement)关系
需要注意的是,虽然在软件开发的不同阶段都使用类图,但这些类图表示了不同层次的抽象。在需求分析阶段,类图是研究领域的概念;在设计阶段,类图描述类与类之间的接口;而在实现阶段,类图描述软件系统中类的实现。按照Steve Cook和John Dianiels的观点,类图分为三个层次。需要说明的是,这个观点同样也适合于其他任何模型,只是在类图中显得更为突出。
· 概念层
概念层(Conceptual)类图描述应用领域中的概念。实现它们的类可以从这些概念中得出,但两者并没有直接的映射关系。事实上,一个概念模型应独立于实现它的软件和程序设计语言。
· 说明层
说明层(Specification)类图描述软件的接口部分,而不是软件的实现部分。面向对象开发方法非常重视区别接口与实现之间的差异,但在实际应用中却常常忽略这一差异。这主要是因为OO语言中类的概念将接口与实现合在了一起。大多数方法由于受到语言的影响,也仿效了这一做法。现在这种情况正在发生变化。可以用一个类型(Type )描述一个接口,这个接口可能因为实现环境、运行特性或者用户的不同而具有多种实现。
· 实现层
只有在实现层(Implementation)才真正有类的概念,并且揭示软件的实现部分。这可能是大多数人最常用的类图,但在很多时候,说明层的类图更易于开发者之间的相互理解和交流。
理解以上层次对于画类图和读懂类图都是至关重要的。但是由于各层次之间没有一个清晰的界限,所以大多数建模者在画图时没能对其加以区分。画图时,要从一个清晰的层次观念出发;而读图时,则要弄清它是根据哪种层次观念来绘制的。要正确地理解类图,首先应正确地理解上述三种层次。虽然将类图分成三个层次的观点并不是UML的组成部分,但是它们对于建模或者评价模型非常有用。尽管迄今为止人们似乎更强调实现层类图,但这三个层次都可应用于UML,而且实际上另外两个层次的类图更有用。
下面介绍细化概念。细化是UML中的术语,表示对事物更详细一层的描述。两个元素A、B描述同一件事物,它们的区别是抽象层次不同,若元素B是在元素A的基础上的更详细的描述,则称元素B细化了元素A,或称元素A细化成元素B。细化的图形表示为由元素B指向元素A的、一头为空心三角的虚线(千万不要把方向颠倒了!)。细化主要用于模型之间的合作,表示开发各阶段不同层次抽象模型的相关性,常用于跟踪模型的演变。
约束
在UML中,可以用约束(Constraint)表示规则。约束是放在括号"{}"中的一个表达式,表示一个永真的逻辑陈述。在程序设计语言中,约束可以由断言(Assertion)来实现。
对象图、对象和链
UML中对象图与类图具有相同的表示形式。对象图可以看作是类图的一个实例。对象是类的实例;对象之间的链(Link)是类之间的关联的实例。对象与类的图形表示相似,均为划分成两个格子的长方形(下面的格子可省略)。上面的格子是对象名,对象名下有下划线;下面的格子记录属性值。链的图形表示与关联相似。对象图常用于表示复杂的类图的一个实例。
包
一个最古老的软件方法问题是:怎样将大系统拆分成小系统。解决这个问题的一个思路是将许多类集合成一个更高层次的单位,形成一个高内聚、低耦合的类的集合。这个思路被松散地应用到许多对象技术中。UML中这种分组机制叫包(Package)(见图6)。
图6 包图
不仅是类,任何模型元素都运用包的机制。如果没有任何启发性原则来指导类的分组,分组方法就是任意的。在UML中,最有用的和强调最多的启发性原则就是依赖。包图主要显示类的包以及这些包之间的依赖关系。有时还显示包和包之间的继承关系和组成关系。
· 包的内容
在图6中,"系统内部"包由"保险单"包和"客户"包组成。这里称"保险单"包和"客户"包为"系统内部"包的内容。当不需要显示包的内容时,包的名字放入主方框内,否则包的名字放入左上角的小方框中,而将内容放入主方框内。包的内容可以是类的列表,也可以是另一个包图,还可以是一个类图。
· 包的依赖和继承
图6中"保险单填写界面"包依赖于"保险单"包;整个"系统内部"包依赖于"数据库界面"包。可以使用继承中通用和特例的概念来说明通用包和专用包之间的关系。例如,专用包必须符合通用包的界面,与类继承关系类似。通过"数据库界面"包,"系统内部"包既能够使用Oracle的界面也可使用Sybase的界面。通用包可标记为{abs tract},表示该包只是定义了一个界面,具体实现则由专用包来完成。
其他模型元素和表示机制
类图中用到的模型元素和表示机制较为丰富,由于篇幅的限制,这里不能一一介绍。主要还有以下模型符号和概念:类
‘贰’ 需求管理的与需求有关的问题:
需求不总是显而易见的,而且它可来自各个方面. 需求并不总是容易用文字明白无误地表达. 存在不同种类的需求,其详细程度各不相同. 如果不加以控制,需求的数量将难以管理. 需求相互之间以及与流程的其他可交付工件之间以多种方式相关联. 需求有唯一的特征或特征值.例如,它们既非同等重要,处理的难度也不同. 需求涉及众多相关利益责任方,这意味着需求要由跨职能的各组人员来管理. 需求发生变更. 需求可能对时间敏感. 当这些问题与需求管理和处理技能不足以及缺乏易用工具等情况一同出现时,许多团队都对管理好需求不抱希望了.IBM Rational 已经开发出指导团队提高需求管理技能和流程的专业技术,并使用相应的工具使得上述的流程和专业技术得以实现.
从上述的分析可以看出,需求的捕获是需求管理的基础和前提.在这里,将介绍一种为业界所广泛采用并经验证的需%E4%BE%8B%E6%A8%A1%E5%9E%8B target=_new class=innerlink>用例模型. 用例模型是系统既定功能及系统环境的模型,并作为客户和开发人员之间的契约.
用例模型用作分析,设计和测试活动的基本输入.用例是贯穿整个系统开发的一条主线.同一个用例模型即为需求工作流程的结果,可当作分析设计工作流程以及测试工作流程的输入使用.参与者(Actor)和用例(UseCase)是用例模型中的主要元素. 下图显示了自动取款机系统用例模型的一部分:
客户
查询
提款
转帐
客户身份验证系统时钟
数据库服务器
(from )系统维护
信函打印机
打印对帐单
用例图用于显示包含参与者和用例的用例模型示例.系统建模有许多种方法,每种建模方法可以满足不同的目的.然而,用例模型最重要的作用是将系统行为传达给客户或最终用户.可能与该系统交互的用户和任何其他系统都是参与者.由于参与者代表了系统用户,它们协助界定系统并提供十分明确的系统用途说明.编写用例依据参与者的需求来进行.这样就确保该系统成为用户期望得到的系统.
参与者和用例都是通过将客户需求及潜在用户当作重要的信息查找到的.找到这些用例和参与者后,应对它们作简要说明.在详细说明这些用例之前,客户应复审该用例模型以核实所有的用例和参与者都已经找到,并且它们可以提供客户所需要的东西. 在迭代开发环境中,您可以选择用例的子集以便在每个迭代中详细描述.参与者和用例找到后,需要详细说明每个用例的事件流.这些说明指出系统与参与者交互的方式以及在各个独立用例中系统执行的有关操作.
最后,对已完成的用例模型(包括用例说明)进行复审,开发人员和客户使用该模型对系统应执行的操作达成一致意见.
‘叁’ 我们应当怎样做需求分析:功能角色分析与用例图
在我们进行一系列需求调研工作的同时,我们的需求分析工作也开始启动了。需求调研与需求分析工作应当是相辅相伴共同进行的。每次参加完需求调研回到公司,我们就应当对需求调研的成果进行一次需求分析。当下一次开始进行需求调研时,我们应当首先将上次需求分析的结果与客户进行确认,同时对需求分析中提出的疑问交给客户予以解答。这就是一个需求捕获->需求整理->需求验证->再需求捕获的过程。
但是,当我们经过一番忙碌,将需求中的第一手资料从调研现场捕获回来以后,我们应当怎样进行分析呢?不少团队对此都比较迷茫,没有一个统一和有效的方法,往往采用想到哪里做到哪里的方式。一些问题想到了就做了,没有想到则忽略掉了。实际上,需求分析不应当是太公钓鱼,而应当是拉网排查。任何一个疏忽都可能对项目研发带来风险。因此,我们应当采用一套成熟而完整的分析方法,稳步而有序地完成这部分工作。不同类型的软件项目其分析方法可能存在差异,但一般来说,信息化管理类软件项目通常从这几个方面着手分析:功能角色分析、业务流程分析与业务领域分析。
需求分析不是一项一蹴而就就可以完成的工作,它需要一个长期的过程,而这个过程是一个由粗到细的过程,它体现了人类认识事物的客观规律。在需求分析的初期,我们对需求的认识往往是整体的、宏观的,随着分析工作的逐渐深入,一步步细化。按照这个思路,我们对需求的分析,首先应当从功能角色分析开始。所谓功能角色分析,就是从一个外部用户的视角分析整个软件系统能够提供的功能,以及这些功能到底是提供给哪些角色使用。
对一个系统进行功能和角色方面的梳理和分析,可以采用的比较主流的方法之一就是绘制用例图。用例图是UML的4+1视图中的一种,准确地说就是那个“+1”。用例图是贯穿整个面向对象分析/设计(OOA/D)的核心视图,它描述的是系统到底为用户提供了哪些功能,以及到底是哪些用户在使用这些功能,是沟通用户与技术人员的桥梁。运用用例视图对业务需求进行分析、抽象、整理、提炼,进而形成抽象模型的过程称之为用例建模,而这个模型就是用例模型。
一般地,在一个用例图中通常有三种元素:参与者(Actor)、用例(Use Case)与系统边界(Boundary)。用例描述的是系统为用户提供的功能,也就是系统能为用户做什么,通常被绘制成一个椭圆;参与者,我认为称为角色更加合适,也就是系统为哪些类型的用户提供服务,他们都各自承担哪些不同的职责,通常被绘制成一个小人儿;最后是系统边界,也就是系统是对现实世界哪个范围的内容进行的模拟,它涉及到软件设计的工作范围与工作量,通常被绘制成一个方框。但是,通常情况下系统边界只是一个概念而不用真正绘制出来,因为被绘制成用例的必然是系统内部的功能,被绘制成参与者的必然是系统外部事物。从这个意义上讲,用例图中的参与者不仅包括人,还包括那些外部系统和自动触发器。根据这样一个思路,我以往常常将外部系统和自动触发器绘制成一个小人,这常常令客户感到困惑。随后我改变了思路,将外部系统和自动触发器绘制成另一种表达形式——类元符号表示法,并在构造型上标注为Actor。
功能角色分析是对系统宏观的、整体的需求分析,它用简短的图形绘制出了一个系统的整体轮廓。但仅仅进行功能角色分析是远远不够的,我们还需要在它的基础上做更加详尽的分析。
‘肆’ 用例模型在面向对象分析中的重要作用是什么
用例图将要设计的整个系统的需求分为若干模块,并定义了每个模块的参与者和参与者之间的联系。用例图就是业务逻辑的总体概况。
‘伍’ 面向对象中的用例图与结构化方法中的数据流图dfd有何异同
用于需求建模的方法有很多种,最常用的包括数据流图(DFD)、实体关系图(ERD)和用例图(Use Case)三种方式。DFD作为结构化系统分析与设计的主要方法,已经得到了广泛的应用,DFD尤其适用于MIS系统的表述。DFD使用四种基本元素来描述系统的行为,过程、实体、数据流和数据存储。DFD方法直观易懂,使用者可以方便地得到系统的逻辑模型和物理模型,但是从DFD图中无法判断活动的时序关系。图2描述的是某个项目的DFD示意图。
ERD方法用于描述系统实体间的对应关系,需求分析阶段使用ERD描述系统中实体的逻辑关系,在设计阶段则使用ERD描述物理表之间的关系。需求分析阶段使用ERD来描述现实世界中的对象。ERD只关注系统中数据间的关系,而缺乏对系统功能的描述。如果将ERD与DFD两种方法相结合,则可以更准确地描述系统的需求。
在面向对象分析的方法中通常使用Use Case来获取软件的需求。Use Case通过描述“系统”和“活动者”之间的交互来描述系统的行为。通过分解系统目标,Use Case描述活动者为了实现这些目标而执行的所有步骤。Use Case方法最主要的优点,在于它是用户导向的,用户可以根据自己所对应的Use Case来不断细化自己的需求。此外,使用Use Case还可以方便地得到系统功能的测试用例。
传统方法:(过程+实体)
把系统看作一个过程的集合体。
过程与数据实体交互。过程接受输入并产生输出。
OO方法:(对象+消息)
把系统看成是一个相互影响的对象集。
对象之间通过发送和响应消息进行交互。
从过程到OO不是简单地一个升级。
传统方法强调“过程模型+实体模型”。
OO方法强调“对象模型+对象交互”。
不可能将传统方法的思维应用于OO方法中。
传统方法用“数据流图+数据字典”来描述系统需求。
数据流图包括外部实体、过程、数据流和数据存储等DFD部件。
数据字典则是对DFD部件的定义,包括过程描述、数据流定义、数据元素定义和数据存储定义。
OO方法用5种图来定义系统需求:类图+用例图+协作图+顺序图+状态图。
这些图相互联系,有时并不是这些图都要用到。
‘陆’ 用例分析的介绍
用例分析是从用例模型到分析模型的过程,是需求与设计之间的桥梁。用例分析把系统的行为分配给分析类,让分析类交互完成系统的行为。
‘柒’ 用例模型的介绍
用例模型是系统既定功能及系统环境的模型,它可以作为客户和开发人员之间的契约。用例是贯穿整个系统开发的一条主线。同一个用例模型即为需求工作流程的结果,可当作分析设计工作流程以及测试工作流程的输入使用。
‘捌’ 用例模型的用途说明
可能与该系统交互的用户和任何其他系统都是主角。由于主角代表了系统用户,它们协助界定系统并提供十分明确的系统用途说明。编写用例依据主角的需求来进行。这样就确保该系统成为用户期望得到的系统。 主角和用例都是通过将客户需求及潜在用户当作重要的信息查找到的。找到这些用例和主角后,应对它们作简要说明。在详细说明这些用例之前,客户应复审该用例模型以核实所有的用例和主角都已经找到,并且它们可以提供客户所需要的东西。
在迭代开发环境中,您可以选择用例的子集以便在每个迭代中详细描述。另请参见活动:确定用例的优先级。
主角和用例找到后,需要详细说明每个用例的事件流。这些说明指出系统与主角交互的方式以及在各个独立用例中系统执行的有关操作。
最后,对已完成的用例模型(包括用例说明)进行复审,开发人员和客户使用该模型对系统应执行的操作达成一致意见。 用例模型退化导致系统功能分解的情况并不罕见。为避免发生这种情况,必须注意以下故障现象:
“小”用例,即对事件流的说明只有一个或少数几个句子。 “许多”用例,即用例的数量有好几百,而不是好几十。 用例名的构造类似于“根据这一特定数据执行本操作”或“利用这一数据执行本功能”等。例如,“在 ATM 机上输入个人识别号”不应建模为 ATM 机的一个单独用例,原因是没有人会使用系统仅执行这一操作。用例是一个完整事件流,它可以产生对主角有价值的东西。
为避免功能分解,您需要确保该用例模型有助于回答诸如以下的问题:
系统的环境是什么? 为什么要建立系统? 用户在使用系统时希望获得什么? 系统将给用户创造什么价值? 不难发现,用例是一个很好的获取系统功能性需求的方法。但是对于非功能性需求,情况又如何呢?什么是非功能性需求,可以在何处获得它们?
非功能性需求通常分为可用性需求、可靠性需求、性能需求以及可替换性需求(另请参阅概念:需求)。它们通常是指定需要符合任意法律法规要求的需求。它们也可以是由于所使用的操作系统、环境平台、兼容性或所采用的任何应用标准等问题产生的设计约束。通常,任何不允许有一个以上设计选项的需求都可以认为是一个设计约束。
许多非功能性需求适用于一个单独的用例,并且可以在该用例的特征内获得这些需求。在这种情况下,这些需求可以在用例的事件流内获取,或者作为用例的一个特殊需求来获取(请参阅指南:用例)。
示例:
在回收机系统中,返还储存项用例的一个特定非功能性需求是:该机器识别储存项的可靠性必须高于 95%。
通常,功能性需求适用于整个系统。此类需求可以在补充规约中获得(请参阅工件:补充规约)。 示例:
在回收机系统中,一个适用于整个系统的非功能性规约是:
机器每次只允许一个用户使用。 学习如何确定用例应该在哪个明细级别上“开始和结束”是一件比较困难的事情。特征和用例开始于何处,而用例结束和设计开始又在什么地方?我们通常说,用例或软件需求应该规定系统做“什么”而不是“如何”做的问题。以下图为例:
一个人的终点是另一个人的起点。
根据个人背景,您可以使用不同的环境来确定您对“什么”以及“如何”的理解。当决定是否应该将某个细节摈弃于用例模型之外时,需要仔细考虑这一问题。 具体用例和抽象用例之间存在一个区别。具体用例由主角来启动,并且构成一个完整的事件流。“完整”意味着该用例的一个实例执行由主角调用的全部操作。抽象用例本身从来不会被实例化。抽象用例包括在(请参阅指南:包含关系)其他用例中,扩展到(请参阅指南:扩展关系)或泛化关系(请参阅指南:用例泛化关系)其他用例。在启动一个具体用例时,也就创建了该用例的一个实例。这一实例还展示了由其关联关系的抽象用例指定的活动。因而,从抽象用例中无法创建单独的实例。
由于主角在系统中“看见”和启动的是具体用例,因此这两种用例之间的区别非常重要。
表明一个用例为抽象用例时,可以将其名称格式设置为斜体。示例:
“创建任务”用例包括在“注册单”用例中“创建任务”用例是一个抽象用例。
在库房管理系统中,“创建任务”抽象用例包括在“注册单”用例中。启动“注册单”用例后,将创建一个注册单实例。该实例除了遵循注册单的事件流之外,它还遵循在所包含的用例“创建任务”内说明的事件流。“创建任务”本身从来不被执行,但始终作为“注册单”(或其他任何包含“创建任务”的用例)的一个部分。因此,“创建任务”是一个抽象用例。 构建用例模型有三个主要的原因:
使用例更易于理解。 将在许多用例内说明的公有行为分离出来。 使用例模型更易于维护。
然而,构建模型并不是首先要做的事情。在您对用例的行为有更深入的了解(而不是一句话简要说明)之前,千万不要构建该用例。您至少需要为该用例的事件流建立一个分步说明大纲,确保您的决策是建立在对该行为有精确而充分的理解基础之上。
有三种关系可以用于构建用例。您可以使用这些关系来分析出用例部件,这些部件可以在其他用例中复用,或者作为该用例的特例或选项。表示修改的用例称为附加用例。被修改的用例称为基本用例。
如果基本用例中有一部分功能,该用例的执行与否由它的结果唯一决定,而不是由产生该结果的方法来决定,则可以将这一部分功能分离出来,放到一个附加用例中。采用包含关系,可以将附加用例显式插入基本用例中。另请参见指南:包含关系。
如果基本用例的一部分是可选的,或对于理解该用例的主要目的来说不是必需的,那么您可以将这部分分离出来,形成一个附加用例,以简化基本用例的结构。利用扩展关系,可以将附加用例隐式插入基本用例中。另请参见指南:扩展关系。
如果用例在行为和结构上具有共同点而且在目的上又很相似,则可以将它们的共同部分分离出来,形成一个基本用例(父用例)。而附加用例(子用例)可以继承该父用例。子用例可以在从父用例继承的结构中插入新的行为或修改现有的行为。另请参见指南:用例泛化关系。
您可以使用主角泛化关系来显示主角之间的特化情况。另请参见指南:主角泛化关系。
示例:
以订单管理系统的用例模型部分为例进行说明。
由于他们具有略微不同的特征,因此将普通客户从 Internet 客户中分离开来是非常有用的。然而,因为 Internet 客户的确显示了一个客户具有的所有特征,所以您可以说 Internet 客户是客户的一个特例,并且能够通过主角泛化关系来指示。
在本图中,具体用例分别是“电话订购”(由客户主角发出)和“Internet 订购”(由 Internet 客户发出)。这些用例都是更普通的“??一个抽象用例。“请求目录”用例代表一个可选行为段,它不是“订购”用例主要目标的组成部分。它已经被分离出来,形成了一个抽象用例,用于简化“订购”用例。“提供客户数据”用例是一个已分离出的行为段。它之所以被分离出来,是因为它是一个独立功能,只有它的结果才能影响“订购”用例。“供给客户数据”用例还可以在其他用例中复用。“请求目录”用例和“供给客户数据”用例在本示例中都属于抽象用例。
本用例图显示订单管理系统的用户模型部分。
下表显示了三个不同用例关系之间更详细的比较:
为达到更易于理解的目的,组织用例模型的另一个方法是对用例进行分组,形成多个包。用例模型可以组织为一个有层次的用例包结构,而主角或用例是该结构中的“树叶”。另请参见指南:用例包。本图显示用例模型的分层结构。箭头表示可能存在所有权关系。 用例模型 的调查说明应该: 声明哪些是系统的主要用例(系统建立的原因)。 总结有关系统的重要技术实际情况。 指出系统定界 - 系统将不执行的操作。 概述系统的环境,例如目标平台和现有的软件。 描述在该系统中正常执行用例的任意序列。 详细说明用例模型未处理的功能。 示例: 以下是关于回收机的用例模型的调查说明示例: 本模型包括三个主角和三个用例。主要用例是“回收项”,它说明回收机的主要用途。 支持用例有: “打印日常报告”,操作员可以使用它获得关于已经回收多少项目的报告。 “管理储存项”,操作人员可以使用它来变更某个储存项类型的退款金额,或增加新的储存项类型。
‘玖’ 业务建模的用例模型
业务用例模型(business use-case model),在RUP中定义为:
业务用例模型是说明业务预期功能的模型。作为一个核心输入模型,业务用例模型用于确定组织的各个角色和可交付工件。
从业务用例模型的定义可以看出,它是企业最核心,最概括的业务说明。它主要是由业务用例和业务主角构成的,其主要目的是说明客户和合作伙伴是如何开展业务的,它描述业务的主要方式是通过业务用例的方式。下图为RUP中业务用例模型的图示。
从图中我们也可以很清楚的看出业务用例模型包括一组的业务用例。这是因为企业中的业务通常都会由多个的业务用例的多个实例构成。这些业务用例形成的企业工作流程可能会由业务主角所引发,也可能会由业务规则②所引发。
②业务规则(Business Rules):业务规则是必须遵守的政策或条件的声明。
业务用例模型实际上就是企业经营业务的一种描述,为了建立完整、准确的企业用例模型,应该将注意力专注于企业的业务做了些什么事情,而不应该集中于如何做。虽然这样可能会产生一些业务用例相冲突,相重复的情况,但是RUP的思想在于迭代,这项工作完全可以在接下去的迭代周期内完善。
业务用例模型是和企业业务最贴近的计算机模型。它的很多思想和企业日常经营如出一辙。在企业的日常活动中,业务的种类可能有很多种。在一些讲述ERP思想的文章中,通常会强调三类:
一种是和主营业务密切相关的工作,例如银行的营业部、信贷部、押汇部等。这种工作通过人的劳动,将一种资源转变为另一种资源,产生价值。
一种是管理型的工作,例如公司的管理层,财务部门等。这种工作本身并不产生价值,但是它通过指导、管理、检测第一种工作,加大第一种工作的产出价值。
还有一种称为支持工作,例如系统管理、安全等。它并不是很重要,具有支持其他工作的性质。
业务模型同样可以使用这种分类。通过这种分类,可以更好的把握核心业务用例,为下一步的工作打好基础。
有很多业务用例是由业务主角触发的,RUP中也把和业务主角有关联关系的业务用例称为核心业务用例(Core Business Use Case)。这强调了构建业务模型的目的是为了提供以用户为中心的服务。这也是我们建立业务用例的时候应该注意的。
当然,有时候业务用例的触发是为了产生用户需要的结果。例如企业的市场调查行为就不是由业务主角触发,而是企业积累了大量用户请求的结果。而对于管理型、支持型的,不直接和业务主角的客户类发生联系,但是也有其特定的业务主角,如管理型的业务用例需要和董事会为发生联系,支持型的业务用例可能和供应商发生联系。
在建立了基本的业务用例模型之后,对此模型进行精化是非常有必要的,这时候,在上一章中我们介绍的用例的扩展关系和使用关系就有了用武之地。除了这两种关系,还有一种新的关系。
业务建模中使用关系
泛化关系(Generalization):根据我的理解,可以把它看作我们比较熟悉的继承关系很相似的一种关系。Generalization一词含有一般化、概括的意思。它是一个相对抽象的词。虽然它和继承关系非常相似,但是它们在使用环境和产生目的方面都有相异之处。下图描述了四个业务实体之间的泛化关系: 当你去麦当劳的时候(不要误会,我并不是很经常去的),会选择麦香鸡汉堡、麦香鱼汉堡或是吉士汉堡。但是分别对这三种汉堡建立业务实体就非常没有意义。所以可以将它们概括为汉堡这个业务实体。同样的道理,企业的业务流程中也可以概括出一些共有的属性和行为。为了避免多次说明同一个工作流程,您可以将共有的行为放在一个单独的业务用例中。称为父用例,执行子用例的用例实例将遵循父用例的事件流,同时插入附加行为或修改在子用例事件流中定义的行为。
方法的选择
以上的原理我采用了UP的方法。但是除了UP方法,还有XP、FDD等方法。所以在做业务建模的时候,也要根据不同的方法选择适当的工件。例如素材和功能。方法的好坏并不是我们这片文章讨论的重点,我会在另一篇文章中讨论方法。再一次需要强调的是,上面讨论的RUP的工件只是为了学习,所以才定义了比较复杂的工件,区分了它们之间的区别。但是在实际中,并不需要这么多的工件,那只会使你的项目涉众和开发人员糊涂。这些工件的区别只要在你心中就可以了。
‘拾’ 用例的程序设计·用例
那么,到底什么是Use Case呢?在UML的文档中,Use Case的定义是:在不展现一个系统或子系统内部结构的情况下,对系统或子系统的某个连贯的功能单元的定义和描述。有点拗口,对吧?其实Use Case就是对系统功能的描述而已,不过一个Use Case描述的是整个系统功能的一部分,这一部分一定要是在逻辑上相对完整的功能流程。在使用UML的开发过程中,需求是用Use Case来表达的,界面是在Use Case的辅助下设计的,很多类是根据Use Case来发现的,测试实例是根据Use Case来生成的,包括整个开发的管理和任务分配,也是依据Use Case来组织的。
对不同的Actor来说,他要使用系统的某项功能也不同。所以,在识别和分析Use Case时,我们要对每个Actor逐一进行。对于ToDo User,我们可以轻易的识别出两个Use Case:Add Task 和 Remove Task。ToDo User主动使用这两个Use Case所描述的系统功能,所以在我们的Use Case图上,ToDo User和这两个Use Case的关系是用从ToDo User发出的箭来表示的。对于FileSystem,我们识别出的也是同样的两个Use Case,不过这次箭头从Use Case指向FileSystem,表示FileSystem是被动的。
Use Case可以用很多方式来描述,我们可以用自然语言(英语,汉语,随您的便),可以用形式化语言(哇!太酷了吧!),也可以用各种图示。在UML中,通常用两种图来描述Use Case,它们就是顺序图(Sequence Diagram)和协作图(Collaboration Diagram)
Use Case 由以下元素组成:
名称
简单描述
事件流
关系
活动图和状态图
Use Case 图
特殊需求
前条件
后条件 1.1 参与者和用例从用户的角度来看,他们并不想了解系统的内部结构和设计,他们所关心的是系统所能提供的服务,也就是被开发出来的系统将是如何被使用的,这就用例方法的基本思想。用例模型主要由以下模型元素构成: 参与者(Actor)参与者是指存在于被定义系统外部并与该系统发生交互的人或其他系统,他们代表的是系统的使用者或使用环境。 用例(Use Case)用例用于表示系统所提供的服务,它定义了系统是如何被参与者所使用的,它描述的是参与者为了使用系统所提供的某一完整功能而与系统之间发生的一段对话。 通讯关联(Communication Association)通讯关联用于表示参与者和用例之间的对应关系,它表示参与者使用了系统中的哪些服务(用例),或者说系统所提供的服务(用例)是被哪些参与者所使用的。 以银行自动提款机(ATM)为例,它的主要功能可以由下面的用例图来表示。ATM的主要使用者是银行客户,客户主要使用自动提款机来进行银行帐户的查询、提款和转帐交易。 通讯关联表示的是参与者和用例之间的关系,箭头表示在这一关系中哪一方是对话的主动发起者,箭头所指方是对话的被动接受者;如果你不想强调对话中的主动与被动关系,可以使用不带箭头的关联实线。在参与者和用例之间的信息流不是由通讯关联来表示的,该信息流是缺省存在的(用例本身描述的就是参与者和系统之间的对话),并且信息流向是双向的,它与通讯关联箭头所指的方向亳无关系。
1.2 用例的内容用例图使我们对系统的功能有了一个整体的认知,我们可以知道有哪些参与者会与系统发生交互,每一个参与者需要系统为它提供什么样的服务。用例描述的是参与者与系统之间的对话,但是这个对话的细节并没有在用例图中表述出来,针对每一个用例我们可以用事件流来描述这一对话的细节内容。如在ATM系统中的提款用例可以用事件流表述如下:
1. 用户插入银行卡 2. 输入密码 3. 输入提款金额 4. 提取现金 5. 退出系统,取回银行卡 但是这只描述了提款用例中最顺利的一种情况,作为一个实用的系统,我们还必须考虑可能发生的各种其他情况,如银行卡无效、输入密码错、用户帐号中的现金余额不够等,所有这些可能发生的各种情况(包括正常的和异常的)被称之为用例的场景(Scenario),场景也被称作是用例的实例(Instance)。在用例的各种场景中,最常见的场景是用基本流(Basic Flow)来描述的,其他的场景则是用备选流(Alternative Flow)来描述。对于ATM系统中的提款用例,我们可以得到如下一些备选流:
备选流一:用户可以在基本流中的任何一步选择退出,转至基本流步骤5。
备选流二:在基本流步骤1中,用户插入无效银行卡,系统显示错误并退出银行卡,用例结束。
备选流三:在基本流步骤2中,用户输入错误密码,系统显示错误并提示用户重新输入密码,重新回到基本流步骤2;三次输入密码错误后,信用卡被系统没收,用例结束。 … 通过基本流与备选流的组合,就可以将用例所有可能发生的各种场景全部描述清楚。我们在描述用例的事件流的时候,就是要尽可能地将所有可能的场景都描述出来,以保证需求的完备性。
1.3 用例方法的优点用例方法完全是站在用户的角度上(从系统的外部)来描述系统的功能的。在用例方法中,我们把被定义系统看作是一个黑箱,我们并不关心系统内部是如何完成它所提供的功能的。用例方法首先描述了被定义系统有哪些外部使用者(抽象成为Actor),这些使用者与被定义系统发生交互;针对每一参与者,用例方法又描述了系统为这些参与者提供了什么样的服务(抽象成为Use Case),或者说系统是如何被这些参与者使用的。所以从用例图中,我们可以得到对于被定义系统的一个总体印象。 与传统的功能分解方式相比,用例方法完全是从外部来定义系统的功能,它把需求与设计完全分离开来。在面向对象的分析设计方法中,用例模型主要用于表述系统的功能性需求,系统的设计主要由对象模型来记录表述。另外,用例定义了系统功能的使用环境与上下文,每一个用例描述的是一个完整的系统服务。用例方法比传统的SRS更易于被用户所理解,它可以作为开发人员和用户之间针对系统需求进行沟通的一个有效手段。 在RUP中,用例被作为整个软件开发流程的基础,很多类型的开发活动都把用例作为一个主要的输入工件(Artifact),如项目管理、分析设计、测试等。根据用例来对目标系统进行测试,可以根据用例中所描述的环境和上下文来完整地测试一个系统服务,可以根据用例的各个场景(Scenario)来设计测试用例,完全地测试用例的各种场景可以保证测试的完备性。 Ivar Jacobson在1967年定义爱立信AXE系统的构架时开始书写使用场境usage scenarios。
二十世纪八十年代中期Jacobson花了很多精力来思考过去十多年的工作方法。他造了一个术语anvendningsfall,大意是“使用情况”(situation of usage)或用况(usage case)。但当用英文出版的时候,他发现“useage case”在英语里说不通,所以写作用例“use case” 用例是短文
用例可以是一个场景,包括动作和互交。
用例可以是一组场景,描述不同场景下的行为。这种书写格式可以在任何时候描述有变体的行为,例如黑盒需求,业务流程,系统设计说明。
用例里不要有系统设计
用例里不要有界面设计
用例里不要有特性列表
用例里不要有测试
用例应该描述行为需求
用例的主场景不要超过九步。可以在适当的层次上得到子目标和移除设计说明。
用例的最大价值不在于主场景,而是在于备选行为。主场景可能只占用例长度的四分之一到十分之一。 Use Case具有一个基本事件流(可称为理想路径)、多个例外流,包括:
基本变化
特殊情况
处理错误情况的异常事件流 Use Case 说明书应包括以下内容:
功能描述
可用性
可靠性
性能
可支持性
设计约束 试图决定Use Case的大小是一个很有趣的话题,处理这件事的一个方法是将Use Case的大小跟它的意图和范围关联起来,对于一个真正大的范围来说,一个Use Case并不要在一个系统中处理那么多,但这些系统都用于同一商业领域,称为Business Use Case,它把整个公司看作一个黑盒和Actor关于公司目标的说明。这些Business Use Case的场景不允许假定任何公司内部的结构,一个客户将向公司下一个定单而不是客户服务部门。
对于系统发展而言,Use Case的范围限制一个单一的系统,这是Use Cases最通常的形式,我们称之为System Use Case,它把整个系统看作是一个黑盒,它不指定任何内部结构并且仅受限于问题域的语言描述。
Use Cases的另一范围是设计子系统和系统内部组件的,称为Implementation Use Cases,它把组件看作一个黑盒,并且这些Actors是区分它的成员。例如:可能会用Implementation Use Cases去说明应用系统中email组件的需求。
给出了这些分类,关于Use Case的大小话题变得容易了,设计这些项的范围来调整整个大小。帮助系统设计者,每个Use Case只描述没有大的分支的行为的单个线索。违背这个规定,Use Case看起来通常是不准确的或含糊的,作为测试说明的资源和参考,它也是很难使用的。 Use Cases的好处是一些情节能用不同程度的正规化的文字说明。每个情节涉及Use Cases中单一的途径,细节是条件组。
不正规的文本描述也能使用,不过当条件较多和可能失败的情况下它们很难跟随下去。开始试图理解需求时,不正规的叙述风格也是非常有用的,然而随着Use Cases的进展,使用更加正规的机制去说明Use Cases才是有用的。
下面是客户对Use Case“下定单”的粗略概略:
“确定客户,找出需要的并且仓库里还有的物品并检查客户信用额是否够用”
结构化叙述的格式已经被证明是非常有效的。这个格式所做的事是描述每一个情节的行为者:目标语句对顺序的叙述。在这个顺序中,每一个行为者:目标的语句对都假设前一个的目标是成功的,右面是一个简单的范例:
Use Cases认为我们正在设计的系统是一个单一的黑盒,根本没有任何内部结构被记录下来,并且它被认为是一个情节产生的目的及对应单一的行为者(Actor)。这些Use Cases没有表示任何关于系统内部的东东,只是表示系统将达到什么样的目标及由什么(人或其它系统)操作和负责。 Use Cases已经得到越来越广泛的应用,它与其它需求捕获技术相比,它成功的原因在于:
1 Use Cases把系统当作一个黑盒
2 Use Case 使在需求中看到实现的决定变得更加容易
最后一点源于第一点的补充,一个Use Case没有指定任何这些需求相关的系统的内部结构,所以说,如果这个Use Case中陈述了提交改变到定单数据库、显示结果到Web页面等的话,那么内部结构是显而易见的,并造成对设计的潜在约束。
为什么这些需求不指定内部结构的原因是,说明的内部结构给设计者带来了额外的约束,没有这些约束设计者们能更自由地建立一个正确实现客观可见行为的系统,并存在出现突破方案的可能性。 这里是Use Cases的图形符号描述,UML中一个单一的Stick-Man符号标示角色(Actor),用椭圆标示Use Cases,如这些图对于你想看到Use Cases之间如何关联的大图和获得系统上下文的大体描述来说是非常重要的。
Use Cases图没有显示不同的场景,它们的意图是显示角色和Use Cases之间的关系。所以Use Cases图需求用结构化叙述文本来补充。UML提供一些可供选择的图来显示不同的场景,这些常规的图形有交互图、活动图、顺序图、状态图等(本文暂不讨论这些图)。使用这些图的主要缺点是它们不象文本一样是紧密的,但它们能用于给出Use Case的整体感觉。 是否每个Use Case 都包括至少一个actor?
是否每个Use Case 都独立于其他Use Case?
是否每个Use Case 都有一个简单的行为或事件流?
是否每个Use Case 都有一个唯一的、直观的、可扩展的名称,使它不至于在后期被混淆。
用户是否容易理解Use Case 的名称和描述。 Use Case模型显示系统中的Use Case与Actor 及其相互关系。其评价标准有:
Use Case 模型是可理解的吗?
通过对Use Case 模型的研究是否能对系统功能有一个清晰的概念。
所有的actor都定义了吗?所有的功能需求都满足了吗?
Use Case 模型是否存在多余的行为。
从模型到Use Case包的划分是否是恰当的。 由于具有简单的图形符号、易理解的自然语言说明书,Use Case在文档系统和软件需求领域成为一 项越来越受欢迎的技术。Use Case对开发小组极具吸引力,即使小组成员对正式的需求文档没有经验,但这些简单性却具有欺骗性,即使项目小组在开始使用Use Case 时没有任何麻烦,当他们将其应用于大项目时常常会遇到许多同样的问题。
1 使用 use case 十大误区
1. 系统的boundary 没有定义或经常改变;
2. 从系统观点而不是actor观点来定义Use Case;
3. Actor的名称不一致;
4. Use Case 定义过多;
5. Use Case 和actor之间的关系象蜘蛛网一样错综复杂;
6. Use Case的说明太长;
7. Use Case的说明不清楚;
8. Use Case没有正确的描述功能需求;
9. 用户无法理解Use Case;
10. Use Case 无法正常结束。
2 如何避免以上问题
清楚的确定系统的boundary.
简单来说,系统的boundary就像一个加了标签的盒子,actor在盒子外,而Use Case在盒子内。我们称之为系统的这个盒子究竟是什么呢?一个计算机系统?一个应用系统?或一个完整的企业?…Use Case 可以用来合理地描述任意系统。但一次只能用来描述一个系统,在一个系统中恰当定义的actor和Use Case用于另一个不同的系统中就会出现错误。
使用标准模板书写Use Case 说明书
Use Case 图形符号已经被标准化并作为对象管理小组UML的一部分,但自然语言的Use Case 说明书还没有被标准化。为了成功书写Use Case 说明书,我们需要一个标准模板来保证Use Case 的一致性。
关注actor的真正目的,从actor的观点而不是系统观点来命名Use Case
面向Use Case 的需求与传统的功能性系统需求之间最显着的区别在于actor ,以面向Use Case的观点,系统存在是由于actors 要通过该系统实现某些目标,actor与系统进行交互来实现其目标,我们将这些交互行为定义为Use Case 。
不要将Use Case 说明书与用户接口设计相混淆
现在有一种很流行的观点:由于Use Case 是actors 与系统之间的交互,所以将所有的用户接口设计图放在Use Case说明书中是一个好办法。初看时,这的确很有用,因为它将在说明书中描述的actor/系统之间的交互行为以图的形式表示出来,非常直观。但是这样做的负面影响却远远大于其好处,用户接口设计可能会随着时间而改变,我们不应该让系统需求依赖于用户接口设计,相反地,用户接口设计应该满足Use Case 需求。如果我们将用户接口设计置于Use Case 说明书中,当需求需要被认可和定为基线时,很自然地,这些设计元素可能仍然在改变,这就使得用户接口设计成为不完整的、不正确的和/或不一致的。
将用户接口设计置于Use Case 说明书还会出现另一个问题,为了在Use Case 之间和接口之间建立一对一的通信,我们会选择反映用户接口的Use Case块而不是反映用户目标的Use Case 块,这样,为了表达一个完整的用户目标,我们使用交互Use Case 关系,将不同的、基于用户接口的Use Case 联接起来,结果在Use Case 模型中,我们得到了一幅类似蜘蛛网的关系图。实际上,这副图是用户接口说明图,虽然它在系统文档中是很重要的一部分,但他属于用户接口设计文档,而不是Use Case 需求文档。
实现用户接口和Use Case 交互之间的松散耦合
松散耦合是比较合适的,低逼真度的用户接口图有助于理解Use Case ,但要注意不要过度的将基本交互与用户界面机制相连,用户界面很有可能会改变。在功能说明书中,要注意actor做些什么(如提交请求)而不是交互是怎样完成的(如双击提交按钮)。
不要在Use Case 和用户接口之间建立通信
试图在Use Case 和用户接口之间建立通信可能会存在潜在的、不正确的功能操作。Use Case 不仅与只能访问某个接口的actor相联,而且与那些能够更新该接口的actors相连(这可能是例外流),结果就造成了不正确的功能操作。我们应该在基于实际用户目标和功能操作的基础上拆分Use Case ,而不是在基于用户接口的基础上组合Use Case ,只有这样才能得到正确的Use Case 模型。
回顾Use Case 模型和Use Case 说明书,如果你不能防止所有的误区,你应该尽早认识问题并确定问题
这个观点并不是什么新东西,有关代码检查的经典算法已有大约25年历史了,但怎样将其应用于Use Case 呢? 首先,回顾Use Case 模型,回顾一下Use Case 的简单说明(Use Case 名称、目标、简单描述)。这项工作应在绘制草图时尽早执行,并在写详细的Use Case 说明书之前完成。接着是回顾Use Case 草图,保证图是正确的,并且详细的Use Case说明书是完整的。最后是正式回顾最终的Use Case 图和Use Case 说明书。
我们发现这种三阶段式回顾比单一的宇宙大爆炸式回顾有效,在我们花大量的时间写说明书之前,Use Case图中存在的许多实质性问题可以被发现,这种方法减少了当需求改变时需要做的重复工作。 主要行为者(Actor)和Use Case之间没有连结
一些情况下,从Use Case中取值的行为者(Actor)和积极参与这个Use Case的行为者(Actor)之间没有清晰的连结。如:财务主管能成为“发票确认”的行为者(Actor),但他未必是创建发票的人。这不是什么问题,这个Use Case仍然是正确的,它正说明行为者取值和设计的系统的范围外的Use Case发生的初始化之间的关系。主要行为者是有用的,因为这个人扮演的角色是当你说明Use Case时需要跟他说的人。
情节步骤不需要连续
情节中步骤顺序的情况是没问题的,这里有一些机制去突出可能的并行步骤。在UML中活动图是首选的机制,通过非正式地看Use Case的情节你可以注意到可能的平行步骤;可以看Use Case内一些邻近的步骤;也可以有相同的行为者(Actor)对步骤负责。之前我们举过的例子里,确认数量和确认信用额可能是平行的。有时候在Use Case的说明文档中标记这些可能的平行步骤是有用的。
Use Cases的大小
当开始做Use Cases的时候有个很显然的危险就是它要么有很多步骤要么就很少步骤。如果在Use Case中有超过15个步骤,它可能包含一些实现明细。如果它只有非常少的步骤则检查它的目标是否是达到一个没有很多分支的活动的单一线索。
较少的人类行为者(Actor)
如果Use Case有较少的人类行为者,而大多数行为者是其它系统,通常的做法是修改这个Use Case。寻找系统必须做出反映或公认的事件胜过会见这些行为者。
需求捕获和系统复杂性
总而言之,这些情节捕获到系统复杂度的同时行为者:目标语句对容许大的系统以相对压缩的格式说明。Use Case的格式的作用是用户和开发者能标志出行为者,然后确认这些行为者工作职责对应(或不对应)的目标,代替一个大的很难读的功能规格说明书。
仅仅这样,用户和开发者就有足够的兴趣进而研究那些情节的细节。
系统不仅仅有应得的功能性需求
一些Use Cases并没有捕获所有的客观需求,仅仅是捕获了系统怎么用的那些功能性需求。然而还有许多方面的需求需要去捕获的。其中有的非功能性需求使用关联以至于也能隶属于个别的Use Case,如性能需求和系统容量的需求。另外的一些不是关联的而是要单独地去捕获,它们是以下的需求:
· 系统范围
· 系统用户的目标
· 用户界面原型
· 一般规则
· 约束
· 算法
运行时期和建立时期的需求比较
一个重要的因数要记住,就是系统的赞助者是大过用户团体的。系统中有许多的风险承担者,Use Cases仅仅捕获其中一些风险承担者的需要,具体说,Use Cases仅仅捕获系统运行时期的需求而忽略做为系统开发组织的风险承担者的需求,开发组织最有兴趣的是对建立时期需求的描述。
运行时期需求包括:系统范围、用户组织对产品的期望和目标、Use Cases、其它非功能性需求。
建立时期需求包括:减少开发成本、较少的变更处理、现存组件的重用。
建立时期的需求可以部分的由Use Cases把握。但许多方面是需要由开发组织的处理的。
· 项目范围和目标:项目必须提交什么。(和系统范围的区别是它提交的是所有项目的东西)
· 增长性和变更请求:这些可以在捕获为常规Use Cases格式中的“Change Cases”
· 开发负责人的约束:包括标准、习惯、工具、品质度量标准、品质保证原则、及品质保证的习惯。 Use Cases首先用于需要响应客观事件的系统。它们能用于提供了一个有很容易理解的目标的清楚的行为者的环境。当结果不可定义或不清晰时不能用Use Cases。意思是如果目标成功或目标失败不能有一个明确的定义,那么Use Cases不能用来捕获需求。
然而说到这,现在大部分对象方法都使用Use Cases。因为Use Cases被证明是捕获需求的非常有效的机制。 Use Case 是系统提供的功能块,换句话来说Use Case演示了人们如何使用系统。通过Use Case观察系统,能够将系统实现与系统目标分开,有助于了解最重要的部分――满足用户要求和期望,而不会沉浸于实现细节。通过Use Case 用户可以看到系统提供的功能,先确定系统范围再深入开展项目工作。