一:基本概念
--->用例定义了一组用例实例,其中每个实例都是系统所执行一系列操作,这些操作生成特定主角可以观测的值。
--->所谓用例,就是一件事情,要完成这件事情,需要一系列活动,而做一件事情可以有很多不同的办法和步骤,也可能遇到各种各样意外情况。因此这件事情是由很多不同情况的集合构成的。在UML中称之为用例场景。一个场景就是一个用例的实例。
--->一个系统的功能性是由一些对系统有愿望的参与者要做的一些事情构成的,事情完成后就达成了参与者的一个愿望,当全部参与者的所有愿望都能够通过用例来达到,那么这个系统就被确定下来。
--->捕捉功能性需求,这就是用例的作用。
二:用例的特征
---->用例是相对独立的。
(1)不需要与其他用例交互而独自完成参与者的目的。用例从“功能”上说是完备的。
(2)用例本质体现了参与者的愿望,不能完整达到参与者愿望的不能称之为用例。
(3)例如:人到银行取钱是有效用例。
---->用例执行结果对参与者来说是可观测的和有意义的。
(1)人去银行取钱,得到了钱。是有效的用例,因为得到了钱。填写取款单,则不是有效用例,只是步骤。
(2)人登陆qq,进入主页。是有效用例,因为通过验证,进入操作界面。而输入密码,则不是有效用例。只能是步骤。
---->这件事情必须由一个参与者发起,不存在没有参与者的用例,用例不应该自动启动,也不应该主动启动另一个用例。
(1)用例总是由一个参与者发起的。参与者的愿望是这个用例存在的原因。
---->用例必然是以动宾短语形式出现的。
(1)用例必须有一个动作和动作的受体。
(2)喝水是一个有效的用例。而“喝”和“水”却不是。
---->一个用例就是一个需求单元,分析单元,设计单元,开发单元,测试单元,甚至部署单元。
三:用例的粒度
---->粒度是令人困惑的。比如在ATM取钱的场景中,取钱,读卡,验证帐号,打印回执单等都可能是用例。显然,取钱包含了后续的其他用例,取钱粒度更大一些,其他用例的粒度则更小一些。到底是一个大的用例合适还是分解成多个小用例合适呢?
---->这个问题并没有一个标准的规则。笔者可以给大家分享的经验是在项目过程中,根据阶段不同,使用不同粒度。
(1)在业务建模阶段,用例的粒度以每个用例能说明一件完整的事情为宜。即一个用例可以描述一项完整的业务流程。这将有助于明确需求范围。例如:取钱,报装电话,借书等表达完整业务的用例,而不需要细到验证密码,填写申请单,查找书目等业务中的一个步骤。
(2)在用例分析阶段,即概念建模阶段,用例的粒度以每个用例能描述一个完整的事件流为宜。可理解为一个用例描述一项完整业务中的一个步骤。需要注意的是,这个阶段需要采用一些面向对象的方法,归纳和抽象出业务用例中关键概念模型并为之建模。例如:宽带业务需求中有申请报装和申请迁移地址用例,在用例分析时,可归纳和分解为提供申请资料,受理业务,现场安装等多个业务流程中都会使用的概念用例。
(3)在系统建模阶段,用例视角是针对计算机的。因此用例的粒度以一个用例能够描述操作者和计算机的一次完整交互为宜。例如:填写申请单,审核申请单,派发任务单等。可理解为一个操作界面或一个页面流。
---->实际上,用例粒度划分依据(尤其是业务用例)最标准的方法是以该用例是否完成了参与者的某个完整目的为依据的。
---->用例分析是以参与者为中心的,因此用例的粒度以能完成参与者目的为依据。
四:用例的获得
---->我们知道用例的定义就是由参与者(actor)驱动的,并且给参与者提供可观测的有意义的结果的一系列活动的集合,用例的来源就是参与者对系统的期望。
---->发现用例的前提条件是:(1)发现参与者(2)确定参与者的同时就确定系统边界。
---->捕获用例前需要能够清楚地理解下面几个问题。以下:参与者改叫主角
(1)主角位于系统边界外的。
(2)主角对系统有着明确的期望和明确的回报要求
(3)主角的期望和回报要求在系统边界之内的。
(4)一个明确的有效的目标才是一个用例的来源
(5)一个真实的目标应当完备表达主角的期望。
(6)一个有效的目标应当在系统边界内,由主角发动,并且有明确的后果。
---->从客户哪儿捕获用例的中心思想?
(1)你对系统有什么期望?
(2)你打算在这个系统里做些什么事情?
(3)你做这些事的目的是什么?
(4)你做完这些事情希望有一个什么样子的结果?
五:用例和功能的误区
---->实际应用中,用例是非常容易被误解和误用的。尤其是习惯了面向过程结构化设计方法的计算机技术人员,最普遍的理解错误是认为用例就是功能的划分和描述。他们认为一个用例就是一个功能点。这是错误的。
---->用例不是功能。用例是一组功能组合。
---->在描述一个事物的时候,我们可以从以下三个观点出发:
(1)这个事物是什么?
(2)这个事物能做些什么?
(3)人们能够用这个事物做什么?
例如:描述一辆自行车的时候,我们同这样说明
第一个人:自行车是一种交通工具,它由传动系统,刹车系统等部分组成【第一个人描述的是一种结构性观点。】
第二个人:自行车可以骑行,可以载物【第二个人描述的是一种功能性观点,说明事物的可利用价值】
第三个人:人们可以用双脚蹬动踏板而往前行,可以用手捏合刹车让自行车停下来。【第三个人描述的是一种使用者观点,说明事物对使用者的意义】
----->而我们熟知这都是我们对一个东西非常熟悉,才可以这样描述。对于一个未知的事物我们是无法这样描述的。软件恰恰就是这样一个不存在的事物,无法直接知晓它的结构,价值,意义。
---->因此,我们从使用者观点出发描述软件是非常合适的。使用者观点告诉需求收集人员,他希望这个系统是什么样,他将怎么样使用这个系统,希望获得什么结果。那么软件只需要按照使用者要求提供一个实现,就不会偏离使用者的预期。至于功能性观点和结构性观点,则可以通过使用者观点推导出来。
----->使用者观点实际就是用例观点。一个用例是一个参与者如何使用系统,获得什么结果的一个集合。通过用例分析,得出结构性和功能性的内容,最终实现用例,也就实现了使用者的观点。
【用例和功能区别的总结】
------>功能是脱离使用者的愿望而存在的。我们常常说某个工具具有某个功能,它是描述工具的,而不是站在使用者的角度描述使用者愿望的。功能用来描述某某东西能做什么,它与使用者愿望无关,描述的是事物固有的性质。
------>功能是孤立的,给一个输入,通过计算就有一个固定的输出。功能描述的是一个个点。如果要达成一个特定的目标,必须要额外加上一个顺序的过程把点串起来才能完成一个系统性的工作。而用例描述的是一个系统性的工作。这个系统性的工作明确地达成一个特定的目标。
------>如果非要从功能的角度解释用例。那么用例可以解释为一系列完成一个特定目标的“功能”的组合,针对不同的应用场景,这些“功能”体现不同的组合方式。并且,不是先有了这些“功能”才来组合某个场景,而是先有了场景,才分解出“功能”。这里的“功能”之所以打引号,是因为UML里没有这个功能词。实际上从场景分解出来的是对象。这些对象通过消息相互交流而完成场景。
例子:从功能的角度出发,对电视的描述:能开关,能显示,可以调频道,可以调声音。
从用例的角度出发,对电视的描述:有一个人要观看电视节目的用例,第一步是先打开开关,调到自己喜欢的频道,如果声音不合适,可以调节一下,以上三者是因为人的需求而相关起来的。读者可以细细品味一下这其中的区别。
六:目标和步骤的误区
---->实际应用中,对用例使用的另一个误区是混淆目标和完成目标的步骤。
---->一个用例是参与者对目标系统的一个愿望,一个完整的事件。为了完成这个事件需要经由很多步骤,但这些步骤不能够完整地反应参与者的目标,不能够作为用例。
---->例子:邮局是目标系统。一个人去邮局寄信就是一个用例。
(1)可分解成的步骤:一个人找到邮局,花钱买信封邮票,将信件交给邮局。
(2)花钱买信封邮票,就是一个步骤,不能作为用例。因为花钱买邮票,不能反应参与者的终极目标。
---->用例是整个系统的架构基础,如果用例不清,错误,则导致根基不稳,建立出错误的架构。
---->步骤也是可以作为用例的。
(1)在概念建模阶段,由于用例已经捕获。对于用例进一步分析的时候,实际上我们已经进入用例的内部。
(2)进入用例内部意味着边界已经改变,而边界的改变以为着参与者也在改变。通常,原来的业务工人,现在变成了参与者。
(3)参与者发生改变,则完整的目的也发生了改变。因此步骤也是一个用例,只是相对于整个大用例,他只是一个步骤。
(4)因此用例和参与者,边界,完整目标。是相对的。
七:用例粒度的误区
----->产生用例粒度错误的原因首先是分不清楚目标和步骤。
----->例子:假设有一个网上购物系统。在获取需求时,我们决定采用整个系统的边界作为起点。
参与者:卖家,买家,系统管理员。
用例:(1)买家购买商品。
(2)卖家发布商品。
(3)系统管理员维护系统。
<一>初看用例粒度很大,有点大而空,离指导开发还很遥远。
<二>感觉空,则想细化于是,给系统管理员添加了一个修改买家的错误订单的用例。这就犯了在同一个抽象层次,用例粒度不一致的错误。
<三>系统管理员修改买家的错误订单,是买家在购买商品用例中一个意外步骤。此系统管理员已经不是彼系统管理员,他成了买家购买商品用例的一个业务工人了。因此在这个阶段就违反了边界不一,导致用例粒度有问题。
---->用例粒度另一个常常被误用的误区是在同一个需求阶段中的用例粒度大小不已。这个问题产生本质上是建模者心目中没有一个清楚的边界,没有时时检查现阶段处于那个抽象层次而造成的。我们知道用例决定了参与者完整期望,而参与者与边界是相生相灭的,所以一旦边界不确定,参与者就会混乱,导致用例粒度不一。
---->另一个方面,边界决定了当前分析阶段的抽象层次,从面向对象的要求来说,一个抽象层次决定了哪些信息该暴露哪些不应该暴露,如果错误的暴露就会导致程序结构混乱。
---->不论边界和抽象层次如何选择,粒度大小如何决定,在同一个需求阶段,必须保持所有用例的粒度在同一量级。
八:业务用例
---->业务用例(business use case)是用例版型中的一种,专门用于需求阶段的业务建模。在为业务领域建立模型时应当使用这种版型。
---->业务用例只是普通用例的一个版型,并不是另一个概念,因此业务用例具有普通用例的所有特征。
---->与其他用例版型不同的是,业务用例专门用于业务建模。业务建模是针对客户业务的模型,也就是现在客户的业务是怎么来建立模型的。严格来说业务建模与计算机系统建模无关,它只是业务领域的一个模型,通过业务模型可以得到业务范围,帮助需求人员理解客户业务。并在业务层面上和客户达成共识。
---->业务范围不等于需求,软件需求真正的来源是系统范围,也就是系统建模。业务模型是系统模型的最重要输入。
---->业务用例的的参与者是系统的客户。那么业务用例卖弄对的问题领域就是没有将来的计算机参与的,目前客观存在的业务领域。相对应,它的参与者是业务主角。站在业务主角的立场上看到的边界是业务边界而非系统边界。这一点,请务必区分。
九:业务用例实现
---->业务用例实现,也称业务用例实例。是用例版型中的一种。专门用于需求阶段的业务建模。在为业务领域建立模型时采用这种版型。
---->一个业务用例可以有多个实现方式。他们的关系可以类比编程的接口和实现类的关系。同一个接口可以有多个实现类。同样的,一个业务用例的多个业务用例实现都是为了达成同一个目的。只是达成这个目地的实现方式不同而已。
----->业务用例实现是实现对象追溯到需求的一个重要环节。在后续的建模过程中,我们根据业务用例实现将得出关键业务对象,再从业务对象转为设计对象,从而生成代码。
---->例子:我们使用电话,需要向电话局缴纳话费。将电话局作为一个业务边界,那么作为这个业务边界的参与者,电话使用者就有缴纳电话费的业务目标。我们可以为电话使用者建立一个缴纳电话费业务用例。则业务用例和业务用例实现的关系就如下图体现。
十:概念用例
---->概念用例在实际的应用中很少被人使用,但不代表不重要,相反,还相当重要。
---->概念用例:永远概念建模
---->概念模型用来获取业务模型中的关键概念,分析出业务模型中的核心业务结构以得到一个易于理解的业务框架。实际上业务架构就是在这个阶段产生的。
---->作为概念模型中的重要元素,概念用例用来获取业务用例中的核心业务逻辑,这些核心业务逻辑揭示了业务模式,成为业务架构的重要指导。同时,概念用例还是从业务用例到系统用例过度时非常重要的指导。
---->虽然概念用例不是必须的,但对于复杂的业务来说,缺少了它,系统用例的产生就会显得突兀和生硬,基本上都是拍脑袋的出来的结果。
十一:系统用例
---->系统用例没有定义版型,实际上它就是我们天天挂在嘴边的用例。因此,接下来本书中把系统二字去掉,直接称之为用例。如果不是特别强调,读者可以把用例等同于系统用例
---->系统用例是用来定义系统范围,获取功能性需求的。因此,系统用例的含义就是,系统用例是软件系统开发的全部范围,系统用例是我们得到的最终需求。
---->估计大部分人在绘制用例图的时候并没有认真想到过采用用例这一元素建模,实际上正在做的事情是划定开发范围,确定系统需求。
---->如果说业务用例是客户业务视角的话。从现在开始,系统用例将采用系统视角来看待了。
十二:用例实现
---->用例实现,完整的叫法是系统用例实现。
---->用例实现也是实现对象追溯到需求的一个重要环节。
---->现实情况中绝大部分项目都是做完用例模型后,直接开始进入数据库表设计,类设计等。有些思考比较深入的项目组成员常常心存疑惑,因为他们不知道这些数据库表和类是依据什么出来的。好像是一拍脑袋就出来了,美其名曰凭经验。其实用例实现正是链接起用例模型和系统实现之间的桥梁。