统一建模语言UML基础专题之UML简介及用例图

在进行对象建模、面向对象分析和设计的过程中,需要使用建模语言来描述分析的过程和结果。统一建模语言(UnifiedModelingLanguage,UML)是为了这个目标而设计的一种标准通用的设计语言。任何想要真正理解面向对象编程思想的人,都需要具备一定的UML知识。

在这个专题中我们会陆续介绍统一建模语言UML中的用例图(usecasediagram)、类图(classdiagram)、对象图(objectdiagram)、序列图(sequencediagram)、状态图(statechartdiagram)、活动图(activitydiagram)、组件图(componentdiagram)和部署图(deploymentdiagram)。

统一建模语言UML简介

UML不是一种方法学,而是一种描述语言,它提供了多种类型的模型描述图(diagram),当在某种给定的方法学中使用这些图时,人们就能更容易理解和交流设计思想。UML的图可划分为如下三种类型。

—静态图(staticdiagram):描述了那些不发生变化的软件元素的逻辑结构,描绘了类、对象、数据结构及其存在于它们之间的关系。

—动态图(dynamicdiagram):展示了在运行期间的软件实体的变化,描绘了执行流程、实体改变状态的方式。

—物理图(physicaldiagram):显示了软件实体的不变化的物理结构,描绘库文件、字节文件、数据文件等,以及存在于它们之间的关系。

下表说明了三类图中最常用的一些UML图,以及它们适用的软件开发阶段。

提示MicrosoftVisio可以用来方便地绘制UML图。VisualStudio2005的类关系图也可以显示类似UML的图,但是与标准的UML稍有不同。

统一建模语言UML用例图

用例(usecase)指的是系统的功能,它是系统某个功能的所有执行动作的集合。用例是从一个用户的观点来描述的。这个用户告诉系统去做一些特定的事情。一个用例捕获一个事件的可视化序列,这个事件是一个系统对单个用户的激励(stimulus)的响应过程。

动作者(actor)表示系统用户能扮演的角色(role)。这些用户可能是人,也可能是其他的计算机、一些硬件,或者甚至是其他的软件系统。对用例的唯一要求是,它们必须位于用例描述的系统部分之外,它们必须能刺激系统部分,并接收返回。

用例描述了当动作者之一给系统特定的刺激时的系统活动。这些活动用文本来描述。它描述了触发用例的刺激的本质,输入和输出到其他活动者,以及从输入到输出的活动。用例文本通常也描述每一个活动可能的错误和系统应采取的补救措施。

在用例图中,用椭圆来表示用例,并将用例的名称放在椭圆的中心或椭圆下面的中间位置。人形符号用来表示角色(用户)。角色和用例之间的关系使用简单的线段来描述,表示角色可以操作此用例。

在用例图中,用一个方框来表示系统的边界。所有系统用例都放在框内,所有动作者都位于框外。动作者和用例之间用直线相连。方框内的每一件事物都是系统的一部分,方框外的每一件事物都是系统的外部。用例图也可以表示方框内的系统用例之间的关系,最常见的是“使用关系”,用带箭头的直线来表示,箭头指向被使用的用例。还有一种关系是扩展关系,用来表示继承。

图6-2显示了一个用例图。用例图通常用于表达系统或者系统范畴的高级功能。在图中可以很容易地看出该系统所提供的功能。这个系统允许乐队经理查看乐队CD的销售统计报告及排行榜报告。它也允许唱片经理查看特定CD的销售统计报告和这些CD在排行榜的报告。这个图还告诉我们,系统将通过一个名为“排行榜报告服务”的外部系统来提供排行榜报告。

用例图不会列出系统不能完成的功能。下图所示的系统不能提供给乐队经理收听排行榜上不同专辑中的歌曲的方法,也就是说,系统没有引用一个叫做“收听排行榜上的歌曲”的用例。如果在用例图中提供清楚的、简要的用例描述,项目赞助商就能很容易地看出系统是否提供了必需的功能。

1.引言

“本系统的目标是制作出一个跨企业的信息平台,为目标公司的客户进行服务。这些服务分成很多的方面,比如提供给银行的公司财务情况查询,提供给生产厂商销售情况的报告。提供给销售的商场以及店铺货源的情况,提供给物流,安装服务公司送货以及安排信息。从中赚取提高销售效率,减少运输损耗的费用。设定目标公司为A公司,信息平台名称B系统。”

从上面介绍的内容来看,我猜B系统是一个类似于供应链应用的企业门户系统,这里所说的A公司好像是一家从事商品分销的企业。通过该门户,A公司可以有效地联系上家—生产商(供货商),下家—商场、店铺以及银行、物流公司、安装服务公司等客户或合作伙伴。

在讨论这个案例前,首先让我们重温一下什么是最外围用例(theoutermostusecases,根据Cockburn的定义改写):

对于每一个用例找到它仍能适用的最外圈的设计范围,针对该范围为它编写一个概要用例;对于一个将要设计的系统,我们通常可以找到一个更广的设计范围,而使主用角(PA,PrimaryActor)仍然处于该范围之外,如果不断扩大该范围,可以找到一个临界点,主用角就会被包含在当前的范围之内,这个临界点就是最外圈的范围;最外围用例是通过把同一个范围内具有相似目标的主用角合并到一起而创建出来的,它们把与这些用角有关的所有低层用例都汇聚到了一起。

如何获取最外围用例呢?Cockburn给了一些步骤建议:(1)从一个用户目标开始。(2)问“这个目标对主用角AA(最好在组织外部)提供什么服务?”,用角AA是我们想要收集用例的最终主用角。(3)找出最外圈的设计范围S,使得AA仍然在S之外,给S命名。(4)找出最终主用角AA在设计范围S中的所有用户目标。(5)找出AA对系统S的概要目标GG。(6)为GG编写出概要用例。这个用例就是我们要找的最外围用例,它将一些海平面(用户目标层)的用例维系在一起。

值得注意的是,这里Cockburn所说的“系统”S不一定都是指软件,它可能是软件系统(如B系统),也可能是业务系统(如A公司、企业、部门等)。在下面第2、第3小节中我将按照Cockburn的最外围用例定义来考察原文中的两个最外围用例,逐个分析存在的错误。用第1个例子说明以“操作人员”为主用角、最外圈范围为软件系统(B系统)的正确写法,用第2个例子说明以“客户”为主用角、最外圈范围为业务系统(A公司)的正确写法。

2.软件用例-业务管理

用例名称:最外围用例

错误分析:显然这不是一个正确的用例名称。建议改为“业务管理”,解释如下文。

简要说明:

A公司决定让其业务合作伙伴以及最终的用户通过互联网访问B系统以达到减少A公司本地人员的工作量以及提升工作效率的目的。B系统负责完成进销存业务、其它业务处理以及报表管理。一些系统维护人员还负责管理基础信息的认定与实现。包括四个用例:基础设置子系统,进销存子系统,其它业务处理子系统,报表子系统。

错误分析:首先,用例的名称、内容中不应该出现“子系统”这个术语,subsystem属于系统设计范畴。从业务介绍来看,操作人员主要进行“进销存、报表和其他业务”的处理,系统维护人员主要进行基础信息管理,所以这4个概要用例(风筝层)分属不同的PA。这两种角色在概要白云层似乎没有必要严格区分,所以我们把系统维护人员和操作人员合并成“操作维护人员”,并且把这4个用例合并成1个最外围用例“业务管理”,并在此处描述。

用例范围:跨企业信息平台主执行者(PA):客户

错误分析:从用例范围和基本流的内容看,这里的PA应该是“操作维护人员”(客户作为PA的最外围用例见第3小节)。

用例层次:白云(最高层次)触发事件:客户有购货的需求

错误分析:这里应该描述可以检测到的事件(动作、状态的改变等),我们怎么知道客户有购货的需求呢?正确的说法可能是:客户以各种方式请求服务。

主成功场景(基本流)·系统维护人员操作基础设置子系统维护基础设置的数据。·操作人员操作进销存子系统完成进销存业务。·操作人员通过报表系统分析查询业务结果。·操作人员通过其它的业务子系统完成对系统中的其它业务处理。(注,其它业务子系统包括财务资金等等子系统,将会子用例描述中强调)

小结:

从以上分析看,原用例存在着基本的概念错误,用例的主用角(PA)、范围和基本流的内容相互之间存在不一致的现象。这个最外围用例可以改写如下:

用例名称:

业务管理

范围:

B系统

层次:

概要/白云

主用角:

系统操作维护人员

触发事件:

基本流:

操作维护人员通过B系统可完成以下任务:1.基础信息管理。2.处理进销存业务。3.进行报表管理,查询、分析业务结果。4.处理其他业务(如财务资金管理)。[用例结束]

3.业务用例-客户服务

错误分析:显然这不是一个正确的用例名称,建议改为“客户服务”。

A公司决定让其业务合作伙伴以及最终的用户通过互联网访问B系统以达到减少A公司本地人员的工作量以及提升工作效率。B系统负责完成销售业务以及报告销售情况。一些系统维护人员还必须为客户和职员设置安全存取级别。包括四个用例:增加服务(A公司本地),增加服务(客户),报告业务情况,管理安全存取权限。

错误分析:这段话其实不太像用例简述。最外围用例应该从A公司向客户提供服务的角度来叙述,比方说,可以请求服务,查询业务销售报表等。在本例中我们进行黑盒业务建模,涉及到B系统和系统维护人员的内容,比如安全级别设置,不应在此处反映。

用例范围:跨企业平台

错误分析:我们选定了A公司的客户作为PA,那么按照最外围用例的定义,最大范围边界应为A公司而不是B系统。实际上这是一个业务用例(BusinessUseCase)。虽然客户也可以直接访问B系统,但是对于客户而言,B系统不是最大的范围。

客户服务

A公司/业务

客户

客户提出服务请求

4.总结

有人认为:“也许针对一个项目可以有很多‘正确的'最外层用例的设计方法。上面两种划分方式应该说只从最外层用例的角度来说都是正确的”。我不同意这种开脱的说法,针对1个项目抽取最外围用例实际上只有1种“最优解”。为什么?道理很简单,因为最外围用例是Cockburn提出的,他给出了找到最外围用例的步骤和方法,而这种方法是明确的、无二义性的。人们找错了最外围用例,多半是因为没有理解和掌握这套方法。

概括一下,原文主要存在以下错误:

1)由于用例的主用角、范围与基本流的内容不一致,导致那两个用例都不是真正的最外围用例。实际上,针对“客户”的最外圈范围是A公司,而针对“操作维护人员”的最外圈范围是B系统。

2)在用例的功能描述中出现了软件内部设计的内容,不符合需求提取、分析的要求。

一、用例基础

1.1用例简史

用例另一支主流派别代表人物AlistairCockburn(阿里斯代·寇本)上世纪90代初从亚克申那里学习了用例,随后通过十年认真广泛的实践对其进行了继承和发展。寇本于1995至1997年间提出了著名的“基于目标的用例”方法[2],他的方法和思想集中体现在《WritingEffectiveUseCases》(以下简称为WEUC)[1]中,以结构化/半结构化文本用例为中心是寇本方法的一大特色,该书可以说是迄今为止最为详细的一本用例教材,对于指导实践者如何写好文本用例具有很高的价值。

1.2用例定义

下面,先让我们从什么是用例开始讨论。亚克申定义[7]强调用例是系统执行的一个动作序列(注:这其中也包括与用户的交互),这些动作必须对某个特定的使用者(Actor)产生可观测的、有价值的结果。(注:Actor实质上是用户所扮演的一种角色)

那么到底什么结果叫“可观测、有价值”呢?虽然两种用例本质上是一致的,但亚克申定义对此没有明说,而寇本定义[1]则更加完善和明确。它首先强调用例是各种系统受益人(Stakeholder,又译“干系人”)之间的一种行为契约(注:行为包括对象的活动、动作和对象之间的交互等),建立契约的目的是为了达成某种目标,因此每一个用例及其名称实际上都应代表一个用户目标,这个目标是否得到真正满足正是判断我们抽取的某个用例是否“有价值”的关键。寇本还点出了要通过用例的具体执行来展现Actor的目标是如何实现或失败的,而一个用例其实就是多个在不同条件下执行并可能导致许多不同后续状态的情节(scenario,又译“场景”)的叠加,这就是用例结果的“可观测”。

因此综合起来,我们只要抓住这样几个关键词:目标、行为契约、行为(事件)序列(动作和交互)、情节、可观测、有价值,就可以比较准确地描述出用例的本质特征。

1.3用例的重要性

为什么用例如此重要?一言以蔽之,这是因为用例是一种普遍存在的客观现实,而实践证明,用例技术是迄今为止最为深刻、准确和有效的系统功能需求描述方法。

功能需求是指系统输入到输出的映射以及它们的不同组合[9],任何功能必然要通过外部环境与系统之间的交互才能完成,这不正是用例所要反映的内容吗?因此,我们可以在内容和形式上把用例和系统的功能需求等同起来,并且得出推论:只要是软件,必然都存在用例(虽然有时候不一定非要用某种具体的用例格式来描述),其中即包含数据流,也包含控制流,既包含消息发送和数据交换(交互),也包括活动/动作的执行以及状态的变迁。这些就是用例的本质(现象背后那个真实的、抽象的“胚”),而各种格式文本、UML图形(我们至少可以用4种UML动态图来描述用例)不过是用例的外部表现形式。所以,与其说亚克申博士发明了用例,还不如说亚克申博士早在20年前就发现了用例这种客观现实,并最终发明了用例表示和用例驱动软件过程的方法。

那么,什么情况下不太适合采用用例方法?主要有两种情况:(1)用户很少或没有,接口也很少,如科学计算/仿真软件、杀病毒软件、编译程序、内存管理程序等[9];(2)功能需求非常简单,非功能需求和约束占主导地位。显然,如今绝大部分的应用软件、系统软件,尤其像电信、银行、保险、税务、制造业、企业信息化等领域的复杂系统,都是符合用例适用条件的,这从一个侧面反映出用例技术的广泛适用性。请注意,即使在上面两种情况下也并不是说这些软件的用例就不存在了,而只是表明它们的功能需求很简明或不太重要,除用例之外可能还有更加适用的方法。

借此机会,顺便谈谈对usecase有关术语翻译的看法。

有的地方把usecase翻译成“用况”,即“使用的情况”之意,意思的确不错(usecase的另一种说法是“使用的方式”)!可我总感觉这个词比较突兀、拗口,类似的还有“用案”,把scenario叫作“案况”,大概这些词读起来不太符合大家的习惯(类似地,既然可以叫“用况”,为什么不能叫“用情”呢?),所以现在“用例”的叫法还是越来越多了。

其实“用例”这个译法还有个附带的好处,通过它我们很容易把原本就存在紧密联系的usecase和testcase(testcase来自于对scenario的分析,而scenario是用例的一次执行)从中文名称上也方便地统一起来。不过,这里我们需要做一个小小的改进。中文的“测试用例”到底是指testcase(带定语的名词词组)呢,还是指对用例进行测试(testingtheusecases,动宾词组)呢?显然这两者不易分辨,而且若“用例”和“测试用例”两个词同时出现在一啰个句子或一段话中,常常会让人感觉嗦和便扭。为了消除歧义,干脆以后把testcase都叫做“测例”,这样不但比以前的叫法更加简洁明了,而且无论字面上还是语义上都很贴切。当然,用例和测例是不同层面的“例”。

现在市面上Actor也有多种译法,常见的包括“参与者、执行者、主角”等等。“参与者、执行者”的问题主要是不准确。首先,“参与者”通常让大家马上想到的词是participant,而且请注意,一个用例的真正参与者决不是只有外部的Actor,它们必然还包括系统本身及其内部的各种元素。“执行者”的问题与此类似:一个用例的真正执行者应该是系统本身!因此严格地讲这样译是错误的,兴许叫作“外部参与者”、“外部执行者”才更为恰当。“主角”的译法同样存在着矛盾。如果把Actor叫作“主角”,那么PrimaryActor就应该叫作“主主角”了。看来Actor的译法中是不能含有“主”的,那么就剩下“角”了,而UML已经有了一个专门术语role(角色),我们又不能把Actor直接叫作“角色”。

目前看来,把Actor意译成“使用者”是比较妥当的。在大多数情况下Actor的的确确就是用户(确切地说是系统用户所扮演的一种角色),所以我们可以用“使用者”这个词从字面上与“用户”(user)进行区分,但同时又保持两者语义上的联系。我们还可以把为系统服务的Supporting/SecondaryActor(见下文)叫做“被使用者”(为了简化可以省略“被”字)或“辅使用者”。除了指系统的用户之外,“使用者”还有另一层含义,即Actor是usecase的使用者(或被使用者),这种关系在UML用例图上应该可视化地表示为它们之间的连线(关联)。这样解释不但说的通,而且更便于不熟悉软件技术的业务人员理解。

当然,我们也不排除将来会找到“usecase”、“actor”等术语更好的译法。

二、统一用例方法

2.1理由

为什么要提出统一用例方法(UUCM),有这个必要吗?

我们发现,虽然寇本用例起源于亚克申用例,但两种用例方法各自经过十多年的发展,彼此之间逐渐出现了一些显著的差异,而且由于商业或其他方面的原因,目前我们尚未看到两者将要融合的明显趋势。两种方法各有优缺点,寇本强调基于目标的文本格式,亚克申用例则更突出UML的作用,如下文所示,两者的差别至少有10处之多。对于实践者来说,如何处理好这些明显差异,避免使用上的误区,再者能否巧妙地做出取舍,实现熊掌与鱼兼得,这些都是非常现实的在实践中必须面对的问题。

笔者认为采用统一的用例方法,把亚克申和寇本用例两者结合起来,甚至融合其他的用例方法(据说已知的各种用例表示方法多达18种以上[2][6]),在理论和实践上均是可行和必要的,这可能是我们目前可以采取的最佳策略。但是,UUCM本身并不是一种全新的用例方法,而只是一种特定的处理方案。它是在对亚克申、寇本用例方法继承的基础上,试图消除这两种经典方法的不一致和矛盾,并探索可能的优化改进和后续发展,所以UUCM起到的作用与亚克申、寇本用例方法相比是次要的和微小的。

以下我们对两种方法的异同进行比较分析,并同时给出UUCM的建议。

2.2层次

明确提出用例的层次和范围划分,是寇本“基于目标的用例方法”的精华所在[2]。显然,每个用例存在的意义是为了完成一定的用户目标。寇本把用例划分为3个目标层次:概要层、用户目标层和子功能层,并通过引入巧妙的Why/How技术帮助分析者找到合适的目标层次,从而可以有效地把握用例的粒度(真正的用例最终应落实到用户目标层),防止用例情节的爆炸。

UUCM:

2.3范围

关于用例范围的处理,两种方法基本上是一致的,都可分为业务用例、系统用例两种,区别在于寇本强调在格式上用图标或文字显式地表示出每个用例的范围,并且在用例层次划分的基础上提出了最外层(或最外围)用例的概念[13],这在亚克申方法中是没有的。

用例的本质就是对象之间的一种协作和交互,这些内容是属于需求还是属于设计,关键就看你划定的讨论边界。我们不仅可以用它来描述发生在系统边界上的功能需求(用例的常规定义),而且还可以同样的方式描述系统内部发生在子系统、构件、接口或类/对象边界上的黑盒交互,不过后者往往涉及到系统设计范畴,属于用例的特殊用法,在做项目的需求分析时一般不予考虑。

正如寇本所提到的,同样一个用例名称,比如“取款”,可能实质上代表着两个截然不同的用例:一个是ATM取款(系统用例),另一个是银行柜台取款(业务用例)。所以在一个用例中明确标记出它的范围,是很有必要的。我们既可以用特定的图标,也可以用专门的格式字段来表明用例的范围,还可以对用例的名称加以修饰以便区分,比如“柜台取款”,“ATM取款”。

当前的讨论边界(SuD,theSystemunderDiscussion)一般比较容易确定,那么如何从用例的范围上判断一个用例是系统用例,还是业务用例呢?(这是一个出现率很高的FAQ)。有个小窍门:如果某个SuD或者用例的范围包含了人以及由人组成的团队、部门、组织的活动,那么针对这个SuD写出的用例必然是业务用例;如果该SuD仅仅是一些软件、硬件、机电设备或由它们组成的系统,并不涉及到人的业务活动,那么根据这个SuD写出来的肯定是系统用例。

由于系统(注意,这里的“系统”是指由软、硬件组成的IT系统)往往是业务的一部分,我们还可以得出推论:对于某个系统用例suc,通常总是可以找到一个业务用例buc,buc的范围要大于或等于suc的范围;当这两个用例的范围相等时,buc就是suc,或者buc的层次要高于suc的层次。

2.4包含与扩展

2.4.1一头雾水

图1、寇本画法[1]

图2、《UML参考手册》画法[10]

为什么会有如此差别?为了说明问题,还是让我们先看看这几个用例的文本描述。《UML参考手册》写道:

基用例ATM会话:

看到这里,我们就不难解释为什么图2把ATM会话与取款之间的关系画成扩展了(注:这本身可能不符合亚克申扩展用例的原则[4])。由于在身份验证通过后,顾客具体执行什么操作是不定的,可以是取款、存款、转账、查询等事务中的任何一个,将来甚至还有可能添加(扩展)新的功能,而ATM打印的凭条根据用户操作的不同,内容也将有所不同。这些内容的发生都需要具备一定的条件,属于可能的情况,这一点似乎很符合扩展用例的定义。考虑到这些因素,作者于是采用了图2的策略,把可能的操作和打印内容都从基用例中抽走。

然而不要忘了,除了扩展用例只有在特定条件下才能被触发之外,把一段内容提取为扩展用例还要求即使在没有该扩展用例插入的情况下,基用例本身的执行也不应受到任何影响。因此,如果我们把上段文字中的两个扩展点拿掉(只看左边的文字)并参照寇本目标用例的标准,可以发现该基用例完全不是一个目标得以完整执行的用例。上述写法是有问题的,它不完整,而且效率不高,似乎模仿了一些编程语言的写法和思路,在实践中不值得推广。

下面再让我们看看寇本版的“使用ATM”[1]:

1.顾客插卡,输入PIN。

2.ATM验证顾客账户和PIN。

3.顾客执行下列任一事务:

取款存款转账查询

顾客执行以上事务直到选择退出。

4.ATM退卡。

在这里,取款、存款等事务操作明确地出现在用例的基本流中,显然它们都是被“使用ATM”所包含的用例。注意,在寇本用例中每个动作步骤不一定都是顺序执行的,可以有循环,有选择,甚至可以是任意顺序,例如上面的步骤3。在WEUC中寇本还指出,实际上取款、存款、转账等操作都是顾客执行一次交易事务的特例和具体化,所以还可以进一步画成类似图3的形式。。我们可以看到图1其实是图3的简化。

图3、更为准确的画法

应该如何判定一个用例关系是包含关系还是扩展关系?有些情况还是比较明确的,例如对于“验证身份”和“吞卡”,大家可能都毫无异议,一致认为它们分别是“使用ATM”的包含用例和扩展用例。但是,一旦出现上例的情况时,就较难处理了。不过,我们通常可以据此判定:如果触发条件中含有基用例负责的事物,即基用例知道附加用例何时、何处、为什么发生,那么基用例应该包含(调用或引用)它;如果触发条件中含有附加用例负责的事物,即附加用例知道它应该何时、何处、为什么发生,那么应该让附加用例扩展基用例[1]。这两条规则还是很管用的。此外,根据笔者经验,还可以参考这样一条简单法则:凡是在用例基本流中出现的附加用例都应作为包含用例,而在扩展流中出现的附加用例必然是扩展用例。显然,图3符合以上规则。

问题似乎得以解决了。然而,在UML2.0上层结构规范草中,我们却看到了类似图4的方案:

图4、另一种近似的画法

2.4.2subusecase之争

寇本在WEUC中把包含用例称为subusecase,即subordinateusecase之意,但其实subordinateusecase(笔者将其译为“分用例”)在亚克申方法中有专门的用途(在亚克申博士早就提出的对大规模系统建模的SystemOfInterconnectedSystems模式中,有超系统/超用例和分系统/分用例之分[4])。而寇本采用的subusecase叫法很容易被直译成中文“子用例”,从而造成新的误解,因为我们知道“父子”一说在OO方法中通常是用来形容对象类之间的继承关系的,子类是父类的派生类,显然这与包含用例的真实语义不符。

在UML[10]中,把包含用例、扩展用例统称为附加(additional)用例,被包含、被扩展的用例叫做基用例,在用例的继承关系中则采用父用例、子用例的说法,这样做是妥当的。

建议在实践中尽量回避寇本subusecase的说法,可以用“包含用例”或“附加用例”来代称,同时明确约定在中文中凡是提到“子用例”的地方,就是指用例的继承或一般化。

2.5Actor

寇本用例的Actor类型有7种之多,包括[1]:Actor(somethingwithbehavior)、Externalactor(anactoroutsideSuD)、Stakeholder(anexternalactorentitledtohaveitsinterestsprotectedbythesystem)、Primaryactor(astakeholderwhorequeststhatthesystemdeliveragoal)、Supporting/secondaryactor(asystemagainstwhichtheSuDhasagoal)、Offstage/tertiaryactor(astakeholderwhoisnotthePA)、Internalactor(eithertheSuD,asubsystemoranactivecomponentoftheSuD)。RUP关于Actor的定义[7]是:Someoneorsomething,outsidethesystemorbusinessthatinteractswiththesystemorbusiness。UML的定义是:Anactorspecifiesaroleplayedbyauseroranyothersystemthatinteractswiththesubject。

亚克申用例与寇本用例对于Actor的定义存在着明显区别。亚克申及UML的Actor是系统之外的人或物,而寇本Actor的含义(可能来自早期的亚克申版本)比较笼统,其范围要大得多,有内外Actor之分。既然我们确定Actor的主要目的之一是为了划定系统(或业务)的边界,那么应该始终把Actor当作系统外部的事物,这样才比较妥当,内部Actor是不必要的概念。而且,在实际应用中Actor即重要也不重要[1],识别Actor的主要目的是为了帮助提取用例,通常不需要对各种Actor类型加以如此细致的区分。

2.6后置条件

与亚克申用例相比,寇本对用例的后置条件进行了细分,提出了最小保证、成功保证等概念,这样做是有意义的。最小保证描述了系统不管在任何情况下,尤其当用例失败、目标未达成时,都应满足的起码条件和应采取的措施。

建议采纳寇本方法的最小保证和成功保证划分。此外,在前置、后置条件(最小保证和成功保证)中除了说明必须满足的条件外,还可以分别说明系统在用例开始前和结束后的状态,包括各种成功和失败状态以及对失败状态的处理。

2.7动作步骤

寇本用例步骤采用独特的编号方式,基本流采用1,2,3…顺序编号,扩展流的条件和扩展步骤采用数字、字母间隔的方式,如1a、1a1、5c、5c3b1等等,而且还可以使用宏代符*,可以指定任意数目步骤的条件,如1-9a、2,7-9c等等,使用起来非常方便。RUP的基本流、扩展流步骤完全采用自然分节的顺序编号,如1.1、2.3.4.1等等,不便于阅读者找到用例具体的引用位置,在指定扩展位置时显得较为麻烦。另一方面,RUP用例的每个步骤都可以附上一个名称,这叫做“命名步骤”。

如果一个步骤内容较多,用一个短语标记来概括说明该步骤执行的大致内容,确实比较方便,而且将来需要画用例的活动图时也可以作为快速参考。

建议采纳寇本的步骤编号方式和RUP的命名步骤方法。

2.8文本与UML

亚克申用例方法与UML、RUP三者之间有着天然的紧密联系。用例驱动、可视化建模是RUP的两大特征,若用例和UML缺席,RUP也就称不上RUP了。在亚克申方法中,除了可以用RUP的格式文本描述用例外,还推荐适当地选择利用UML用例图、序列图、协作图、活动图和状态图5种图示从各个角度来描述用例,可谓手段充足、武器齐备。

UUCM:

如前所述,文本用例本质上是对对象交互过程的执行步骤的罗列。用例本身即每个“椭圆”内部的东西才是最为关键和重要的,用例之间的关系相对来说要次要些,在这一点上,可以说亚克申方法和寇本方法的看法是一致的[1][4]。实践中,我们发现很多时候,先写文本系统用例,后照着已有的文字说明画UML图比先画图或完全依赖于图形来描述系统用例要容易得多。可见对于软件需求分析,我们应该首先把更多的精力放在写好文本用例上(这正是寇本方法的强项)。

但是,寇本认为“Sequencediagramsarenotagoodformforexpressionusecases”[1],这种说法有失准确和全面。纵观全书,寇本主要是从工具使用的角度来分析的,他在书中对当时那些不那么先进的CASE工具颇有微词,认为它们不如文本写作更加便捷和有效。然而,事实上这只是问题的一个方面,UML工具的缺陷并不能简单地等同于UML语言本身的缺陷。正确地使用UML及其工具不仅仅是为了获得形象直观、交叉引用、超链接、名称自动变更等一目了然的好处,更重要的一个原因是,通过合适的UML图形,比如SSD(系统序列图),来精确地定义和描述系统事件与作为其响应的系统操作(也就是系统的输入和输出)[8]之间的契约,这正是后续系统分析和设计的起点。序列图在用例分析中其实起到相当关键的作用,在实践中用它来刻画每一个重要的系统用例也是非常普遍的做法。

而且,在分析复杂的业务流程/业务用例时,人们好像更习惯于首先画活动图(可能与人类自身的思维习惯有关),反而不太愿意采用繁琐的文字说明。对于复杂和关键的用例,除了一些必要的文本描述之外,再辅之以UML活动图、序列图或状态图进行可视化,是行之有效的好做法,有助于澄清问题本质、迅速抓住要领。对于复杂的用例模型,通过用例图描述用例之间的关系,提供全局浏览视图,也是非常必要的。

用例的UML图形与文本描述之间不是谁取代谁的关系,而是相辅相成、优势互补,应该因地制宜地加以运用。不仅如此,同时拥有用例的结构/半结构化文

本和UML图形,往往还有助于彼此之间相互比对、确认,能显著提高用例描述和分析的正确性。根据本人经验,把两者结合起来运用效果才是最好的,没有必要过份地强调某一方面。

2.9黑盒白盒

亚克申博士发明的用例实现(UCR,UseCaseRealization)[5]在RUP、UML中是一个非常重要的概念,它描述了内部对象如何相互协作共同实现一个用例,理论上每一个用例都应该至少有一个UCR与其对应,因而UCR在亚克申方法中起到了联接问题域和解决域、贯穿整个软件分析设计过程的关键作用。在寇本方法中,不存在UCR这个术语,只有黑盒用例(需求)、白盒用例之分(需求的实现)。

首先,既然谈及基于用例表示的功能需求,那么它就应该是黑盒的、透明的。如果我们看到了系统内部的情况(白盒、不透明),那么这其实已经是需求的一种实现了。所以,我们应该在需求分析时尽量避免“白盒用例”这种矛盾的说法。严格地区分UC和UCR,有助于项目团队在实践中消除需求和实现不分的情况。这一点过去在被拉来写需求的程序员当中比较普遍,受习惯性思维的影响,他们往往写到最后就变成写软件设计方案了,这是很糟糕的。

2.10格式模板

寇本在WEUC中一共列出了5种主要的用例格式模板:完整型、简易型、单列表式、双列表式和RUP样式。在此,我们推荐以完整型(寇本本人最喜欢的)为基础,结合了单列表式和RUP样式特点的UUCM模板:

用例名称:层次:+|!|-范围:简述/背景:主使用者及利益:其他受益人及利益:受益人1:受益人2:最小保证:状态1:状态2:后置条件成功保证:前置条件:条件1:条件2:状态1:状态2:触发事件:基本流:1.步骤12.<可选名称>.步骤2…n.步骤n<结束>扩展流:1a.条件1:1a1.步骤11a2.步骤2扩展点:名称1:位置1名称2:位置2技术和数据变化:1a.2a.非功能需求:业务规则:备注:其他必要字段……表1、UUCM模板v1.0

双列表式较多地被用来描述用户界面需求,有些人偏爱它,但我们发现双列表不够简洁,比较占空间,而且很多情况并不适用,比如参与者多于两个的情况。

三、结语

寇本用例方法以基于目标的结构化/半结构化文本描述见长,亚克申用例方法更重视UML可视化建模和用例驱动过程。两者尽管同宗同源[1],却在一些使用细节上存在着明显差异,而且各自还在沿着既有轨道继续向前发展。本文提出的统一用例方法并不是一种全新的方法,UUCM仅仅是个符号或代称(也许可以有其他更好的名称),它实质上代表了一种解决方案和思路,目的是吸收亚克申和寇本用例方法的长处,消除两者的不一致,从而帮助实践者尽可能规避使用上的误区,发挥用例和UML方法“1+1〉2”的联合优势。这既是实践的选择,也是现实的需要。

话说天下IT之势,合久必分,分久必合。UUCM不是句号,而是一个新的起点。出于商业、私人或其他方面的原因,国内外许多技术流派分呈的局面会长久持续下去,这本身是一件好事。不过,对于我们实践者来说,选择实用的工程技术时不应有门派分割的障碍。对于特定的场合、特定的项目,企业人往往只有一个明智的选择,那就是:用最小的成本创造最大的客户价值。所以,对于实用型技术我们完全可以采取拿来主义的态度,防止guru-locked-in,适用的即是最好的!

2.1用例与用例图

需求获取(RequirementElicitation)是需求工程的主体,其主要工作是建立待开发系统的模型,而用例就是用于建立这种模型的良好方法。用例最初由IvarJackboson博士提出,后被综合到UML规范之中,成为需求表述的标准化体系。前文已经提到,整个RUP流程都是"用例驱动"的,各种类型的开发活动包括项目管理、分析、设计、测试、实现等以用例为主要输入工件,用例模型奠定了整个系统软件开发的基础,用例被认作第二代面向对象技术的标志,可见其重要性非同一般。

参与者

参与者是与系统、子系统或类发生交互的外部用户、进程或其他系统。参与者可以是人、另一个计算机系统或一些可运行的进程。在图2.1中,"读者"和"管理员"即为参与者。

参与者之间可以存在泛化关系,例如,在图2.1所示图书馆管理系统用例图中,可以认为"读者"是"学生读者"和"教师读者"的泛化,而"学生读者"还可以具体化为"本科生读者"和"研究生读者";同样,"图书管理人员"也是"采购员"、"编目员"及"借阅人员"的泛化。图2.2表示出了参与者之间的泛化关系。

图2.2参与者泛化关系

用例

用例是外部可见的一个系统功能,这些功能由系统所提供,并通过与参与者之间消息的交换来表达。用例的用途是在不揭示系统内部构造的情况下定义行为序列,它把系统当作一个黑箱,表达整个系统对外部用户可见的行为。

鉴于用例的特点,用例一般被命名为一个能够说明目标的动名词组。如图2.1中的"借书"、"还书"和"管理图书"皆为动名词组。

用例之间也可以存在包含、扩展和泛化等关系:

(1)包含关系:用例可以简单地包含其他用例具有的行为,并把它所包含的用例行为做为自身行为的一部分,这被称作包含关系。

(2)扩展关系:扩展关系是从扩展用例到基本用例的关系,它说明为扩展用例定义的行为如何插入到为基本用例定义的行为中。它是以隐含形式插入的,也就是说,扩展用例并不在基本用例中显示。在以下几种情况下,可使用扩展用例:

a.表明用例的某一部分是可选的系统行为(这样,您就可以将模型中的可选行为和必选行为分开);

b.表明只在特定条件(如例外条件)下才执行的分支流;

c.表明可能有一组行为段,其中的一个或多个段可以在基本用例中的扩展点处插入。所插入的行为段和插入的顺序取决于在执行基本用例时与主角进行的交互。

图2.3给出了一个扩展关系的例子,在还书的过程中,只有在例外条件(读者遗失书籍)的情况下,才会执行赔偿遗失书籍的分支流。

图2.3用例扩展关系

图2.4用例泛化关系

通讯关联

通讯关联用于表示参与者和用例之间的对应关系,它表示参与者使用了系统中的哪些用例(或者说系统所提供的用例被哪些参与者使用)。

通讯关联以箭头或实线表示。若使用箭头,箭头所指方将是对话的被动接受者;如果不强调对话中的主动与被动关系,则可以使用不带箭头的关联实线。

2.2建立用例模型

知道了用例与用例图的概念,我们还需要懂得怎样建立用例模型,即怎样找出参与者、用例以及定义用例的过程。一般来说,建立用例模型的步骤为:

(1)确定谁会直接使用该系统,即参与者(Actor),为了发现参与者,我们可以尝试问如下问题:

a.谁/什么使用系统?

b.谁/什么从系统获得信息?

c.谁/什么向系统提供信息?

d.谁/什么支持、维护系统?

e.哪些其它系统使用此系统?

f.公司的哪个部门使用系统?

(2)选取其中一个参与者;

(3)定义该参与者希望系统做什么,参与者希望系统做的每件事成为一个用例,为了发现用例,我们可以尝试问如下问题:

a.为什么该参与者想要使用此系统?

b.该参与者是否要创建、保存、更改、移动或读取系统的数据?如果是,为什么?

c.该参与者是否要通知系统外部事件或变化?

d.该参与者是否需要知道系统内部的特定事件?

(4)对每件事来说,何时参与者会使用系统,通常会发生什么,这就是用例的基本过程;

(5)描述该用例的基本过程;

(6)考虑一些可变情况,把他们创建为扩展用例;

(7)复审不同用例的描述,找出其中的相同点,抽出相同点作为共同的用例;

(8)重复步骤2-7找出每一个用例。

参与者检查的参考标准如下:

(1)是否您已找到所有的参与者?也就是说,是否您已经对系统环境中的所有参与者都进行了说明和建模?

(2)每个参与者是否至少涉及到一个用例?

(3)您能否列出至少两名可以作为特定参与者的人员?

用例检查的参考标准如下:

(1)用例模型的简介部分简明清晰地概述此系统的目的和功能;

(2)所有的用例已确定,这些用例共同说明所有的必要行为;

(3)所有的功能性需求都至少映射到一个用例;

(4)该用例模型不包含多余的行为,所有的用例都可回溯到某个功能性需求来证明其合理性。

用例图从总体上大致描述了系统所能提供的各种服务,让我们对于系统的功能有一个总体的认识,仅此还是不够的,我们还需要描述每一个用例的详细信息,即用例规约。用例模型正是由用例图和每一个用例的详细描述――用例规约所组成的。RUP中提供了用例规约的模板,包含以下内容:

(1)简要说明(BriefDescription):简要介绍该用例的作用和目的;

(2)事件流(FlowofEvent):包括基本流和备选流,事件流应该表示出所有的场景;

(3)用例场景(Use-CaseScenario):包括成功场景和失败场景,场景主要是由基本流和备选流组合而成的;

(5)前置条件(Pre-Condition):执行用例之前系统必须所处的状态;

(6)后置条件(Post-Condition):用例执行完毕后系统可能处于的一组状态。

编写方案文本,而非功能需求。用例描述的是对参与者来说有价值的一系列行动,而不是特性集。例如,“招收研习班的学生”用例描述的是学生如何与系统交互来参加研习班。它没有描述用户界面看上去是什么样子,或者它是如何工作的。有一些其它的模型来描述这些重要的信息,例如用户界面模型和增补规范。面向对象分析非常复杂,因此需要对它使用几种模型,并且应该适当地应用每一种模型。

用例只记载行为需求。用例既不是类规范,也不是数据规范。这是应该由概念性模型捕捉的一种信息,在对象世界中,它是通过UML类模型建模的。您往往会引用概念性模型中描述的类,例如,“参加研习班”用例包括了“研习班”和“学生”等概念,它们都将由概念性模型描述。

不要忘记用户界面。系统用例经常引用主用户界面(UI)元素,这些元素常常称为“边界”或“用户界面”项,例如HTML页面和报表。用例有时也引用一些次要的UI元素,例如按钮或数据输入字段,但这种级别的细节并不太常见。

始终如一地组织用例图。一般的做法是垂直地绘制继承(inheritance)和扩展(extend)关联,在父/基本用例下面绘制继承/扩展用例。同样,通常水平绘制包含(include)关联。请注意,这些是简单的经验法则--只要始终遵循这些法则,产生的图将很容易理解。

不要忘记系统对参与者行动的响应。用例既应该描述参与者是如何与系统交互的,也应该描述系统如何响应这些交互。例如,在“参加研习班”用例中,如果系统在学生表明他们希望参加研习班时没有做出响应,学生就会很沮丧地离开。

备选行动过程非常重要。如果一切顺利,使用的将是基本行动过程--但也不要忘记备选过程。引入备选过程是为了描述潜在的使用错误以及商业逻辑错误和异常。这些重要的信息对于驱动系统的设计来说很有必要,因此不要忘记在用例中对它们建模。

让用例带动用户文档。用户文档的目的是描述如何使用系统。每个用例都描述了参与者通过使用系统所采取的一系列动作。简而言之,用例包含从中开始编写问党用户稳当的信息。例如,可以使用“参加研习班”用例作为基础来编写系统用户文档的“如何参加研习班”一节。

让用例带动演示。软件开发过程中的一部分是向项目资金管理者通报工作成果,因此有时需要提供演示。因为用例是从用户的角度编写的,它们包含了演示中对资金管理者可能希望听到的事物的有价值的深刻见解。换句话说,用例通常包含制定演示稿所需的逻辑。

参考资料

接下来我们再深入考虑一下为什么你不直接买房子而需要中介?其实一个问题恰恰解答了什么时候该用代理模式的问题。

原因一:你可能在外地上班,买房子的人没法找到你直接交易。

对应到我们程序设计的时候就是:客户端无法直接操作实际对象。那么为什么无法直接操作?一种情况是你需要调用的对象在另外一台机器上,你需要跨越网络才能访问,如果让你直接coding去调用,你需要处理网络连接、处理打包、解包等等非常复杂的步骤,所以为了简化客户端的处理,我们使用代理模式,在客户端建立一个远程对象的代理,客户端就象调用本地对象一样调用该代理,再由代理去跟实际对象联系,对于客户端来说可能根本没有感觉到调用的东西在网络另外一端,这实际上就是WebService的工作原理。另一种情况虽然你所要调用的对象就在本地,但是由于调用非常耗时,你怕影响你正常的操作,所以特意找个代理来处理这种耗时情况,一个最容易理解的就是Word里面装了很大一张图片,在word被打开的时候我们肯定要加载里面的内容一起打开,但是如果等加载完这个大图片再打开Word用户等得可能早已经跳脚了,所以我们可以为这个图片设置一个代理,让代理慢慢打开这个图片而不影响Word本来的打开的功能。申明一下我只是猜可能Word是这么做的,具体到底怎么做的,俺也不知道。

原因二:你不知道怎么办过户手续,或者说除了你现在会干的事情外,还需要做其他的事情才能达成目的。

对应到我们程序设计的时候就是:除了当前类能够提供的功能外,我们还需要补充一些其他功能。最容易想到的情况就是权限过滤,我有一个类做某项业务,但是由于安全原因只有某些用户才可以调用这个类,此时我们就可以做一个该类的代理类,要求所有请求必须通过该代理类,由该代理类做权限判断,如果安全则调用实际类的业务开始处理。可能有人说为什么我要多加个代理类?我只需要在原来类的方法里面加上权限过滤不就完了吗?在程序设计中有一个类的单一性原则问题,这个原则很简单,就是每个类的功能尽可能单一。为什么要单一,因为只有功能单一这个类被改动的可能性才会最小,就拿刚才的例子来说,如果你将权限判断放在当前类里面,当前这个类就既要负责自己本身业务逻辑、又要负责权限判断,那么就有两个导致该类变化的原因,现在如果权限规则一旦变化,这个类就必需得改,显然这不是一个好的设计。

好了,原理的东西已经讲得差不多了,要是再讲个没完可能大家要扔砖头了。呵呵,接下来就看看怎么来实现代理。

代理模式的实现:

其实代理模式还是很容易实现的,随便举个例子,比如你有一个类负责返回员工的薪资信息,如下:

THE END
1.数据库用例图数据库用例图的内容摘要:https://m.360docs.net/doc/0f19380489.html
2.学生信息管理系统ER图,数据流图用例图以及用例说明(部分)软件...使用rose软件建模,包括用例图 ,时序图,协作图,类图,活动图等等 上传者:weixin_57433608时间:2021-05-06 企业财务管理系统---软件工程课程设计--数据库课程设计 企业财务管理系统软件,适合计算相关专业的软件工程课程设计,数据库课程设计,含需求分析、概要设计、详细设计、测试文档、代码,很值所以分高! https://www.iteye.com/resource/m0_45272112-13585493
3.基于UML的超市进货管理系统设计根据对用例的分析,做出用例图如上,管理员主要利用本系统,实现对进货信息和对柜存信息的管理。系统采用VB环境开发,实现C/S结构,管理员对各个信息的修改都直接写入数据库,把前台界面和数据库分开存放,提高了程序的可扩展性。 2.2类图 分析系统,本系统主要包含数据库类和操作类。 https://www.jianshu.com/p/a3408047177e
4.**使用RationalRose绘制用例图类图状态图顺序图**(5)添加用例。单击工具栏中的用例图符,然后在用例图中的合适位置单击鼠标右键,得到一个用例图符,然后对该用例进行编辑,添加它的名称。 (6)添加操作员与各用例之间的关系。单击工具栏中的单向连接线图标,然后在编辑区中从操作者到相关用例画一条线即可。 https://blog.nowcoder.net/n/956ebcebd1f3431196d0c3b1f72cb778
1.mysql画类图mob64ca12df277e的技术博客记住,类图可以在项目的不同阶段进行修改和调整,因此基于你实际的数据库设计,生成的类图也需要随之更新。在软件开发过程中,良好的数据库设计与清晰的类图能够帮助团队更高效地交流与协作。 最后,让我们来看看一个小的饼状图,展示用户订单类型的分布情况(假设只有两个订单类型): 60%40%用户订单类型分布电子产品...https://blog.51cto.com/u_16213359/12485357
2.UML各种图总结精华数据库uml图用户根据用例图抽象成类,描述类的内部结构和类与类之间的关系,是一种静态结构图。 在UML类图中,常见的有以下几种关系: 泛化(Generalization), 实现(Realization),关联(Association),聚合(Aggregation),组合(Composition),依赖(Dependency)。 各种关系的强弱顺序: 泛化 = 实现 > 组合 > 聚合 > 关联 > 依赖 ...https://blog.csdn.net/qq_41694906/article/details/100738238
3.浅谈UML学习笔记之用例图腾讯云开发者社区最近一直在学习UML的基础知识,再看完视频之后,并没有很好的总结,在画图的过程中发现了很多的问题,下面是看书的过程自己总结的UML用例图的一点知识,与大家分享一下。 一、概念 用例图是由参与者、用例以及它们之间的关系构成的用于描述系统功能的动态视图。 https://cloud.tencent.com/developer/article/1781896
4.数据库中用例图怎么画火山引擎是字节跳动旗下的云服务平台,将字节跳动快速发展过程中积累的增长方法、技术能力和应用工具开放给外部企业,提供云基础、视频与内容分发、数智平台VeDI、人工智能、开发与运维等服务,帮助企业在数字化升级中实现持续增长。本页核心内容:数据库中用例图怎么画https://www.volcengine.com/theme/884235-S-7-1
5.{人力资源管理}人事管理系统用例图类图活动图UML 给出了一种描述系统蓝图的标准方法,其中即包括概念性的事物,如 业务过程和系统功能,也包括了具体的事物,如用特定的编程语言编写的类、数据库模式和 可复用的软件结构。 UML 图根据描述的功能不同可分为很多中类型,如系统类构造图是描述系统中类的构造 和属性的图,用例图是描述系统中用例基本信息的图,交互...https://doc.mbalib.com/view/1a39eb08eb0b28e68cb3bade37f12b41.html
6.UML——用例图(UseCaseDiagram)用例图是指由参与者(Actor)、用例(UseCase),以及它们之间的关系构成的用于描述系统功能的视图。用例图(UserCase)是外部用户(被称为参与者)所能观察到的系统功能的模型图。用例...。如下图所示:2.用例是对包括变量在内的一组动作序列的描述,系统执行这些动作,并产生传递特定参与者的价值的可观察结果。用例在画图...https://www.pianshen.com/article/4588923153/
7.干货!14种uml图类型及示例简而言之,类图包含类及其属性(也称为数据字段)和它们的行为(也称为成员函数)。更具体地说,每个类都有 3 个字段:顶部的类名,名称正下方的类属性,底部的类操作/行为。不同类之间的关系(用连线表示),构成了类图。 (9)对象图 数据库UML对象图描述一组对象之间的关系,是具有具体属性值和行为的一个具体事物。其...https://boardmix.cn/article/uml-diagram-styles/