天天看点

[软件方法]系统用例不存在层次问题

第5章 需求 之 系统用例图

爱情不是你想卖,想买就能卖。

《爱情买卖》;词:何欣,曲:周洪涛,唱:慕容晓晓;2009

让我们把思考的边界从组织缩小到要研究的系统。有了业务建模的铺垫,系统的用例图已经呼之欲出,但是我们还是要先来讲解一下系统执行者和系统用例的要点,再看看如何从业务序列图映射出系统用例图。

执行者和用例的概念在业务建模的章节已经出现过。现在要研究的执行者和用例,与业务建模时研究的执行者和用例相比,不同之处是研究对象,之前研究组织,现在研究系统。

5.1 系统执行者要点

系统执行者的定义:在所研究系统外,与该系统发生功能性交互的其他系统。

5.1.1 系统是能独立对外提供服务的整体

封装了自身的数据和行为,能独立对外提供服务的东西才能称为系统。不了解这一点,建模人员很容易把“添加一些功能”当作“研发新系统”。如图5-1所示,系统对外提供了某些服务,这些服务被分为A和B两组,但不能说有A和B两个系统。这个错误其实就是“从需求直接映射设计”的错误,如果没有很好理解第1章所阐述的“需求和设计的区别”,建模人员很容易犯这样的错误。

[软件方法]系统用例不存在层次问题

图5-1 错误:把功能分包当成系统

图5-2中A系统和B系统各自封装,通过接口协作,这种情况下可以称为两个系统(或子系统、组件)。

[软件方法]系统用例不存在层次问题

图5-2通过接口协作的两个系统

例如,建模人员说“我们在做一个积分兑换系统”,画出用例图如图5-3。

[软件方法]系统用例不存在层次问题

图5-3 错误:胡乱划分系统

实际上哪里有那么多系统,只是同一系统上的功能分包而已,数据都是共享的。正确的用例图应如图5-4。

[软件方法]系统用例不存在层次问题

图5-4 系统只有一个

5.1.2 系统边界是责任的边界

系统执行者不是所研究系统的一部分,是该系统边界外的另一个系统。这里的系统边界不是物理的边界,而是责任的边界。

现在大多数的软件运行形态是分布式的。一个系统可能有一部分组件部署在移动终端,其他部分组件可能部署在不同物理位置的Web服务器、应用服务器等等,导致建模人员会不自觉地认为自己在做多个系统,然后针对每个部分画用例图。其实他所研发的只有一个系统,上面这些组件都属于系统的设计。涉众根本不在意系统划分成几个组件以及组件之间如何分布和交互。建模人员如果没有学会从涉众视角看问题,只是从自己角度看问题,就会犯这样的错误。甚至有的人根据研发团队分几个组来判断当前在做几个系统,说两个就两个,说三个就三个,根本不管在客户眼里人家要几个。

严格来说,即使是“单机”的系统,运行形态也是“分布式”的,分布在CPU、高速缓存、主存、辅存等多个部位,互联网可以看作更大的“单机”。

[软件方法]系统用例不存在层次问题
[软件方法]系统用例不存在层次问题

图5-5 “分布式”没什么特别

如果根据责任来划分边界,那么一个系统在所研究系统之外的意思是:实现它不属于所研究系统的研发团队的责任——可能是父母通过生物编码实现,也可能是其他公司的程序员编码实现。这意味着一个系统可以分布在多个物理位置,也意味着同一个物理位置可以存在多个系统。

手机里装了很多软件,物理边界似乎说不清道不明,但从责任上看,哪一段代码是Google的程序员写的,哪一段代码是腾讯的程序员写的,哪一段代码是本公司的程序员写的,清清楚楚明明白白。

图5-6是一个通过物理位置来划分系统的错误例子。做一个通过手机遥控电视的控制软件,因为想到系统将来部署时可能会有一部分部署在手机端,另一部分部署在电视端。建模人员按照物理位置把系统分为手机端、电视端两个系统画在业务序列图上,映射到系统用例图时,得到两张系统用例图。

[软件方法]系统用例不存在层次问题

图5-6错误的遥控软件用例图

正确的用例图应如图5-7所示。

[软件方法]系统用例不存在层次问题

图5-7 正确的遥控软件用例图

边界越模糊,越需要执行者来帮助理清。有的建模人员觉得自己所研发的系统“比较特别”,执行者很难界定,干脆认为“执行者”不适合他们所研发的系统。仔细观察可以发现,该人员所在团队的成员对系统的责任范围根本没有形成共识,而且扯了几个月了还是扯不清楚。这样的想法相当于认为“把公鸡杀了,天就永远不会亮了”。

5.1.2 系统执行者和系统有交互

外系统必须和系统有交互,否则不能算是系统的执行者。

如图5-8,一名旅客来到火车站售票窗口,告诉售票员目的地和车次,售票员使用售票系统帮助旅客购买火车票。这个场景中,和火车票售票系统交互的是售票员,他是售票系统的执行者,旅客不是。有的建模人员碰到类似问题时会情不自禁地把旅客当作执行者,因为他觉得售票员是在执行旅客的指令(也许旅客又是执行其配偶的指令),或者觉得旅客比售票员重要,如果不把旅客当作执行者的话旅客的利益就会被忽略。

[软件方法]系统用例不存在层次问题

图5-8 旅客不是售票系统的执行者

系统执行者和重要无关。系统执行者只关注哪个外系统和所研究系统接口。这个外系统可能连人都不是,更谈不上重要不重要了。从平时的工作和生活经验我们也可以知道,当系统执行者当得最欢、整天和电脑手机打交道的人,多半不是什么大人物,而是一线的打工仔,例如营业员、办事员、客服等。大人物虽然偶尔也会用软件系统看看报表,但更多时间恐怕不是敲键盘点手机,而是摸高尔夫球杆。

和重要有关的概念是涉众。在上面提到的售票系统的“售票员→售票”用例中,旅客是很重要的涉众,而且用例不止这么一个涉众。售票员在售票的时候,好多双眼睛在盯着看呢。

旅客:担心出错票,更担心拿到了错票自己还不察觉;担心票是打出来了,信息却没有保存下来;担心指定日期没那个车次的票…

售票员:担心操作太复杂,一天下来手指麻木;担心不好用,出错票被扣钱…

火车站领导:担心售票员玩忽职守,出错票引起纠纷;担心重复出票造成纠纷…

用例必须在它的路径、步骤和补充约束中考虑这些涉众的利益。

火车票售票系统现在已经提供了旅客自行购票的接口,例如互联网购票、售票机等。这种情况下,旅客也是售票系统的执行者,不过“售票员→售票”和“旅客→购票”是两个不同的用例,它们关注的涉众利益不完全相同,相应的需求自然也不同。旅客不是天天都买票,所以和旅客打交道的用例,交互界面可以浅显一点,交互节奏可以慢一点,甚至可以卖卖广告,而且要特别注意并发容量、网络安全等问题;售票员一天要卖几百上千张票,和售票员打交道的用例,交互应该直截了当。

接下来是一个经常引起争议的问题:还是以售票系统的“售票员→售票”用例为例,假设在售票员售票过程中,旅客前面也有一个界面向旅客反馈他关心的信息,比如余票、当前选择的票等,甚至还可以根据旅客的目的地播放当地旅游景点的广告。这种情况下,旅客是售票系统的执行者吗?

依然不是,因为系统要完成用例不需要等待旅客的响应。旅客就算睡着了也不影响用例的完成。如果售票过程中需要旅客有意识地按键确认一下,否则票就出不来,那就不一样了,旅客就成了售票系统的“售票员→售票”用例的(辅)执行者。

5.1.3 交互是功能性交互

上面说的交互还引出一个问题:假设售票员使用鼠标和售票系统交互,按道理,比起售票员来,鼠标离售票系统更近,为什么不把鼠标作为售票系统的执行者呢?还有,假设售票系统运行在Windows操作系统之上,那么Windows是不是售票系统的执行者?

辨别的要点就是:执行者和系统发生的交互是系统的功能需求。如图5-9上部的序列图所示,售票员能自如地辨认并控制鼠标,是因为她的大脑里安装了如何使用鼠标的专家系统(可能是老师也可能是父母安装的)。猴子的大脑里没有这个系统,所以它很可能看到鼠标就一把抓起来往嘴里送。鼠标的移动和点击如何变成有效的输入事件,则由操作系统(包含了鼠标驱动程序)负责。以上这些交互都不是售票系统的核心域概念,售票员和售票系统之间的交互才是,所以售票员才是售票系统的执行者。

[软件方法]系统用例不存在层次问题

图5-9 售票系统的功能需求

Windows也不会成为售票系统的执行者,因为售票系统和Windows之间的交互很可能只是开发人员的设计,不是需求。涉众只是要求系统又快又好又稳定,并不在意操作系统用Windows还是Linux。如果涉众明确要求操作系统必须是Windows,那么Windows就会成为需求,但也只是设计约束类型的需求,不会成为功能需求。

当然,如果所研究系统是鼠标驱动程序,鼠标会成为合适的执行者,因为这时和鼠标之间的交互成为鼠标驱动程序的功能需求。

5.1.4 系统执行者可以是人或非人系统

系统执行者可以是一个人脑系统,也可以是一个非人智能系统,甚至是一个特别的外系统——时间。在软件业的早期,一个系统的执行者往往全部都是人。随着时间的推移,系统的执行者中非人执行者所占的比例越来越多。现在一个新系统上线,可能只有一半的接口是和人打交道,另一半接口是和非人智能系统打交道。如图5-10所示。

[软件方法]系统用例不存在层次问题

图5-10 从“执行者都是人”到“执行者有一些是人”

用例的优势在这里得到了体现。用例技术中“执行者”和“涉众”的概念,把演员和观众分开了。演员(执行者)在台上表演,观众(涉众)在台下看,演员表演什么是由观众的口味决定的,演员可以不是人,但观众肯定是人。演员如果是人类,那么在观众席上也会有一个位置,不过在第几排就不知道了。

用例使用“执行者”和“涉众”代替了原来的“用户”,这是一个非常大的突破。“用户”这个词混淆了演员和观众的区别。过去经常说“找用户调研需求”,这是错误的。所谓“用户”,就是上台表演的人类演员。找用户调研需求,相当于找演员问剧本应该是什么内容,岂不是很荒谬?剧本应该由编剧向观众调研编写出来,然后由各路演员在台上演绎。

上面已经说过,在台上当“用户”当得越欢的涉众,往往在涉众排行榜上排位越靠后。整天操作电脑搞得手僵脖子硬的“用户”,有几个是职位高的呢?真正位高权重的涉众,虽然偶尔也会上台表演,但更多时候是坐在台下看戏。建模人员如果过多地关注“用户”,花在重要的前排涉众身上的时间可能就不够了。

像“用户故事”这样的方法在开发一些面向大众的互联网系统时还能应付,因为这类系统的执行者往往属于前排涉众。如果开发涉众较多、利益冲突微妙的系统,应该采用用例这样更严谨的需求技能。

越来越多的系统执行者不是人类,也就是说没有“用户”。两个电脑系统交互的需求,难道就不用做了,或者可以随便做?非也。那只是相当于上台表演的不是人,是功夫熊猫、变形金刚和喜羊羊灰太狼,但是台下对表演说好说坏的观众依然是人。建立“执行者和系统在台上表演,涉众在台下看表演”的概念,在执行者为非人系统时对捕获需求很有帮助。

5.2 【步骤】识别系统执行者

5.2.1 从业务序列图映射系统执行者

如果没有做业务建模,识别系统执行者只能靠头脑风暴。可以思考类似下面的问题:什么人会使用系统来工作?什么人负责维护系统?系统需要和哪些其他智能系统交互?有没有定时引发的事件?

有了业务建模,就不需要头脑风暴了,直接从业务序列图映射即可。业务序列图上,和所研究系统有实线相连的对象映射为所研究系统的执行者。图5-11是某个房屋中介组织“寻找租客线索”的业务序列图,从中可以看出,和线索管理系统交互(有实线相连)的有线索部经理、外呼人员、电信电话系统和CRM,它们就是线索管理系统的执行者。映射到系统用例图如图5-12。

本书为了讲解需要,故意把系统执行者和系统用例分成两次识别,此处只识别系统执行者。实际工作中,系统执行者和系统用例是一起识别的。

[软件方法]系统用例不存在层次问题

图5-11 业务序列图:寻找租客线索

[软件方法]系统用例不存在层次问题

图5-12 从业务序列图映射得到系统执行者

图5-12中执行者不再带有斜杠,因为这时候研究对象是系统。有的执行者画在边界框左边,有的则画在右边,是为了方便表达主执行者和辅执行者。这方面内容稍后再详述。

[软件方法]系统用例不存在层次问题

本书不提供练习题答案,请扫码或访问​​http://www.umlchina.com/book/quiz5_1.htm​​完成在线测试,做到全对,自然就知道答案了。

1. 以类似_______这样的系统为研究对象时,“打印机”作为执行者是合适的。

 A) Word

 B) 财务报表系统

 C) Photoshop

 D) 打印管理器

2. 市民想给交通卡充值,来到营业点把钱和卡一起递给营业员,营业员操作“充值系统”充值。针对“充值系统”的执行者,以下看法正确的是

 A) 执行者应是市民,因为市民比营业员重要,而且营业员最终执行的是市民的指令。

 B) 执行者应该是充值系统,因为充值由充值系统完成

 C) 执行者应该是营业员,系统执行者与重要无关

 D) 市民和营业员一起作为执行者

3. 根据以下业务序列图,请问属于“一卡通系统”执行者的是(可多选)

[软件方法]系统用例不存在层次问题

 A) 外来办事人员  B) 一卡通系统

 C) 大院门口保安 D) 受访人

 E) 来车监控系统 F) 时间

4. 以下说法正确的是(多选):

 A) 业务执行者不一定是系统执行者。

 B) 系统执行者一定是业务执行者。

 C) 系统执行者一定是业务工人。

 D) 系统执行者一定要和系统交互。

 E) 系统执行者一定是系统的涉众。

 F) 系统的涉众一定是系统执行者。

5. 作为新一代的需求技术,用例用“执行者”取代了“用户”,关于这两个概念,以下说法正确的是(本题可多选)

 A) 实际上是一回事,某些方法学家炒作概念而已。

 B) “用户”把演员和观众混在一起了。

 C) “执行者”指的是“客户”,比“用户”更加值得关注。

 D) “执行者”可以不是人,“用户”默认是人。

 E) “执行者”不一定直接使用系统,“用户”一定直接使用系统。

 F) “执行者”之间可以有泛化关系,“用户”没有。

6. 类似“用户故事”之类的需求描述方式,在开发一些面向大众的互联网系统时还能应付,原因是:

 A) 互联网比较注重创新,用户故事也比较注重创新。

 B) 互联网比较注重敏捷,用户故事更敏捷。

 C) 互联网系统的“用户”和前排涉众重叠程度较高。

 D) 故事的方式更适合和低学历的大众沟通。

5.3 系统用例要点

5.3.1 价值是买卖的平衡点

系统用例的定义:系统能够为执行者提供的、涉众可以接受的价值。和第3章的业务用例相比较,研究对象从组织变成了系统。要理解好系统用例,重点依然是之前所强调的买卖平衡点、期望和承诺平衡点。

以取款机为例,“储户→登录”不是它的用例,因为储户对取款机的期望以及取款机能做的承诺不只是登录。或者这样思考:取款机不能这么叫卖:“来啊来啊!我这里能登录啊”,然后储户就说“哇,真棒,这正是我想要取款机提供的服务,好,我去用一用”。

或者可以设想可能观察到的场景:

张三要出差,发现身上没现金,到取款机那里取现金,然后离开取款机忙别的去了。

客户给张三卡里转了5000元,电话请张三查收,张三到取款机那里看看自己的卡当前余额多少,脑子里想想是不是比之前多了5000,然后离开取款机忙别的去了。

以上两个场景在典型的业务流程中可以观察到,而下面的场景就比较离谱了:

************,张三到取款机那里登录,然后离开取款机忙别的去了。

所以,取款机正确和错误的用例如图5-13所示。

[软件方法]系统用例不存在层次问题

图5-13 取款机的用例

用例之前的许多需求方法学,把需求定义为思考系统“做什么”,用例把需求提升到思考系统“卖什么”的高度。这种思考是非常艰难的,因为它没有标准答案,只有最佳答案,而得到这个最佳答案不是靠拍脑袋,而是要通过揣摩涉众得到。要得到合适的用例,需要有一颗善于体察他人的心。如果建模人员总是习惯于从自己的角度想问题,那么让他思考“什么是系统应该提供的价值”有时甚至会让他痛苦到想要逃避,或者干脆用功能、特性等模糊不清的词语代替。

但是逃是逃不开的,生活中处处都需要这样的思考。人们求职、求偶不就是要搞清楚“我”这个人脑系统应该卖给谁,卖什么服务的最佳答案吗?我会吃喝拉撒,你不愿意为此给我报酬;你想要长生不老,我又提供不了这么大的价值。要找到一个我能干好而且你又乐意买单的平衡点,确实很难。

例如,“程序员”这个人脑系统为它的老板提供的用例是什么?安装开发工具?编码?为公司赚钱?答案是编码,这是老板对程序员的期望以及程序员可以提供的承诺的平衡点,或者说,这是程序员能卖,老板愿意买的价值。程序员不能因为装了个Visual Studio就理直气壮向老板要报酬,老板不给就生气;程序员按要求编出了代码,老板就不能因为销售部门不给力或经济崩溃导致赚不到钱而责怪程序员。正确和错误的用例如图5-14所示。

[软件方法]系统用例不存在层次问题

图5-14 程序员人脑系统的用例

程序员如果摆错了自己的位置,没有好好完成编码的本职工作,反倒是动不动向老板上“万言书”,对公司的发展方向大放厥词,老板是不会喜欢的,因为他不期望从程序员身上“购买”这个服务(用某知名企业领导人的话说就是:有精神病就送医院,没精神病就辞退)。

可见,搞清楚自己的“用例”,认清自己的定位,对人生多么重要。如果您不断通过用例思维来思考系统的价值,就能训练出越来越强大的发现价值的能力。无论打工还是创业,这种发现价值的能力都可以让您受益。

5.3.2 价值不等于“可以这样做”

回到上面取款机的例子,可能有人会“较真”了:什么,你说没有人会登录了就离开?我今晚下班就去取款机那里登录一下就走人给你看!那么我们来看看下面的例子:

电视台记者小崔经受着失眠的痛苦,经常精神恍惚。有一天晚上他在取款机取现金时,居然恍惚到把银行卡往取款机一插就走开了。回家之后,发现自己可能会丢钱,心里居然生出一种舒适感,过一会就安然入睡了。小崔尝到这个甜头后,干脆睡不着时就跑到楼下取款机插一张卡,回家后果然酣然入睡。在小崔看来,千金难买安稳觉,这样做是划算的。

请问:如果世界上确实有小崔这样的人,那么插卡是取款机的用例吗?

不是。理由:小崔不是取款机的目标执行者。虽然取款机无法防止小崔这样做,但取款机被摆在大街上的初衷不是为小崔这样的人这么用的。当然,不排除有厂家看到“类小崔人群”的痛苦,分析背后的心理后,制造出面向“类小崔人群”的助眠专用取款机。那已经是另外一款产品了。

再看下面的例子。一个办公系统,科员有两个用例A和B。科长比科员级别高,所以除了自己的用例,还可以使用科员的用例。处长级别最高,想做什么就做什么,没人敢拦着。所以,建模人员画出了图5-15这样的蜘蛛网用例图,把执行者和用例的关系误解成了权限管理。

[软件方法]系统用例不存在层次问题

图5-15 蜘蛛网用例图

用例的执行者只是表明这个用例是为这一类执行者而做,但不代表系统一定要有权限控制以防止其他的人或电脑系统使用该用例。即使系统确实需要有权限控制,而且角色的划分和执行者相近,也要把这两者分开,更不可以因为系统不设权限控制,所以把执行者的名字合并为“用户”。图5-15应改成图5-16。

[软件方法]系统用例不存在层次问题

图5-16 明确用例为谁而提供

一罐可乐打开放在那里,乌鸦路过也可以喝,可乐本身并没有权限管理防止乌鸦喝它,但乌鸦仍然不是可乐的执行者,因为乌鸦不是可乐的目标客户。

理解了上面两个要点,经常被讨论的“粒度”困惑就不存在了。用例不是面团,任由建模人员关在办公室里乱捏——“我觉得那个用例粒度大了,捏小一点,那个用例粒度小了,捏大一点”,你以为你爸是李刚,随便做点什么都有人买单吗?建模人员只能根据目标涉众心中对系统的期望来确定系统应该提供什么样的服务。

有的书中给出“最佳粒度原则”,例如:一个系统的用例最好控制在××个之内、一个用例的基本路径最好控制在×步到×步之间……这些是没有根据的。市场需要各种各样的系统,有功能众多的也有功能单一的,有一步到位的也有交互复杂的。应该把屁股坐到涉众那边去,揣摩涉众的心理,实事求是写下来。不过,“粒度”、“层次”这些概念迎合了建模人员的“设计瘾”,很容易误导建模人员。

如果建模人员在粒度问题上热烈争吵,纠缠不清,有可能已经犯了错误。最常犯的错误是把步骤当作用例。如图5-17,右侧的“验密码”和“扣除金额”其实只是用例“取现金”的步骤(一眼可以看出其主语是系统),不是用例。Include(包含)关系也不是这样用的。Include的目的是为了复用在多个用例中重复出现的步骤集合,形状往往是多个用例Include一个用例。看到这种一个用例Include许多个用例的形状,基本上可以判断它犯了把步骤当作用例的错误。正确的做法是:把右侧的“验密码”和“扣除金额”作为步骤写在用例规约中。

[软件方法]系统用例不存在层次问题

图5-17 错误:把步骤当作用例

5.3.3 CRUD用例的根源是从设计映射需求

打开一些用例图,映入眼帘的用例是四个四个一组的。仔细一看,刚好对应了数据库的四种操作。相当于把数据库的各个表名加上新增、检索、修改、删除就得到了用例的名字。很多用例书籍和文章都提到了这个典型的错误,有的建模人员就学乖了,干脆把每四个用例合并,改名叫管理××(或××管理),如图5-18——可惜,依然是换汤不换药。

[软件方法]系统用例不存在层次问题

图5-18 从数据库视角得到的用例

乍一看好像也可以理解。不管前面的业务多复杂,到数据库这一层,不都是新增、检索、修改、删除吗?有位开发人员和我说过,“潘老师,我找到了抑制需求变更的好方法,把数据库的表和字段当成需求不就行了吗?业务变来变去,数据库的表和字段是相对稳定的。”我还见到过这样的软件系统:在界面上把所有的“新增”功能都放在一起,根本不管这些功能是给不同的人在不同时间和不同业务流程中使用的。程序员肯定想“反正都是数据库里新增一条记录嘛”。

问题在于:做需求的目的不是为了安慰自己或走过场,而是让系统更加好卖。需求工作中,我们所写的每一个字,所画的每一张图都必须对好卖有推动作用,否则还不如不做。所以即使再难,也只能从涉众的视角来定义需求,不能贪图方便选择一个自己熟悉的视角应付了事。如果允许应付了事,我还有更好的绝招:我就是程序,程序就是我。您问我,某某系统的需求是什么?我回答:就是0和1的组合。对吗?对得不得了。可惜,这种正确而无用的废话,对做出好卖的系统没有帮助。

[软件方法]系统用例不存在层次问题

图5-19 从涉众视角得到的才是用例

如何避免这样的错误呢?老老实实去研究业务流程,做好业务建模,尽量从业务序列图中映射出系统用例,这样得到的系统用例是不会骗人的。新增、修改、删除、查询、管理、改变状态……这些词是数据库的“鸟语”,不是领域里的“人话”。业务流程中不会有人说,小张等一下,我到系统哪里去做一下发票管理,只会说,我去开一张发票,我去作废一张发票,我去开一张红字发票……而且,这些事情以不同的频率发生在不同的业务流程中。所以图5-18的用例图应该修改为图5-20。

[软件方法]系统用例不存在层次问题

图5-20 “说人话”的正确用例

还会有人有困惑。例如图5-20的发票系统,可以猜想系统会保存有开票员的信息,那难道不能有“添加开票员”、“删除开票员”、“编辑开票员”等用例吗?当然可以。关键是“系统应该有这个用例”这个结论是如何推导出来的。

因为数据库里有一个“开票员”表,所以应该有“添加开票员”、“删除开票员”、“编辑开票员”、“检索开票员”等用例。这个思路是错的。

当开票量较大而且需要即时开票时,如果只有一个开票员无法应付,需要增加开票员,这样就可以独立开票而且明确责任,所以系统需要为管理员提供一个“添加开票员”的用例。这个思路是可以的,而且我们还可以看到这里提到了领域知识,后面写用例规约时寻找到的涉众利益也丰富得多。

有些建模人员懒得思考,干脆一口咬定“有些系统用例就是在业务流程中无法体现”,这怎么可能呢?认真思考、如实描述改进之后的业务流程应该是怎样的,肯定能找到。系统都是在业务流程中起作用的,不会有人无缘无故突然就使用系统来做事情,没有认真去观察而已。

5.3.4 从设计映射需求错误二:“复用”用例

CRUD实际上就是从设计映射需求,导致“复用”用例的一种情况。再看图5-21的例子:

[软件方法]系统用例不存在层次问题

图5-21 “复用”用例错误示例——缺陷管理系统

从不同的业务序列图分别映射得到系统有右边四个用例,但有的建模人员会动起心思:这些实现起来不都是针对“缺陷”表来“Select ××× from 缺陷 where ×××”吗,合并成一个用例“检索缺陷”(CRUD来了)多好!于是得到左边的结果。实际上,右边这四个用例面对的执行者不同,背后的涉众利益也有差别。

用例是涉众愿意“购买”的、对系统的一种“用法”,只要涉众愿意“购买”,当然是越多越好。同样的制作材料,变出更多可卖的价值,说明您的设计能力强,制作成本低,何乐而不为?

可惜建模人员经常会犯傻,不自觉地合并用例,相当于告诉涉众说,你真笨,你买我这些功能,其实我只用了同样几个类灵活组装出来。干脆,你成本价把我的零件买走,自己去组装吧!首先,研发团队这边赚不到钱;其次也是更关键的是:顾客是不乐意买的,因为市场有分工,顾客有他自己最值得做的事情做,否则他干嘛不干脆自己开个厂组装赚钱?

说到这里,可能有人就会说了:哇,这样的话我故意把用例搞多一点,搞他1000个用例,那不是乱套了?——“我爸是李刚”的感觉又来了,用例是你搞出来的吗,是客户乐意“买”才有的。如果说真的按照“卖”的思路去找,确实是这么多,那是好事来着!事实上,往往用例的大量膨胀根本不是因为这个,而是因为建模人员把很多不是用例的步骤当成用例画出来了!

害怕用例多了会导致工作量大增,背后可能隐藏着这样的问题:研发团队做分析设计时缺乏循序渐进的抽象能力,只会把需求直通通地映射,所以害怕用例变多,或者在发现“此处似乎可以抽象”时害怕此时不抽象以后就忘记了。研发团队分析设计能力不足,会反向损害需求的质量,进而损害系统在市场上的竞争力。

我们来看现实生活的例子。面馆老板的赚钱之道是用少量的材料(设计组件)灵活组合出不同的需求(用例)卖给不同的顾客。同样是以面粉、肉、菜为主原料,面馆就可以做出许多的“用例”:馒头、包子、花卷、烧饼、饺子、馄饨、锅贴、烧麦、春卷、油条、发糕……拉面、刀削面、擀面、擦面、哨子面、扯面、油泼面、担担面、拌面、焖面、面疙瘩、揪面片、手擀面、拉条子、炒面……臊子面、沙茶面、茄丁面、酸菜面、鸡蛋面、虾仁面、牛肉面……

我去面馆就餐,点了一碗馄饨。过了一会,老板端来一碗饺子。我说,“老板,这是饺子,不是馄饨!”老板肯定不能嘲笑我,“笨,饺子和馄饨98%是一样的,都是面粉和肉菜的组合,制作工艺也差不多,你就将就着吃吧!”,要是这样我会扭头就走,到隔壁吃去了。老板可以把饺子端回后厨,经过快速分解,重新组合,几分钟之后饺子变成了馄饨,然后又端出来给我。我并不了解馄饨哪里来的,只要味道比隔壁的好,价格又公道,我就吃呗。

遗憾的是,许多研发团队没有能力低成本把饺子变成馄饨,而倒掉重做一锅成本又太高,只好哄顾客“其实你要的就是饺子”、“我们的馄饨就是这个特点”。顾客第一次可能会将就,下次就不再光顾了,毕竟街上的面馆不止你这一家。

讲到这里,就要来说一个需求的基本要点:需求不考虑“复用”,如果在考虑“复用”,要警惕自己是不是已经转换到了设计视角来思考问题。

再举几个类似的"复用"用例错供参考。

图5-22犯的错误和图5-21一样。因为最终结果都是导致数据库的“保单”表里增加一行,建模人员干脆让几个执行者共用一个用例“新增保单”。

[软件方法]系统用例不存在层次问题

图5-22 错误:因数据库都是添加保单记录而“复用”用例

正确的用例图如图5-23。

[软件方法]系统用例不存在层次问题

图5-23 正确的用例图

客户在家里通过网络投保,操心的是“可别上当”;客户代表录入自己代理的客户的保单时,操心的是“佣金要高”;内勤面对堆积如山的待录入保单,操心的是“省力一点”。从“卖”的角度来看,这是系统的三种不同用法,背后的涉众利益不同。不能用“都是往数据库的保单表里插入一条记录啊”这样的理由合并而抹杀其中的差别。

下一个错例如图5-24。因为顾客、店员和经理都参与了退货的流程,干脆共用一个用例“退货”。

[软件方法]系统用例不存在层次问题

图5-24 错误:因为参与同一业务流程而“复用”用例

正确的用例图如图5-25。

[软件方法]系统用例不存在层次问题

图5-25 正确的用例图

图5-17、图5-22和图5-24的错误用例图有一个共同点:多个执行者指向同一个用例。如果已完工的用例图不应该出现这样的形状,如果出现,可以有两种修改方法。要是我们揣摩系统的这个用例针对这几个执行者来说并无区别,就泛化出抽象的执行者,或者不需要泛化关系,直接用单个更合适的执行者代替;反之,如果对不同执行者来说有区别,就把该用例分成几个不同的用例。后一种往往更常见。如图5-26所示。

[软件方法]系统用例不存在层次问题

图5-26 出现多执行者指向同一用例时的修改

5.3.5 系统用例不存在层次问题

系统用例的研究对象就是某特定系统,不是组织,也不是系统内的组件。如果存在“层次”上的疑惑,背后的原因是研究对象不知不觉改变了。

像医院信息系统的用例,有人会画成图5-27,原因可能是前面没有画业务用例图和业务序列图,所以建模人员头脑里不知不觉把医院信息系统的价值和医院的价值混在一起了。

[软件方法]系统用例不存在层次问题

图5-27 错误的“高层”用例:混淆组织的价值和系统的价值

再看图5-28中防汛系统,把系统的愿景当成“高层”用例了。

[软件方法]系统用例不存在层次问题

图5-28 错误的“高层”用例:把愿景当作用例

以上错误是因为缺少业务建模导致研究对象不知不觉改变。下面的错误更常见——为系统的“模块”画用例图。

一种错例如图5-29。建模人员觉得系统的用例比较多,所以把用例分了分包,“记录出车”、“记录违章”等用例作为“车辆管理模块”的用例。

[软件方法]系统用例不存在层次问题

图5-29 错误:模块的用例

图5-29是错误的。用例很多时可以将用例分包,但用例包是从外部对系统用例所做的分包,里面的用例依然是系统的用例,不是用例包或“模块”的用例。正确的图如图5-30所示,用例包的命名保留领域词汇即可,删掉“管理”、“模块”等字眼。

[软件方法]系统用例不存在层次问题

图5-30 用例仍然是系统的用例

图5-29的错误实际上就是第1章提到的“从需求直接映射设计”的错误,从外部(功能分包)直接映射内部(构成组件)。我们可以说吃喝拉撒是“人”的功能,但不能说是“吃喝拉撒模块”的功能。从内外两个角度分割系统是有区别的,如图5-31所示。

[软件方法]系统用例不存在层次问题

图5-31 内外分割系统的区别

上面说的是内外不分的情况。假设建模人员已经清楚内外的区别,他理解的子系统确实就是子系统。那么,可不可以如图5-32为子系统画用例图,方便分包给研发团队各小组开发?

[软件方法]系统用例不存在层次问题

图5-32 可以这样画子系统的用例吗?