這一季我們來了解一下UML中的用例圖。
在開發系統之前,最重要的工作是獲取用戶的需求,而在用戶需求中最重要的是關于用戶提出的系統功能性需求,我們可以借助用例圖來可視化的表達用戶的需求。
用例圖(Use Case Diagram)是由參與者(Actor)、用例(Use Case)以及它們之間的關系構成的用于描述系統功能的視圖,是被稱為參與者的外部用戶所能觀察到的系統功能的模型圖。
用例圖常在需求分析階段使用。
用例圖中主要的元素包括參與者、用例以及各元素之間的關系。
除此之外,用例圖中還可以包含注解和約束。
參與者(Actor)是與主體系統交互的外部實體。
參與者可以是系統外部的人、子系統、其它系統等。
每個參與者實際上是一個角色集。
在UML中,參與者使用使用人形的圖形表示,并給這個參與者賦予一個名字。
如下圖中的“讀者”即是圖書館借閱系統中的一個參與者。
參與者應位于系統邊界之外,而不是系統的一部分。
在進行用例建模時,確定參與者是用例圖建模的第一步。那么,如何確定系統的參與者呢?我們可以從以下思路進行考慮:
(1)系統的服務對象
如圖書館借閱系統中的讀者;
(2)為其提供支持以完成工作的人
如圖書館借閱系統中的圖書館工作人員,他需要借助系統幫助讀者完成借閱、還書、催還工作。
(3)系統的維護者:負責安裝、維護和管理系統的人員,這種情況下,需要系統確實提供了相關功能以幫助這類人員完成安裝、維護和管理工作。
(4)外部設備:需要向外部設備傳輸信息或從外部設備讀入信息,如讀卡器。
(5)其它系統或子系統:如借閱系統中的財務系統,財務系統并非借閱系統的功能,但借閱系統需要向其傳遞信息以完成超期罰款工作。
(6)時間:在預定的時刻,有特定事件自動發生,如自動備份、定時提醒等。
(7)特定事件:如外賣系統中自動接單,是由訂單產生事件推動的。
在識別參與者時,要注意以下幾點:
參與者位于系統的外部,而不是系統的一部分;
參與者通過系統邊界與系統進行交互;
參與者的圖標雖然使用人形圖標來表示,但參與者不一定是人,也可能是其它子系統、其它系統、時間、溫度等其它因素。
參與者間的主要關系是泛化。泛化關系是一般和特殊(具體)之間的關系。
在泛化關系中一個參與者的抽象描述可以被一個或多個具體的參與者所共享。
下圖描述了圖書館借閱系統中參與者之間的泛化關系。
上圖中,讀者是一個“一般”參與者,下面的教職工、學生、教職工家屬等是“具體”的參與者。
泛化使用實線空心三角形箭頭來表示,箭頭指向更一般的參與者,箭尾端在“具體”參與者這端。
參與者泛化可以理解為:“具體”參與者是一種“一般”參與者,如教職工是一種讀者。
在參與者泛化中,表示“一般”參與者可執行的用例,作為“具體”(“特殊”)參與者也可以執行。
用例是參與者可以感受到的系統服務或功能單元。它定義了系統要實現的一個目標。用例只定義系統的一個行為,而不顯示系統的內部結構。
用例最大的優點是站在用戶的角度描述系統功能。
在圖形上,用例使用實線橢圓來表示,并在橢圓內部或下部標注用例的名稱:
可以通過以下要點來識別用例:
(1)參與者需要系統提供哪些功能,以支持他的工作?
(2)參與者是否需要查詢系統中的某些信息?
(3)參與者是否需要改變系統中的某些信息,如創建、修改和刪除操作?
(4)系統發生的特定事件或狀態的改變是否需要通知參與者?
(5)系統哪些外部事件會促使系統執行相關功能以應對?
(6)系統是否提供相關功能以幫助維護人員來維護系統?
(1)識別出的用例應該反應出系統的目標,即“要做什么”,而非“怎么做”,就是說用例不是系統實現的細節;
(2)從參與者(用戶)的角度出發定義用例,而非系統的角度。
(3)用例應為參與者提供有價值的結果,而非動作的集合;
(4)避免陷入功能分解,步驟分解;
(5)每個參與者都應該有可執行的用例,每個用例都應關聯至少一個參與者
在確定好系統的用例后,需要給各個用例進行命名。
用例的命名需要站在用戶的角度描述參與者達到的目標。可以使用下述命名方式:
(狀語)動詞+(定語)賓語
也就是說,用例的名稱應該是動賓短語的格式。
如選課、借閱圖書、訂購貨物、使用信用卡支付。
用例粒度是指用例細化或綜合系統功能的程度。也可以說用例所包含的系統服務或功能單元的多少。用例粒度過粗或過大,則用例包含的系統功能就越多,反之越少。
用例粒度過粗,不便于理解系統,粒度過細會使用例模型過于龐大,給設計帶來困難。
用例粒度過細,可能會陷入功能分解,如:
實際上,系統中很多業務都包含這種增、刪、改、查的操作,這樣做并不能為用戶提供任何有意義的目標,反而會忽略了用戶的真正目的。
上面這種“增刪改查”無非就是用戶管理,這才是參與者的真實目的。使用下面這種方式處理上面的用例也許會更好一些:
管理用戶這種用例體現了系統管理員的一個目標或任務。如果非要添加上增刪改查,可以使用下面的方式來表達會更好一些。
在用例建模中常犯的另外一個錯誤是把步驟當用例。
如下面這個,似乎挺完美,但是很明顯是把操作步驟當用例了。
上面這些步驟,無非就是完成用戶這個參與者的目標:注冊。因此,應該改成下面這個樣子:
在用例建模中,常犯的第3個錯誤是把系統活動當用例。
上面這個用例圖中,建立連接對象、建立命令對象和執行SQL語句是系統內的活動,是用戶無法感知的,不是用戶的目的,用戶也不關心。所以這種用例圖是不準確的。
用例建模中常犯的第4個錯誤是使用系統觀點來命名用例。
上面左右這兩個用例圖,哪個畫得更好呢?
很明顯,右邊的比左邊的要好,因為右邊的是從用戶的角度命名的用例,而左側的用例是從系統的角度對用例進行命名,用戶看到后會感到莫名其妙的。
用例圖在總體上描述了用戶的功能需求(系統提供的功能或服務),但對于每個用例還要進行詳細的描述,以便讓人知道這個用例具體要做什么,這就是用例規約。也就是說,用例模型實質上是由用例圖和對每一個用例的詳細描述(用例規約)組成的。
一個用例規約(use case specification)應該包含以下內容:
(1)用例的標識與名稱;
(2)用例涉及到的參與者;
(3)用例的簡要說明;
(4)相關的其它用例;
(5)用例執行的前置條件
(6)基本事件流;
(7)備選事件流;
(8)用例執行的后置條件;
(9)其它信息,如非功能性需求、設計約束、用例審核狀態、編制者、修改記錄等。
下面是一個用例文檔中對借閱圖書用例的一個描述情況。
用例之間的關系主要包括泛化、包含和擴展三種。
當多個用例擁有相似的屬性或行為時,我們可以將它們的共性抽象為父用例,而其它用例作為泛化關系的子用例。子用例繼承父用例中的屬性和行為。
用例的泛化關系可以理解為同一業務目的的不同實現路徑。
泛化(Generalization)關系在圖形上使用帶空心三角形箭頭的實現表示,箭頭由子用例指向父用例。
上面這個例子中,“使用微信支付”和“使用支付寶支付”是“支付”的子用例。在父用例“支付”中并不提供具體的支付方式,只提供支付必須的屬性和接口,而在其子用例中實現具體的支付功能。
在系統建模過程中,有些功能在不同業務情境中需要反復使用。這些反復使用的功能可以單獨剝離出來形成一個單獨的用例,而在執行相關功能時,可以把剝離出來的公共功能再包含到主流程中去。用例的包含關系就可以描述這種情形。另外,如果一個基本用例的功能過多時,也可以把其拆解成多個小的用例。
被包含的用例稱作提供者用例,包含其它用例的用例稱作客戶用例。
在UML中,包含(include)關系使用帶<<include>>構造型的虛線箭頭表示,箭頭由基本用例(包含用例/客戶用例)指向被包含的用例(提供者用例)。
下面是一個具體的例子:
在這個例子中,讀者要預借圖書,他需要執行查詢圖書用例,才能執行預借圖書,所以查詢圖書用例將被包含到預借圖書用例中來,同時,讀者要執行預借圖書時,前提他必須已經登錄到系統中,系統已經保存了他的登錄狀態才能執行預借操作,所以驗證身份用例也將被包含到預借圖書用例中來。查詢圖書即是一個讀者要求具有的一個基本功能,又是其它功能的一個必要操作過程。驗證身份不僅在預借圖書時要用到,還要在執行如查詢借閱記錄、繳納罰款時等用到的一個功能,把驗證身份單獨提出來形成一個用例比較合適。
基本用例提供擴展點,在擴展點中可以添加新的行為,擴展用例提供了一組插入片段,這些片段能插入到基本用例的擴展點上。
基本用例僅提供擴展點,而不必知道擴展用例的任何細節。
基本用例即使沒有擴展用例也是完整的,這與包含關系不同。
一個用例可以提供多個擴展點,每個擴展點也可出現多次。
一般情況下,基本用例的執行不會涉及到擴展用例,只有在特定條件或事件發生時,才會執行擴展用例的功能。
在UML中,擴展關系使用帶構造型<<extend>>的虛線箭頭表示。箭頭由擴展用例指向基本用例。
下面這個例子是圖書館借閱系統中,一個用例圖片段:
在這個例子中,繳納罰款即是讀者的一個基本用例,也是歸還圖書的一個擴展用例。
“繳納罰款”作為“歸還圖書”的擴展用例,只有在以下條件時,才會被執行:
(1)讀者圖書有超期或其它原因產生有罰款記錄,且未繳清;
(2)讀者選擇了在歸還圖書后,同時繳清罰款。
擴展關系與包含關系有什么不同呢?
擴展關系中,基本用例是完整的,執行基本用例不一定執行擴展用例;但包含關系中的基本用例不完整,執行基本用例必須執行包含用例。
在下一篇文章中將給出一個具體的用例圖案例,敬請關注。
新聞熱點
疑難解答