用例
上一章节中,我们已经找到了潘多拉魔盒系统的涉众,接下来,我们就看看他们能干什么吧。
先让我们来看看玩家到底能干什么?通过前面的介绍,我们可以得知玩家能干的最主要的事情就是“抽奖”。抽完奖之后,就是到奖品袋里取奖品。我们总结如下:
玩家用例:
抽奖;
取奖品;
要抽奖,怎么着也得先看见奖品再抽奖吧。所以玩家用例中又多了一个查看奖品,也就是查看潘多拉魔盒。取奖品也是一样,总得能打开奖品袋看一眼,再取奖品吧。于是用例列表就变成了下面这个样子:
玩家用例:
查看潘多拉魔盒;
抽奖;
查看奖品袋;
取奖品;
开篇的介绍中提到过这么一件事儿:最终,会有一个人横空出世,为了抢到大奖,一口气抽走所有奖品。这种行为学名叫作“包圆”。也就是说,在“抽奖”这个用例中会有一种特殊的情况。用例整理如下:
玩家用例:
查看潘多拉魔盒;
抽奖;
□ 包圆;
查看奖品袋;
取奖品;
对于用例最直观的说明,莫过于 UML 用例图(UseCase Diagram)。我们把上面的用例画成用例图,如图 1 所示:
(图1)玩家用例
抽奖用例是一个关键用例,该用例“扩展(Extend)”出“包圆”用例。注意,这里面是用的扩展,而不是“包含(Include)”。如图 2 所示,扩展和包含这两个箭头有什么区别呢?
(图2)扩展与包含的区别是?
我们还是以 ATM 机系统为例。ATM 机系统有个取款用例,如果你想取款,你可以先查询一下余额,也可以不查询直接取款。但是你必须在输入取款金额之后才能取款。用例图如下:
(图3)扩展与包含的区别
“查询余额”对于“取款操作”来说,可有可无。而“输入取款金额”对于“取款操作”来说,是必须的!否则系统无法得知用户要取多少钱?即,可有可无的操作用扩展箭头连接,必须有的操作用包含箭头连接。
好了,我们可以继续画出 GM 和定时器的用例图,在这里我就不画的那么详细了。如图 4、图 5 所示:
(图4)GM 用例
(图5)定时器用例
设计上的误区
我曾经见过类似这样的用例图,如图 6 所示:
(图6)错误的用例设计
图 6 可能画的比较夸张,单从用例图的使用上来说,这个图是没有任何问题的。但是确实是一个错误的用例图!因为它把所有系统的用例都混在一个层级上。这就好比把所有功能代码都写在一个类文件里。对于庞大的类文件,我们要做的就是重构!阅读代码后将功能分成若干模块,放到不同的代码文件里,以此来明确代码的层次性(或者是关系)。设计又何尝不是呢?设计也需要有层次性。图 6 的错误就是因为没有体现出设计的层次性,把不同层次的问题混在一起进行思维,这样的思维方式其结果可想而知。正确的做法应该是类似图 7 所示:
(图7)设计的层次性
我们先告诉读者,玩家大体会有哪些用例。然后再分别深入竞技场系统和护送系统,来说明这两个系统中的具体用例。如图 8、图 9 所示:
(图8)竞技场系统用例
(图9)护送系统用例
这又好比是你被派往杭州出差,下榻的宾馆是西湖区的约克酒店。你不可能站在北京长安街街头这样问路人:“嗨,姐们儿,请问杭州西湖区的约克酒店怎么走?”。你肯定是心里盘算着:先坐飞机到杭州萧山机场,然后再说吧。到了萧山机场后,你会先问西湖区怎么走?到了西湖区之后,你才会问路人约克酒店怎么走?生活如此,代码如此,设计亦是如此,xxx亦是亦是如此……
在潘多拉魔盒系统介绍中,我们初步得出了“业务模型”中的“业务对象“。现在我们又通过用例得到了“业务模型”中的“业务行为”。这将奠定我们之后的设计步骤。