在UML風格這本書中,關於使用案例圖的指南一共有二十九條,編號由58到86,共分為四組:使用案例、參與者、關係和系統範圍,上期介紹了前面兩種,本期接續著從「關係」指南開始。

原著作者Scott W. Ambler在書中這個次小節的一開始就提到,使用案例圖中有四種關係,分別為:

1. 一個參與者與一個使用案例之間的「結合關係」(association relationship)。

2. 兩個使用案例之間的結合關係。

3. 兩個參與者之間的「一般化關係」(generalization relationship)。

4. 兩個使用案例之間的一般化關係。

其實,兩個使用案例之間還可以有「包含關係」(include relationship)和「擴充關係」(extend relationship)。

另外,目前為止,我對上述的第二條仍保持懷疑,兩個使用案例之間可以有結合關係嗎?事實上,在UML的規格書中有提到,同系統的兩個使用案例之間是不可以有結合關係的。理由在於,一個使用案例應該可以完整描述參與者與系統互動的情況,所以禁止結合同系統的其他使用案例。

可是有個微妙的地方在於,UML規格書中沒有提到不同主題的使用案例之間可否有結合關係。這個問題,目前我也無解。不過可以確認的是,至今我還沒見過,在使用案例之間建立結合關係的範例。我在《OCUP/UML初級認證攻略》一書中,有更深入討論這個問題,有興趣的讀者可以去翻閱我的這本著作。

所以,如果由我來條列使用案例圖中會出現的關係線的話,我會把他們改成下列五種:

1. 一個參與者與一個使用案例之間的結合關係。

2. 兩個參與者之間的一般化關係。

3. 兩個使用案例之間的一般化關係。

4. 兩個使用案例之間的包含關係。

5. 兩個使用案例之間的擴充關係。

接下來,編號第69到84號的指南跟上述的關係有關,一共有十六條,我們逐一來細究吧!

指南69 如果參與者出現在使用案例中,則可以在參與者與使用案例之間放置結合關係(Indicate an Association Between an Actor and a Use Case if the Actor Appears Within the Use-Case Logic)
在使用案例途中,參與者與使用案例之間的實線,無論帶箭頭與否,都稱之為「結合關係」(association relationship),如圖1所示。


參與者與使用案例兩者之間的結合關係代表著,參與者在該使用案例的執行期間,會與系統交換資訊、彼此互動,以便完成整個使用案例。簡言之,整個使用案例的執行期間,其實就是參與者與系統相互對話的互動過程。

指南70 參與者與使用案例之間的結合關係線上,避免出現箭頭(Avoid Arrowheads on Actor–Use-Case Relationships)
參與者與使用案例之間的結合關係,用來代表參與者與系統雙方的「通訊關係」(communication relationship)。特別注意,有許多人誤以為這條關係線是用來表達資訊或資料流向,其實這是個誤解。也正因為這樣的誤解,讓原著作者認為最好少用箭頭。

以最原始的定義來看,結合關係既然代表溝通關係,那麼帶箭頭的結合關係便可以解釋為單向溝通,可是反觀現在的系統,鮮少是單向溝通。比方說,我們去使用自動櫃員機時,一開始螢幕上可能出現請插入晶片金融卡的訊息,然後我們依照指示逐步輸入資料給自動櫃員機,這就是一種典型的雙向溝通。

也因為現在的系統多半是雙向溝通,所以帶箭頭的結合關係在使用案例圖中就沒多大用處了。不過,我倒是在實務上或教學上,都建議使用單向的結合關係,用以分辨參與者扮演的是啟動角色還是支援角色。

請看圖2基金系統的範例,投資人是設定扣款日期使用案例的啟動者,所以帶箭頭的結合關係線由參與者指向使用案例,代表投資人是扮演啟動角色的參與者。


「時間」參與者將啟動自動扣款申購當期基金使用案例,代表這個使用案例是系統定時啟動的,而這個使用案例的支援者為綜存系統。由於,綜存系統是扮演支援角色的參與者,所以帶箭頭的結合關係線由使用案例指向參與者,代表綜存系統是支援者。

指南71 使用案例「一定」會被啟動,適用包含關係(Apply 《include》 When You Know Exactly When to Invoke the Use Case)
指南72 使用案例「可能」會被啟動,適用擴充關係(Apply 《extend》 When a Use Case May Be Invoked Across Several Use Case Steps)
我要先澄清的是,原著作者在書中將包含關係和擴充關係視為一種結合關係,將它們稱為「包含結合」(include association)和「擴充結合」(extend association),這其實是有誤的。

請看到圖3,這是UML規格書中的母模式(metamodel),圖中很清楚看到,結合關係是一種「關係」(Relationship),而包含關係和擴充關係則是一種「具向關係」(DirectedRelationship)。


看不太懂圖3,沒關係,打個比方,請看到圖4,相似的分類架構。
根據圖4,我們會說機車和汽車是一種「車」,但是不會說它們是一種「船」,雖然機車、汽車和船三者都是一種交通工具,但顯然地,機車、汽車跟船是不同的。


澄清完之後,再回到這兩條指南,我沒有按字面中譯,而是參照原文書中的說明,點出它們的重點。包含關係和擴充關係兩者最大的不同在於,包含關係中的被包用例(included use case)是「一定」會被執行,但是擴充關係中的擴充用例(extending use case)則是「可能」會被執行。

簡單來說,數個使用案例中,都含有一段相同且一定會被執行的小流程時,可將小流程獨立成另一個小的使用案例,方便數個使用案例共用。例如自動櫃員機的範例,無論是執行查詢餘額或者提款的過程中,都有一段檢驗晶片金融卡的流程,所以我們可以將這條相同的小流程獨立出來。

請看到圖5,原始的大流程稱為「基礎用例」(base use case),獨立出來的共用小流程稱為「被包用例」(included use case),兩者之間使用標示《include》字眼的帶箭頭虛線,由基礎用力連接指向被包用例。


請接著看到圖6的流程示意圖,因為包含關係中的被包用例一定會被執行,所以看起來很像是基礎用例在執行期間一定會呼叫執行被包用例,形成一條完整的流程。


如果,這一條共用的小流程會因為狀況的不同而「可能」被執行,那就不能使用包含關係,而得改用擴充關係。同樣看到自動櫃員機的範例,在執行提款的過程中,可以自行選擇列印收據與否,但無論是否有列印收據都不會影響提款流程。

在這種情況下,可以使用標示《extend》字眼的帶箭頭虛線,由列印收據的小流程連接指向提款這個大流程。請看到圖7,原始的大流程同樣稱為「基礎用例」(base use case),獨立出來的共用小流程稱為「擴充用例」(extending use case)。特別注意到,包含關係與擴充關係的箭頭方向剛好相反,前者由基礎用例指向被包用例,後者由擴充用例指向基礎用例。


最後,我們來看圖8的流程示意圖,擴充關係中的擴充用例可能會被執行,也可能不會被執行,當不執行擴充用例時,基礎用例還是一條完整的流程。如果執行了擴充用例,看起來就像是買大送小,執行一條完整的大流程之外,還會附加執行另一條小流程。這麼一來,採用擴充關係將形成兩條不同的流程:一條流程為單純的提款,另一條流程為提款外加列印收據。

指南73 謹慎地使用擴充關係(Apply Extend Associations Sparingly)
我認為無論是包含關係或是擴充關係,都要謹慎使用,因為它們不僅容易造成使用案例圖面上的複雜度,更多時候還因為不當地過度使用,使得原先完整的使用案例被切割的七零八落。

指南74 描述相似的企業邏輯時,適用一般化關係(Generalize Use Cases When a Single Condition Results in Significantly New Business Logic)
什麼叫「相似的企業邏輯」呢?可以說,兩個使用案例描述相同的企業邏輯,但是彼此之間又有細微的差異時,比較適用「一般化關係」(generalization relationship)。

以自動櫃員機為例,我們來看下面三個小範例,不用我多加說明,你絕對可以判斷出來哪一種狀況具有相似的企業邏輯,如下:

1. 查詢餘額、檢驗晶片金融卡,兩者相似嗎?

2. 提款、列印收據,兩者相似嗎?

3. 轉帳、跨行轉帳,兩者相似嗎?

很好辨識相似的企業邏輯吧,跨行轉帳是轉帳的一種,它們兩個當然具備相似的企業邏輯。請看到圖9,一般化關係是一個帶大三角形的實線,從較一般化的父用例(super use case)指向較為特殊化的子用例(sub use case)。因此,我們可以說,本行轉帳和跨行轉帳都是轉帳的一種,它們與轉帳之間都具備有相似的企業邏輯。


再多看個例子,在購物網站的範例中,我們可以選擇信用卡刷卡結帳或者ATM轉帳結帳,不過它們都是一種結帳方式及過程,所以在這個範例中,我們可以使用一般化關係,如圖10所示。


指南75 不要使用《uses》、《includes》或《extends》(Do Not Apply 《uses》, 《includes》, or 《extends》)

在UML舊版中,曾經使用過《uses》、《includes》和《extends》字眼,不過後來的新版中,將《uses》、《includes》統一改成不加“s”的《includes》,也將《extends》改成不加“s”的《extend》。

指南76 使用案例之間的包含關係或擴充關係,避免達兩層以上(Avoid More Than Two Levels of Use-Case Associations)
如果,使用案例之間的包含關係或擴充關係有層層包含的情況時,很可能陷入了功能式分解(functional decomposition)的窘境。

例如,圖11的使用案例圖,提款包含了檢驗晶片金融卡,這算第一層,但是檢驗晶片金融卡又包含了連線讀卡機,這就算第二層了。


實務上或教學上,我只要看到複雜的包含關係或擴充關係,以及多層關聯的使用案例圖時,我通常都會開始跟學員談功能式分解的問題。千萬別把使用案例切割的太細,使用案例應該是有頭有尾,可以提供使用者完整的服務才對。

指南77 把被包用例放置於基礎用例的右方(Place an Included Use Case to the Right of the Invoking Use Case)
指南78 把擴充用例放置於基礎用例的下方(Place an Extending Use Case Below the Parent Use Case)
在使用案例圖面上放置參與者和使用案例時,想像圖面底下有格線,將這些節點放在格線的交錯點上。而且,把被包用例放置於基礎用例的正右方,把擴充用例放置於基礎用例的正下方,如圖12所示。


指南79 應用「就像是」規則來判斷使用案例之間的一般化關係(Apply the “Is Like” Rule to Use-Case Generalization)
除了「就像是」(is like)規則外,其實更常用的是「是一種」(a kind of)規則。以自動櫃員機為例,我們會說,跨行轉帳「是一種」轉帳,跟跨行轉帳「就像是」轉帳,兩者有異曲同工之妙。
不過以中文句子來說,我認為「是一種」更為通順。

指南80 把子參與者放置於父參與者的下方(Place an Inheriting Actor Below the Parent Actor)
記得將節點放在想像的格線交錯點上,而且把子用例放置於父用例的下方,如圖13所示。


指南81 應用「就像是」規則來判斷參與者之間的一般化關係(Apply the“Is Like”Rule to Actor Inheritance)
指南82 把子參與者放置於父參與者的下方(Place an Inheriting Actor Below the Parent Actor)
「就像是」或「是一種」的規則一樣也可以用來判斷參與者之間的一般化關係,不過參與者屬於系統外部,不是開發人員專研的對象,所以適可而止,別把參與者之間的關係搞得太複雜了。

同樣將節點放在想像的格線交錯點上,而且把子參與者放置於父參與者的下方。請看到圖14的範例,我們會說,醫生、護士或復健師都「是一種」醫護人員。

指南83 避免使用擴充點(Avoid Modeling Extension Points)
指南84 只有在不夠清楚的情況下,才使用擴充條件(Model Extension Conditions Only When They Aren’t Clear)
老實說,在實務上我從來沒用過擴充點(extension point)和擴充條件(extension condition)的概念,許多UML書籍中通常也對這兩個概念簡單帶過。其實,套個80/20法則來看,比較為人熟知的UML概念大概只有百分之二十吧!

幾乎沒人在談的概念,通常是稍嫌多餘的概念,或者是令人難以理解、更別說可以派上用場的概念了。擴充點和擴充條件屬於前者,它們在使用案例圖面上,其實稍嫌多餘而且也不好用,當然肯花時間去搞懂這兩個概念的人,我想是挺少的吧。

從這兩條指南看來,可以得知原書的作者其實是不希望我們用擴充點和擴充條件這兩個概念的,就嫌它們多餘、散亂無用。所以,我也不再多說明這兩條指南,反倒是想要用一點篇幅說明這兩個概念,你才不至於不知所以然。

其實,擴充點是用來搭配擴充關係使用的,用來指明執行擴充用例的時機點。以圖15為例,提款使用案例記載了一個名為「列印」的擴充點,意謂著列印收據這個小的擴充用例會被插入到列印擴充點處。


這樣說似乎有些難懂,我們分兩個部份來看:先看到圖的部份,除了在基礎用例處設置擴充點,在擴充關係線上我們也要標示出擴充點,如此一來,才能夠得知基礎用例執行到某一個擴充點時,必須插進哪一個擴充用例。以圖15為例,我們就會知道當提款執行到「列印」這個擴充點時,就會啟動列印收據這個擴充用例。

接著看到使用案例敘述的部份,在撰寫使用案例敘述(use case narratives)時,我們可以在流程敘述中使用擴充點名稱做為關鍵字,在流程步驟敘述中提及某一個擴充點時,即意謂著插入擴充用例。

以圖16為例,當提款使用案例執行到第六步驟時,會詢問顧客是否列印收據,如果顧客選擇列印,就會引發擴充點—列印,隨後將列印收據擴充用例的執行步驟插入。


此外,擴充點也可以搭配限制條件,限制擴充用例必須在限制條件為真(true)的情況下,才能夠執行。延續上述自動櫃員機的範例,在列印收據之前,必須先檢驗紙張是否充足,要是沒有紙張的話,就不啟動列印收據,如圖17所示。擴充條件可以放置於註解圖示內部,用來限制擴充點。再者,擴充點可以記錄在使用案例內部,也可以採用像圖15的表示法。


一般,我們看到的擴充用例裡頭就只有一個執行片段,不過,其實一個擴充用例裡頭可以設置多個執行片段,而且這些片段可以不需要一次執行完畢。因此,一個擴充關係就有可能會連到多個擴充點。

以圖18的線上訂票系統為例,顧客訂票之後,可以自己挑選座位,也可以不挑座位。比較特別的是,在選位擴充用例中有三段流程,分別為:查詢空位、選定座位、列印座位表。這種情況下,我們可能會設置三個擴充點,分別為:查詢、選位、列印,如圖19所示。



接著看到圖20的示意圖,選位內部的三條流程並非一次執行完畢,而是被插入到不同的流程位置。如果,在這種情況下同時設有擴充條件的話,擴充條件僅會在第一個擴充點啟動之前,檢查擴充條件是否為真,只要為真,就會依序執行這些片段,為否(false)的話,三個片段都不會被執行。


有些時候,我們想要表達同時執行多個擴充用例,就可以讓多個擴充用例共用同一個擴充點。以圖21和圖22為例,當擴充點—列印啟動時,基礎用例會同時間執行兩個擴充用例,一個將收據秀在螢幕上,另一個列印收據。


系統範圍

前面我們提過,有時候我們會在使用案例圖內,以大方框表示系統範圍,而使用案例與參與者分別放置於大方框的內外,如圖23的大方框代表購物網站。


原文書中,跟系統範圍有關的指南只有下列兩條,我們趕快來看看吧!

指南85 在系統範圍方框內指出釋出範圍(Indicate Release Scope with a System Boundary Box)
原著作者使用大方框來區分使用案例分批釋出的範圍(release scope),挺有創意的用法,不過就是太佔圖面空間就是了。

請看圖24購物網站的範例,不用多加解釋就知道加入會員和登入會員使用案例將於專案的第一階段釋出。以此類推,加入購物車和刷卡結帳使用案例於第二階段釋出,至於查詢紅利點數和兌換紅利贈品則於第三階段釋出。


在圖24中,第二階段釋出範圍會包含第一階段的釋出範圍,意味著在進行第二階段時,可以針對第一階段的使用案例多添加一些額外的功能。此外,請仔細看第三階段釋出的範圍方框與第二階段釋出的範圍方框並列,意味著第三階段釋出的範圍可以與第一、二階段並行開發。

指南86 避免無意義的系統範圍方框(Avoid Meaningless System Boundary Boxes)
由於,參與者與使用案例兩者分別位於系統內外,所以即便在使用案例圖面上未繪製出大方框,系統範圍仍舊存在於兩者之間。也因此,實務上,除非遇到同時開發多個系統的專案,需要明確知道該使用案例圖屬於哪個系統所有,否則的話,圖面上通常會省略大方框,畢竟它太佔圖面空間了。

下一回將要介紹關於類別圖的指南,這也是我認為在UML中最重要的圖。

作者簡介:
邱郁惠
研究OOAD、UML、MDA十餘年,經歷過顧問、專案、教學及寫作工作。離職後創辦UML Blog推廣UML,組織《UML互助會》社群定期舉辦軟體技術講座,出版多本UML專業書籍與電子書。目前擁有OCUP/UML三級認證、PMP認證。

相關連結
沒時間讀 UML/OOAD 書之挑讀筆記 第6回 The Elements of UML 2.0 Style(1)
沒時間讀 UML/OOAD 書之挑讀筆記 第7回 The Elements of UML 2.0 Style(2)
沒時間讀 UML/OOAD 書之挑讀筆記 第8回 The Elements of UML 2.0 Style(3)

熱門新聞

Advertisement