Skip to content
On this page

第5章 需求之系统用例图

← 返回《软件方法》

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

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

5.1 系统执行者要点

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

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

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

但是如果,A系统和B系统各自封装,通过接口协作,这种情况下可以称 为两个系统(或子系统、组件)。

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

text
图5-3
@startuml
actor "顾客" as customer
actor "库存系统" as inventory
actor "支付系统" as payment
actor "订单系统" as order
rectangle "积分兑换系统" {
    (兑换积分) as exchange
}
customer --> exchange : 使用
exchange --> inventory : 查询库存
exchange --> payment : 扣除积分
exchange --> order : 创建订单
@enduml

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

text
图5-4 系统只有一个
@startuml
left to right direction
actor "顾客" as customer
rectangle "网店系统" {
    (兑换积分) as exchangePoints
}
customer --> exchangePoints 
@enduml

5.1.2 系统边界是责任的边界

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

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

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

手机里装了很多软件,物理边界似乎说不清道不明,但从责任上看, 哪一段逻辑该由Android封装,哪一段逻辑该由微信封装,哪一段逻辑 该由我们研发的系统封装,清清楚楚、明明白白。

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

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

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

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

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

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

旅客:担心出错票,更担心拿到了错票自己还不察觉;担心拿到 重复的票引起纠纷;担心指定日期没那个车次的票……

售票员:担心一天出很多张票太劳累;担心出错票被扣钱……

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

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

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

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

5.1.4 交互是功能性交互

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

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

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

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

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

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

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

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

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

像“用户故事”这样的方法在开发一些面向大众的互联网系统时还能应 付,因为这类系统的执行者往往属于前排涉众。如果开发涉众较多、 利益冲突微妙的系统,应该采用用例这样更严谨的需求技能。 越来越多的系统执行者不是人类,也就是说没有“用户”。两个电脑系 统交互的需求,难道就不用做了,或者可以随便做?非也。那只是相 当于上台表演的不是人,是功夫熊猫、变形金刚和喜羊羊灰太狼,但 是台下对表演说好说坏的观众依然是人。建立“执行者和系统在台上表 演,涉众在台下看表演”的概念,在执行者为非人系统时对捕获需求很 有帮助。

 所以涉众虽然不直接参加用例执行,但是非常重要。需求绝对不能漏掉。

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

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

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

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

text
图5-11 业务序列图:寻找租客线索
@startuml
actor "线索部经理" as 线索部经理
participant "线索管理系统" as 线索管理系统
actor "外呼人员" as 外呼人员
participant "电信电话系统" as 电信电话系统
actor "租客" as 租客
participant "CRM" as CRM
线索部经理 -> 线索管理系统 : 分配名单()
线索管理系统 -> 线索管理系统 : 根据历史拨打情况分配名单()
外呼人员 -> 线索管理系统 : 获取当天名单()
外呼人员 -> 线索管理系统 : 拨号()
线索管理系统 -> 电信电话系统 : 拨号()
电信电话系统 -> 租客 : 接听()
线索管理系统 -> 线索管理系统 : 录制通话()
线索管理系统 -> 线索管理系统 : 转成文字()
外呼人员 -> 线索管理系统 : 记录通话情况()
线索管理系统 -> 线索管理系统 : 判断是否属于线索()
线索管理系统 -> CRM : 接收线索()
@enduml

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

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

text
图5-12 从业务序列图映射得到系统用例
@startuml
left to right direction
actor "线索部经理" as 线索部经理
actor "外呼人员" as 外呼人员
actor "电信电话系统" as 电信电话系统
actor "CRM" as CRM
rectangle "线索管理系统" {
    ' 定义用例(椭圆)
    (分配名单) as 分配名单
    (查看本人当天名单) as 查看名单
    (拨号) as 拨号
    (记录通话情况) as 记录通话情况
}
线索部经理 --> 分配名单 : 分配
外呼人员 --> 查看名单 : 查询
外呼人员 --> 拨号 : 发起
外呼人员 --> 记录通话情况 : 提交
拨号 --> 电信电话系统 : 调用
记录通话情况 --> CRM : 同步
@enduml

5.3 系统用例要点

5.3.1 价值是买卖的平衡点

**系统用例的定义:系统能够为执行者提供的、涉众可以接受的价值。 **

和第3章的业务用例相比较,研究对象从组织变成了系统。要理解好系 统用例,重点依然是之前所强调的买卖平衡点、期望和承诺平衡点。 以ATM为例,“储户→登录”不是它的用例,因为储户对ATM的期望以 及ATM能做的承诺不只是登录。或者这样思考,ATM不能这么叫 卖:“来啊来啊!我这里能登录啊”,然后储户就说“哇,真棒,这正是 我想要ATM提供的服务,好,我去用一用”。

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

张三要出差,发现身上没现金,到ATM那里取现金,然后离开ATM忙 别的去了。 客户给张三卡里转了5000元,电话请张三查收,张三到ATM那里看看 自己的卡当前余额多少,脑子里想想是不是比之前多了5000元,然后 离开ATM忙别的去了。

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

张三到ATM那里登录,然后离开ATM忙别的去了。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

5.3.3 增删改查用例的根源是从设计映射需求

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

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

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

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

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

因为数据库里有一个“开票员”表,所以应该有“新增开票员”“删除开票 员”“编辑开票员”“查询开票员”等用例。这个思路是错的。

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

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

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

增删改查用例实际上就是从设计映射需求,导致“复用”用例的一种情 况。

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

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

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

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

害怕用例多了会导致工作量大增,背后可能隐藏着这样的问题:研发 团队做分析设计时缺乏循序渐进的抽象能力,只会把需求直通通地映 射,所以害怕用例变多,或者在发现“此处似乎可以抽象”时害怕此时 不抽象以后就忘记了。研发团队分析设计能力不足,会反向损害需求 的质量,进而损害系统在市场上的竞争力。 我们来看现实生活的例子。面馆老板的赚钱之道是用若干种原料(组 件)灵活组合出许多吃法(用例)卖给不同的顾客。同样是以面粉、 肉、菜为主原料,面馆可以做出馒头、包子、花卷、烧饼、饺子、馄 饨、锅贴、烧麦、春卷、油条、发糕……拉面、刀削面、擀面、擦 面、扯面、油泼面、担担面、拌面、焖面、面疙瘩、揪面片、手擀 面、拉条子、炒面……臊子面、沙茶面、茄丁面、酸菜面、鸡蛋面、 虾仁面、牛肉面……

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

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

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

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

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

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

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

以上错误是因为缺少业务建模导致研究对象不知不觉地改变。下面的 错误更常见——为系统的“模块”画用例图。建模人员 觉得系统的用例比较多,所以把用例分了包,认为“记录出车”“记录违 章”等是“车辆管理模块”的用例。

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

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

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

答案仍然是否定的,理由是:客户找你买的是整个系统,他不关心内 部分成几个子系统以及它们之间如何协作,这不属于需求。如果要表 达这些内容,可以用类图、序列图、组件图等,不需要用例图。

经常在这个地方“我爸是李刚”的思想又冒头了——如果我在研发团队 内部把它当成几个独立系统来开发,那么分别画用例图不行吗?假如 您看到这里,也刚好冒出这样的想法,原因可能是还没有学会从卖的 角度看需求,那么真应该从头再阅读本书。要是反复阅读后还是无法 理解,有可能您真的是“我爸是李刚”,也有可能本书对您确实没有帮 助,不必再看下去了。

5.3.6 用例的命名是动宾结构

用例的命名是动宾结构,例如“取现金”。动词前面可以加状语,宾语 前面可以加定语,把一句话的主语砍掉,剩下的可以作为用例的名 字。

给用例起名时不要使用弱动词。用例之前的需求技术,可能是以“名字 +动词”的形式命名系统的功能,例如“发票作废”,后来要改成用例的 动宾结构了,有的建模人员就在前面加一个弱动词“进行”,就变成 了“进行发票作废”,这个也是不合适的。 如果“名词+动词”已经成为行业中的一个术语,也未必要严格的动宾结 构。例如“成果分析”在某行业是一个术语,也就不必硬要倒过来变 成“分析成果”了。

5.4 【步骤】识别系统用例

其实只要认真做好业务建模,从业务序列图上映射系统用例,得到的 结果自然就会符合上面说的这些要点。

业务序列图中,从外部指向所研究系统的消息,可以映射为该系统的 用例。我们从图5-11的业务序列图上找出从外部指向“线索管理系 统”的消息,然后映射成“线索管理系统”的用例图,如 图5-34所示。

text
图5-34 从业务序列图映射得到系统用例
@startuml
left to right direction
actor "线索部经理" as 线索部经理
actor "外呼人员" as 外呼人员
actor "电信电话系统" as 电信电话系统
actor "CRM" as CRM
rectangle "线索管理系统" {
    ' 定义用例(椭圆)
    (分配名单) as 分配名单
    (查看本人当天名单) as 查看名单
    (拨号) as 拨号
    (记录通话情况) as 记录通话情况
}
线索部经理 --> 分配名单 : 分配
外呼人员 --> 查看名单 : 查询
外呼人员 --> 拨号 : 发起
外呼人员 --> 记录通话情况 : 提交
拨号 --> 电信电话系统 : 调用
记录通话情况 --> CRM : 同步
@enduml

在图5-34中,用例名改成了“查看本人当天名单”。因为序列图 上的消息代表“请求某系统做某事”,用例代表“用某系统来做某事”, 所以有的地方要调整。 图5-34的用例图中,有的箭头是从执行者指向用例,这样的执行者称 为用例的主执行者 ,有的箭头是从用例指向执行者,这样的执行者称 为用例的辅执行者 。主执行者主动发起用例的交互,辅执行者在交互 的过程中被动参与进来。UML标准中,执行者和用例之间没有要求使 用箭头,但我认为用箭头表示主、辅执行者是有意义的,建议还是加 上。

辅执行者这个概念是被误用比较多的。最常见的错误是把信息的接收 者或者将来可能使用信息的人当成辅执行者。还是以图5-34中线索管 理系统为例,有人可能画成外呼人员为辅执行者,因为他认为线索部经理使用线索 管理系统分配名单给外呼人员,箭头代表数据的流动方向,所以画一 个箭头指向外呼人员。

实际上,箭头代表的是责任分配,线索部经理使用 线索管理系统分配名单的过程中需要外呼人员的帮忙,如果外呼人员 睡着了没有响应,用例的目标就受到影响。显然,这不符合事实,所 以,外呼人员不是“分配名单”用例的辅执行者,应该从图上删掉它。

另一种辅执行者的误用刚好反过来,把信息的来源当作辅执行者。如 果,建模人员认为外呼人员要想使用线索管理系统来查看本 人当天名单,会“依赖于”线索部经理事先分配好名单。这同样是错误 的,在用例进行过程中不需要线索部经理的参与,所以线索部经理不 是“查看本人当天名单”用例的辅执行者,应该从图上删掉它。

以上错误的原因很多是因为前面没有画业务序列图,导致建模人员在 画系统用例图的时候产生焦虑,总是希望在图上多放一些信息,以免 自己忘记了。

一般来说,辅执行者是非人智能系统的情况较多,人脑系统作为辅执 行者的情况比较少,所以碰到辅执行者是人的时候,要多留心。

辅执行者是人的时候。营业员使用营业系统为顾客办 卡,在用例交互过程中,需要顾客配合输入账户密码,否则办卡用例 不能成功,这时顾客是合适的辅执行者。

最后要注意的是,主、辅执行者是针对某个用例来说的,一个外系统 可以是这个用例的辅执行者,也可以是另外一个用例的主执行 者。“××是系统的主(辅)执行者”的说法是错误的。