[2010-10-03]
UML的用例图(Usecase Diagram)是一种很好的捕获需求的方法(比起古老的CRC),但在实际运用中却很少有人 真正能正确地使用它们。这次我要讲的是用例图中include、extend、generalizaion与association四种常见关系的用法。
一个用例是描述用户与系统之间的一个交互场景,Bob去ATM取钱,John打电话给10010寻问电话卡 上的余额等这些都是一个用例,这里需要注意的是,用户不一定就是指人,可以是任何需要系统服务的单位。Wikipedia对Usecase的定义如下:
好了,理论知识看懂(好吧,也许你没懂),老板接了一个KTV点唱软件的项目并交给了Ketty。 Ketty是一个有修养的开发者,写代码之前肯定要抓取好需求的。采访用户后你发现,用户在点唱的时候都会有点歌、搜歌、排序等操作。Ketty心想用例不就是描述系统 对用户部输入的反应的吗?因此Ketty定义了点歌、搜歌与排序这三个用例。那么是谁来进行操作?Ketty很牛B,一下子就想到了“歌唱者”这个角色,于是就把“歌唱者” 与这三个用例关联了起来。这就是用例联系中的:association,它表示用例与角色存在关系。Ketty了解到,搜索功能会使用到“Sam乐库”系统的接口,因此用例图如下:
Ketty寻问了“Sam乐库”,发现他们能够提供两种搜索方式,一种是按专辑名称,另一种是按歌手名字, 但这两种搜方式都有共同的操作流程点,比如输入信息等,但又略有不同,Ketty就把他们与搜索弄了一个泛化的关系,这就是Generalization。这与面向对象的原理差不多。 《UML User Guide》是这样描述Generation关系的:

之后Ketty发现,“歌唱者”在点歌时如果余额不足,则需要进行充值,而充值是另一个用例。这个 用例只是当余额不足时才进行,因此Ketty把它作为了一点歌的扩展用例。这个就是:Extend的关系。也就是说,Extend是描述用例可能会引出另一个用例的情况。这个时候 基用例的责任(Reponsibility)就被扩展了。《UML User Guide》给出的定义是:
在使用extend关系的时候还需要注意的点就是extension point的书写,extension point就是基用例 中可被扩展的流程事件(Flow of event),在这个项目中,Ketty分析出扣款时可能会触发此extend用例,因此这里的extension point就是扣款了。
好了,大功告成了!开始写代码吧?正当Ketty想开一瓶可乐庆祝一下子的时候,Ketty发现 其实“歌唱者”每次在搜歌的时候都会系统都自动进行排序,用户不可能在不搜歌的情况下就排序,而排序肯定是在搜歌过程中进行的,那么这个时候,Ketty就想到 了include关系,include关系其实就是指一个用例每次会显示地调用另一个用例,而那个用例是一个常用的交互集,可能还会被其它用例使用。最关键的是,这个被 include的用例是决绝不能单独存在的,就像《UML User Guide》所说的那样:
好,把该画的都画好,美化一下我们的用例图,最终的结果就是这样的了:

好了,开始写代码!Ketty高兴得手舞足蹈,但Sefler给了他一记耳光,为什么?嘿嘿!优秀的 开发者(而不是程序员),你们懂的!光凭用例就做到了需求建模?显然是错的!呵呵~