在實(shí)際工作中,大部分程序員很少接觸到需求分析,即使有需求分析,也是草草了事,沒有用正規(guī)的方式來表達(dá),所以一般程序員使用用例圖的機(jī)會(huì)是不多的。但是卻又常常在各種媒體上看見用例圖,于是對一種常常出現(xiàn),自己又不太熟悉的技術(shù),會(huì)產(chǎn)生恐懼。如果說對MDA或者CORBA這樣的技術(shù)產(chǎn)生恐懼還是值得的話,對用例圖產(chǎn)生恐懼是非常不值的。因?yàn)?/span>MDACORBA這樣的技術(shù)也許要花上半年的時(shí)間才能夠初步了解,而克服用例圖恐懼癥,則只要不到一天的時(shí)間。

用例圖初感

UML是一組圖示符號的標(biāo)準(zhǔn)。所謂圖示符號,就是一組定義好的圖示,它們可以表達(dá)定義好的各種意思。用UML進(jìn)行軟件建模,就是用規(guī)定好的符號畫圖,這些圖表達(dá)了開發(fā)人員腦中的軟件系統(tǒng)。用UML進(jìn)行軟件建模,其難度并不比我們小時(shí)候上的美術(shù)課更難。在美術(shù)課上,一個(gè)圓形加上四根線條表示太陽,一個(gè)三角形加上一個(gè)矩形表示房子;同理,在UML的用例圖中,一個(gè)橢圓表示用例,一個(gè)小人表示參與者。我并不認(rèn)為它們之間有質(zhì)的區(qū)別,想到我對這種小學(xué)生畫圖課恐懼了幾年,不由得感到羞愧。

用例圖是UML的九個(gè)圖中較為重要和常用的一種圖。常常用于軟件開發(fā)的需求分析階段,也能用于軟件的系統(tǒng)測試階段。簡單的來說,用例圖是描述系統(tǒng)的外部視圖。

在開始設(shè)計(jì)一個(gè)軟件系統(tǒng)時(shí)(更廣義的情況下,可以用來設(shè)計(jì)任何系統(tǒng)),需要一種手段來發(fā)現(xiàn)系統(tǒng)的功能,用例圖雖然是圖示,但是這些圖示隱含了一種啟發(fā)系統(tǒng)功能的手段。其實(shí)所有的UML圖都只包含圖示和標(biāo)準(zhǔn),并不包含方法,但是它們往往隱含了某種方法。UML和軟件開發(fā)方法的關(guān)系,很類似于漢字和語文的關(guān)系。

用例圖包含了三種基本的概念:用例、角色和系統(tǒng)。它們可以組合起來表達(dá)系統(tǒng)的外部視圖。而且這種表達(dá)方式是如此直觀和簡單。

第一張用例圖

畫用例圖是一件很簡單的事情,而且感覺還很舒適,因?yàn)橛美龍D簡潔、直觀。雖然用例圖不能像HelloWorld一樣運(yùn)行,也不能生成代碼,不過畫一張清晰的用例圖還是很有成就感的。

我使用的工具是Eclipse+EclipseUML插件,功能不如Rose,但是是開源而且免費(fèi)的(EclipseUMLfree版也有企業(yè)版),而且效果也不錯(cuò)。第一張用例圖如下:

可以看出圖中有一個(gè)系統(tǒng)(保險(xiǎn)商務(wù)系統(tǒng)),兩個(gè)角色(客戶和保險(xiǎn)銷售員)以及三個(gè)用例(簽訂保險(xiǎn)單、銷售統(tǒng)計(jì)資料、客戶數(shù)據(jù)資料),另外還有四個(gè)連接線以及一個(gè)注釋。如果在紙上或者合適的工具中,畫這樣一張用例大概只需要五分鐘吧。不過僅僅畫出來是沒有意義的,需要弄清楚其背后真正的含義才行。

理解用例圖

可以這樣簡單的理解用例圖中的一些概念,系統(tǒng)System)指的是軟件系統(tǒng),它可以包含一些用例,并界定系統(tǒng)的邊界,邊界之內(nèi)的屬于系統(tǒng)的功能和行為,邊界之外的則不是系統(tǒng)所關(guān)心的內(nèi)容。系統(tǒng)規(guī)定了一個(gè)具有某些功能的黑盒子,在系統(tǒng)之外看到的僅僅是這個(gè)系統(tǒng)的功能,而不能看到系統(tǒng)的內(nèi)部細(xì)節(jié)。這一點(diǎn)也是用例圖經(jīng)常被用來做系統(tǒng)測試的原因。當(dāng)然這些測試一般是黑盒測試。

角色Actor)是與系統(tǒng)中的用例交互的一些實(shí)體,在實(shí)際情況中,角色可以是人,也可以是其他系統(tǒng)或者硬件設(shè)備。在畫用例圖的過程中,角色往往是第一個(gè)被確定的,因?yàn)橄到y(tǒng)或者用例在開始時(shí)是模糊的,但是參與系統(tǒng)的角色是最容易明晰的。有了角色之后,根據(jù)角色與系統(tǒng)的交互,以及角色要求的功能,可以進(jìn)一步確定系統(tǒng)和用例。

用例Use case)指的是系統(tǒng)的功能,它是系統(tǒng)某個(gè)功能的所有執(zhí)行動(dòng)作的集合。在UML圖示中它是一個(gè)橢圓,但是具體分析用例的時(shí)候需要給出這個(gè)用例的所有執(zhí)行動(dòng)作的步驟。例如上圖中的“簽訂保險(xiǎn)單”用例,就可以分為幾個(gè)步驟:第一,客戶發(fā)出保險(xiǎn)單請求;第二,系統(tǒng)給出保險(xiǎn)單樣式表;第三,用戶填寫保險(xiǎn)單樣式表;第四,系統(tǒng)檢查用戶提交的保險(xiǎn)單格式是否規(guī)范;第五,如果不規(guī)范則返回第二步,如果規(guī)范則給保險(xiǎn)單銷售員發(fā)出消息;第六,保險(xiǎn)單銷售員填寫保險(xiǎn)單;第七,保險(xiǎn)單銷售員將填寫好的保險(xiǎn)單加入數(shù)據(jù)庫,并將客戶資料輸入客戶數(shù)據(jù)庫。當(dāng)然,以上步驟僅僅是我想象的,我還從來沒有見過什么“保險(xiǎn)單”,這次過了一把癮。

連接Assocation)是角色與用例的連接,表達(dá)此角色可以初始化此用例。 

注釋Note)可以添加到任何地方,對用例圖的不同部分加以說明。

泛化、包含和擴(kuò)展

泛化Generalization)在面向?qū)ο蟮募夹g(shù)中無處不在,它的另一個(gè)名字也許更為著名,就是“繼承”。下圖給出了一個(gè)使用泛化的用例圖:

由此可知,在用例圖中,角色和用例都能夠泛化。角色的泛化/繼承很容易理解,因?yàn)榻巧緛砭褪穷悾?/span>Class),它是一種版型(stereotype)為Actor的類,所以角色的繼承直觀而自然。但是用例的繼承實(shí)際上分為兩種情況,并不是簡單的使用泛化,而是使用擴(kuò)展(extended)和包含(include)兩種泛化的特例。

擴(kuò)展用于子用例的動(dòng)作步驟基本上和父用例的動(dòng)作步驟相同,只是增加了另外的一些步驟的情況下。包含用于子用例包含了所有父用例的動(dòng)作,它將父用例作為了自己的一個(gè)大步驟,子用例常常包含一個(gè)以上的父用例。如下圖:

小結(jié)

關(guān)于用例圖基本上也就是上面提到的這些內(nèi)容了。當(dāng)然,用例圖還常常和類圖、活動(dòng)圖聯(lián)合使用,不過那些知識還是等其他知識完備了以后再說比較好。

我總結(jié)的畫用例圖的步驟如下:

l        確定系統(tǒng),擬出系統(tǒng)的名稱,這個(gè)不難,例如電信計(jì)費(fèi)系統(tǒng);

l        找出所有與系統(tǒng)打交道的角色,角色要進(jìn)行一些精簡和整合;

l        站在角色的立場想象系統(tǒng)應(yīng)該提供的功能,將這些功能畫成系統(tǒng)中的用例;

l        對于每個(gè)用例給出詳細(xì)的動(dòng)作步驟;

l        找出用例圖中角色、用例之間可能有的繼承、擴(kuò)展或者是包含關(guān)系;

以我現(xiàn)在的理解能力,認(rèn)為用例圖到此為止了。當(dāng)然,我還可以想象,用例圖會(huì)用來啟發(fā)類圖的構(gòu)建,例如用例圖中的某些部分(角色或者用例)會(huì)變成類圖中的類或者接口。另外,可以想象用例圖還可能會(huì)影響活動(dòng)圖中的流程。

后記

讓我恐懼了好久的用例圖在今天便土崩瓦解了,心中卻彷佛有一點(diǎn)茫然,因?yàn)槲矣浀米约簾o數(shù)次的對自己說“好忙啊,這個(gè)技術(shù)肯定要花很多時(shí)間,還是以后再學(xué)吧”類似的話。當(dāng)我用C的時(shí)候?qū)?/span>C++這樣說過,然后是JavaCORBA、JSPXML、MDA、XMI、UML……

blog不僅僅是一種愛好,對我來說,更是一種最好的學(xué)習(xí)方法,當(dāng)我讀小學(xué)的時(shí)候,班主任常常對我說“好記性不如爛筆頭”,我當(dāng)時(shí)的理解是把事情用筆記下來比用腦袋背下來更加持久(腦袋是內(nèi)存?紙筆是數(shù)據(jù)庫?)。但是,現(xiàn)在我理解到,要學(xué)習(xí)某個(gè)東西,最好的方法是用自己的語言把它表達(dá)出來,如果你能讓別人理解這個(gè)技術(shù),你自己當(dāng)然已經(jīng)精通了。在我寫blog的過程中,常常會(huì)出現(xiàn)寫到一半的時(shí)候猛然領(lǐng)悟的情況,這是因?yàn)楫?dāng)你在選擇最佳的表達(dá)方式的時(shí)候,將你自己頭腦中一團(tuán)亂麻的線索都理清了的結(jié)果。

有朋友留言說,自己計(jì)算機(jī)本科畢業(yè),在計(jì)算機(jī)領(lǐng)域?qū)W習(xí)了八年,竟然看不懂我的blog。這個(gè)我認(rèn)為很正常,讀本科的時(shí)候,所有同學(xué)都可以在一起討論問題、實(shí)習(xí);等到上研的時(shí)候,同學(xué)對我說他的課題,我只能模糊的聽個(gè)大概,因?yàn)閷I(yè)方向已經(jīng)分開了;現(xiàn)在讀博了,同學(xué)要拉著我說他的課題,我只能明白是哪個(gè)領(lǐng)域里面的問題,往往對這個(gè)問題的描述都聽不懂了。這是因?yàn)檠芯糠较蛞呀?jīng)非常精細(xì)的原因。我自問我的方向已經(jīng)很大眾化了,如果研究圖像壓縮算法的話,那滿篇都是數(shù)學(xué)公式了;如果研究微電子技術(shù),那么滿篇都是集成電路圖了。