|
2004 年 11 月 01 日 用例(Use Case)是一種描述系統需求的方法,使用用例的方法來(lái)描述系統需求的過(guò)程就是用例建模。用例方法最早是由Iva Jackboson博士提出的,后來(lái)被綜合到UML規范之中,成為一種標準化的需求表述體系。用例的使用在RUP中被推崇備至,整個(gè)RUP流程都被稱(chēng)作是"用例驅動(dòng)"(Use-Case Driven)的,各種類(lèi)型的開(kāi)發(fā)活動(dòng)包括項目管理、分析設計、測試、實(shí)現等都是以系統用例為主要輸入工件,用例模型奠定了整個(gè)系統軟件開(kāi)發(fā)的基礎。 1. 什么是用例? 在介始用例方法之前,我們首先來(lái)看一下傳統的需求表述方式-"軟件需求規約"(Software Requirement Specification)。傳統的軟件需求規約基本上采用的是功能分解的方式來(lái)描述系統功能,在這種表述方式中,系統功能被分解到各個(gè)系統功能模塊中,我們通過(guò)描述細分的系統模塊的功能來(lái)達到描述整個(gè)系統功能的目的。一個(gè)典型的軟件需求規約可能具有以下形式: ![]() 采用這種方法來(lái)描述系統需求,非常容易混淆需求和設計的界限,這樣的表述實(shí)際上已經(jīng)包含了部分的設計在內。由此常常導致這樣的迷惑:系統需求應該詳細到何種程度?一個(gè)極端就是需求可以詳細到概要設計,因為這樣的需求表述既包含了外部需求也包含了內部設計。在有些公司的開(kāi)發(fā)流程中,這種需求被稱(chēng)為"內部需求",而對應于用戶(hù)的原始要求則被稱(chēng)之為"外部需求"。 功能分解方法的另一個(gè)缺點(diǎn)是這種方法分割了各項系統功能的應用環(huán)境,從各項功能項入手,你很難了解到這些功能項是如何相互關(guān)聯(lián)來(lái)實(shí)現一個(gè)完成的系統服務(wù)的。所以在傳統的SRS文檔中,我們往往需要另外一些章節來(lái)描述系統的整體結構及各部分之間的相互關(guān)聯(lián),這些內容使得SRS需求更象是一個(gè)設計文檔。 1.1 參與者和用例 從用戶(hù)的角度來(lái)看,他們并不想了解系統的內部結構和設計,他們所關(guān)心的是系統所能提供的服務(wù),也就是被開(kāi)發(fā)出來(lái)的系統將是如何被使用的,這就用例方法的基本思想。用例模型主要由以下模型元素構成:
這大三種模型元素在UML中的表述如下圖所示。 ![]() 以銀行自動(dòng)提款機(ATM)為例,它的主要功能可以由下面的用例圖來(lái)表示。ATM的主要使用者是銀行客戶(hù),客戶(hù)主要使用自動(dòng)提款機來(lái)進(jìn)行銀行帳戶(hù)的查詢(xún)、提款和轉帳交易。 ![]() 通訊關(guān)聯(lián)表示的是參與者和用例之間的關(guān)系,箭頭表示在這一關(guān)系中哪一方是對話(huà)的主動(dòng)發(fā)起者,箭頭所指方是對話(huà)的被動(dòng)接受者;如果你不想強調對話(huà)中的主動(dòng)與被動(dòng)關(guān)系,可以使用不帶箭頭的關(guān)聯(lián)實(shí)線(xiàn)。在參與者和用例之間的信息流不是由通訊關(guān)聯(lián)來(lái)表示的,該信息流是缺省存在的(用例本身描述的就是參與者和系統之間的對話(huà)),并且信息流向是雙向的,它與通訊關(guān)聯(lián)箭頭所指的方向亳無(wú)關(guān)系。 1.2 用例的內容 用例圖使我們對系統的功能有了一個(gè)整體的認知,我們可以知道有哪些參與者會(huì )與系統發(fā)生交互,每一個(gè)參與者需要系統為它提供什么樣的服務(wù)。用例描述的是參與者與系統之間的對話(huà),但是這個(gè)對話(huà)的細節并沒(méi)有在用例圖中表述出來(lái),針對每一個(gè)用例我們可以用事件流來(lái)描述這一對話(huà)的細節內容。如在A(yíng)TM系統中的"提款"用例可以用事件流表述如下: 提款-基本事件流 1. 用戶(hù)插入信用卡 2. 輸入密碼 3. 輸入提款金額 4. 提取現金 5. 退出系統,取回信用卡 但是這只描述了提款用例中最順利的一種情況,作為一個(gè)實(shí)用的系統,我們還必須考慮可能發(fā)生的各種其他情況,如信用卡無(wú)效、輸入密碼錯、用戶(hù)賬號中的現金余額不夠等,所有這些可能發(fā)生的各種情況(包括正常的和異常的)被稱(chēng)之為用例的場(chǎng)景(Scenario),場(chǎng)景也被稱(chēng)作是用例的實(shí)例(Instance)。在用例的各種場(chǎng)景中,最常見(jiàn)的場(chǎng)景是用基本流(Basic Flow)來(lái)描述的,其他的場(chǎng)景則是用備選流(Alternative Flow)來(lái)描述。對于A(yíng)TM系統中的"提款"用例,我們可以得到如下一些備選流: 提款-備選事件流 備選流一:用戶(hù)可以在基本流中的任何一步選擇退出,轉至基本流步驟5。 備選流二:在基本流步驟1中,用戶(hù)插入無(wú)效信用卡,系統顯示錯誤并退出信用卡,用例結束。 備選流三:在基本流步驟2中,用戶(hù)輸入錯誤密碼,系統顯示錯誤并提示用戶(hù)重新輸入密碼,重新回到基本流步驟2;三次輸入密碼錯誤后,信用卡被系統沒(méi)收,用例結束。 … 通過(guò)基本流與備選流的組合,就可以將用例所有可能發(fā)生的各種場(chǎng)景全部描述清楚。我們在描述用例的事件流的時(shí)候,就是要盡可能地將所有可能的場(chǎng)景都描述出來(lái),以保證需求的完備性。 1.3 用例方法的優(yōu)點(diǎn) 用例方法完全是站在用戶(hù)的角度上(從系統的外部)來(lái)描述系統的功能的。在用例方法中,我們把被定義系統看作是一個(gè)黑箱,我們并不關(guān)心系統內部是如何完成它所提供的功能的。用例方法首先描述了被定義系統有哪些外部使用者(抽象成為Actor),這些使用者與被定義系統發(fā)生交互;針對每一參與者,用例方法又描述了系統為這些參與者提供了什么樣的服務(wù)(抽象成為Use Case),或者說(shuō)系統是如何被這些參與者使用的。所以從用例圖中,我們可以得到對于被定義系統的一個(gè)總體印象。 與傳統的功能分解方式相比,用例方法完全是從外部來(lái)定義系統的功能,它把需求與設計完全分離開(kāi)來(lái)。在面向對象的分析設計方法中,用例模型主要用于表述系統的功能性需求,系統的設計主要由對象模型來(lái)記錄表述。另外,用例定義了系統功能的使用環(huán)境與上下文,每一個(gè)用例描述的是一個(gè)完整的系統服務(wù)。用例方法比傳統的SRS更易于被用戶(hù)所理解,它可以作為開(kāi)發(fā)人員和用戶(hù)之間針對系統需求進(jìn)行溝通的一個(gè)有效手段。 在RUP中,用例被作為整個(gè)軟件開(kāi)發(fā)流程的基礎,很多類(lèi)型的開(kāi)發(fā)活動(dòng)都把用例作為一個(gè)主要的輸入工件(Artifact),如項目管理、分析設計、測試等。根據用例來(lái)對目標系統進(jìn)行測試,可以根據用例中所描述的環(huán)境和上下文來(lái)完整地測試一個(gè)系統服務(wù),可以根據用例的各個(gè)場(chǎng)景(Scenario)來(lái)設計測試用例,完全地測試用例的各種場(chǎng)景可以保證測試的完備性。
2. 建立用例模型 使用用例的方法來(lái)描述系統的功能需求的過(guò)程就是用例建模,用例模型主要包括以下兩部分內容:
在用例建模的過(guò)程中,我們建議的步聚是先找出參與者,再根據參與者確定每個(gè)參與者相關(guān)的用例,最后再細化每一個(gè)用例的用例規約。 2.1 尋找參與者 所謂的參與者是指所有存在于系統外部并與系統進(jìn)行交互的人或其他系統。通俗地講,參與者就是我們所要定義系統的使用者。尋找參與者可以從以下問(wèn)題入手:
這些問(wèn)題有助于我們抽象出系統的參與者。對于A(yíng)TM機的例子,回答這些問(wèn)題可以使我們找到更多的參與者:操作員負責維護和管理ATM機系統、ATM機也需要與后臺服務(wù)器進(jìn)行通訊以獲得有關(guān)用戶(hù)賬號的相關(guān)信息。 ![]() 2.1.1 系統邊界決定了參與者 參與者是由系統的邊界所決定的,如果我們所要定義的系統邊界僅限于A(yíng)TM機本身,那么后臺服務(wù)器就是一個(gè)外部的系統,可以抽象為一個(gè)參與者。 ![]() 如果我們所要定義的系統邊界擴大至整個(gè)銀行系統,ATM機和后臺服務(wù)器都是整個(gè)銀行系統的一部分,這時(shí)候后臺服務(wù)器就不再被抽象成為一個(gè)參與者。 ![]() 值得注意的是,用例建模時(shí)不要將一些系統的組成結構作為參與者來(lái)進(jìn)行抽象,如在A(yíng)TM機系統中,打印機只是系統的一個(gè)組成部分,不應將它抽象成一個(gè)獨立的參與者;在一個(gè)MIS管理系統中,數據庫系統往往只作為系統的一個(gè)組成部分,一般不將其單獨抽象成一個(gè)參與者。 2.1.2 特殊的參與者――系統時(shí)鐘 有時(shí)候我們需要在系統內部定時(shí)地執行一些操作,如檢測系統資源使用情況、定期地生成統計報表等等。從表面上看,這些操作并不是由外部的人或系統觸發(fā)的,應該怎樣用用例方法來(lái)表述這一類(lèi)功能需求呢?對于這種情況,我們可以抽象出一個(gè)系統時(shí)鐘或定時(shí)器參與者,利用該參與者來(lái)觸發(fā)這一類(lèi)定時(shí)操作。從邏輯上,這一參與者應該被理解成是系統外部的,由它來(lái)觸發(fā)系統所提供的用例對話(huà)。 ![]() 2.2 確定用例 找到參與者之后,我們就可以根據參與者來(lái)確定系統的用例,主要是看各參與者需要系統提供什么樣的服務(wù),或者說(shuō)參與者是如何使用系統的。尋找用例可以從以下問(wèn)題入手(針對每一個(gè)參與者):
綜合以上所述,ATM系統的用例圖可表示如下, ![]() 在用例的抽取過(guò)程中,必須注意:用例必須是由某一個(gè)主角觸發(fā)而產(chǎn)生的活動(dòng),即每個(gè)用例至少應該涉及一個(gè)主角。如果存在與主角不進(jìn)行交互的用例,就可以考慮將其并入其他用例;或者是檢查該用例相對應的參與者是否被遺漏,如果是,則補上該參與者。反之,每個(gè)參與者也必須至少涉及到一個(gè)用例,如果發(fā)現有不與任何用例相關(guān)聯(lián)的參與者存在,就應該考慮該參與者是如何與系統發(fā)生對話(huà)的,或者由參與者確定一個(gè)新的用例,或者該參與者是一個(gè)多余的模型元素,應該將其刪除。 可視化建模的主要目的之一就是要增強團隊的溝通,用例模型必須是易于理解的。用例建模往往是一個(gè)團隊開(kāi)發(fā)的過(guò)程,系統分析員在建模過(guò)程中必須注意參與者和用例的名稱(chēng)應該符合一定的命名約定,這樣整個(gè)用例模型才能夠符合一定的風(fēng)格。如參與者的名稱(chēng)一般都是名詞,用例名稱(chēng)一般都是動(dòng)賓詞組等。 對于同一個(gè)系統,不同的人對于參與者和用例都可能有不同的抽象結果,因而得到不同的用例模型。我們需要在多個(gè)用例模型方案中選擇一種"最佳"(或"較佳")的結果,一個(gè)好的用例模型應該能夠容易被不同的涉眾所理解,并且不同的涉眾對于同一用例模型的理解應該是一致的。 2.3 描述用例規約 應該避免這樣一種誤解――認為由參與者和用例構成的用例圖就是用例模型,用例圖只是在總體上大致描述了系統所能提供的各種服務(wù),讓我們對于系統的功能有一個(gè)總體的認識。除此之外,我們還需要描述每一個(gè)有例的詳細信息,這些信息包含在用例規約中,用例模型是由用例圖和每一個(gè)用例的詳細描述――用例規約所組成的。RUP中提供了用例規約的模板,每一個(gè)用例的用例規約都應該包含以下內容:
用例規約基本上是用文本方式來(lái)表述的,為了更加清晰地描述事件流,也可以選擇使用狀態(tài)圖、活動(dòng)圖或序列圖來(lái)輔助說(shuō)明。只要有助于表達的簡(jiǎn)潔明了,就可以在用例中任意粘貼用戶(hù)界面和流程的圖形化顯示方式,或是其他圖形。如活動(dòng)圖有助于描述復雜的決策流程,狀態(tài)轉移圖有助于描述與狀態(tài)相關(guān)的系統行為,序列圖適合于描述基于時(shí)間順序的消息傳遞。 2.3.1 基本流 基本流描述的是該用例最正常的一種場(chǎng)景,在基本流中系統執行一系列活動(dòng)步驟來(lái)響應參與者提出的服務(wù)請求。我們建議用以下格式來(lái)描述基本流: 1) 每一個(gè)步驟都需要用數字編號以清楚地標明步驟的先后順序。 2) 用一句簡(jiǎn)短的標題來(lái)概括每一步驟的主要內容,這樣閱讀者可以通過(guò)瀏覽標題來(lái)快速地了解用例的主要步驟。在用例建模的早期,我們也只需要描述到事件流步驟標題這一層,以免過(guò)早地陷入到用例描述的細節中去。 3) 當整個(gè)用例模型基本穩定之后,我們再針對每一步驟詳細描述參與者和系統之間所發(fā)生的交互。建議采用雙向(roundtrip)描述法來(lái)保證描述的完整性,即每一步驟都需要從正反兩個(gè)方面來(lái)描述:(1)參與者向系統提交了什么信息;(2)對此系統有什么樣的響應。具體例子請參見(jiàn)附錄。 在描述參與者和系統之間的信息交換時(shí),需指出來(lái)回傳遞的具體信息。例如,只表述參與者輸入了客戶(hù)信息就不夠明確,最好明確地說(shuō)參與者輸入了客戶(hù)姓名和地址。通??梢岳迷~匯表讓用例的復雜性保持在可控范圍內,可以在詞匯表中定義客戶(hù)信息等內容,使用例不至于陷入過(guò)多的細節。 2.3.2 備選流 備選流負責描述用例執行過(guò)程中異常的或偶爾發(fā)生的一些情況,備選流和基本流的組合應該能夠覆蓋該用例所有可能發(fā)生的場(chǎng)景。在描述備選流時(shí),應該包括以下幾個(gè)要素: 1) 起點(diǎn):該備選流從事件流的哪一步開(kāi)始; 2) 條件:在什么條件下會(huì )觸發(fā)該備選流; 3) 動(dòng)作:系統在該備選流下會(huì )采取哪些動(dòng)作; 4) 恢復:該備選流結束之后,該用例應如何繼續執行。 備選流的描述格式可以與基本流的格式一致,也需要編號并以標題概述其內容,編號前可以加以字母前綴A(Alternative)以示與基本流步驟相區別。 2.3.3 用例場(chǎng)景 用例在實(shí)際執行的時(shí)候會(huì )有很多的不同情況發(fā)生,稱(chēng)之為用例場(chǎng)景;也可以說(shuō)場(chǎng)景是用例的實(shí)例,我們在描述用例的時(shí)候要覆蓋所有的用例場(chǎng)景,否則就有可能導致需求的遺漏。在用例規約中,場(chǎng)景的描述可以由基本流和備選流的組合來(lái)表示。場(chǎng)景既可以幫助我們防止需求的遺漏,同時(shí)也可以對后續的開(kāi)發(fā)工作起到很大的幫助:開(kāi)發(fā)人員必須實(shí)現所有的場(chǎng)景、測試人員可以根據用例場(chǎng)景來(lái)設計測試用例。 2.3.4 特殊需求 特殊需求通常是非功能性需求,它為一個(gè)用例所專(zhuān)有,但不適合在用例的事件流文本中進(jìn)行說(shuō)明。特殊需求的例子包括法律或法規方面的需求、應用程序標準和所構建系統的質(zhì)量屬性(包括可用性、可靠性、性能或支持性需求等)。此外,其他一些設計約束,如操作系統及環(huán)境、兼容性需求等,也可以在此節中記錄。 需要注意的是,這里記錄的是專(zhuān)屬于該用例的特殊需求;對于一些全局的非功能性需求和設計約束,它們并不是該用例所專(zhuān)有的,應把它們記錄在《補充規約》中。 2.3.5 前置和后置條件 前置條件是執行用例之前必須存在的系統狀態(tài),后置條件是用例一執行完畢后系統可能處于的一組狀態(tài)。 2.4 檢查用例模型 用例模型完成之后,可以對用例模型進(jìn)行檢查,看看是否有遺漏或錯誤之處。主要可以從以下幾個(gè)方面來(lái)進(jìn)行檢查:
3. 系統需求 RUP中根據FURPS+模型將系統需求分為以下幾類(lèi):
除了第一項功能性需求之外的其他需求都歸之為非功能性需求。 3.1 需求工件集 用例模型主要用于描述系統的功能性需求,對于其他的非功能性需要用其他文檔來(lái)記錄。RUP中定義了如下的需求工件集合。
在實(shí)際應用中,除了這些工件之外,我們還可以根據實(shí)際需求靈活選用其他形式的文檔來(lái)補充說(shuō)明需求。并不是所有的系統需求都適保合用用例模型來(lái)描述的,如編譯器,我們很難用用例方法來(lái)表述它所處理的語(yǔ)言的方法規則,在這種情況下,采用傳統的BNF范式來(lái)表述更加合適一些。在電信軟件行業(yè)中,很多電信標準都是采用SDL語(yǔ)言來(lái)描述的,我們也不必用UML來(lái)改寫(xiě)這些標準(UML對SDL存在著(zhù)這樣的兼容性),只需將SDL形式的電信標準作為需求工件之一,在其他工件中對其加以引用就可以了??傊?,萬(wàn)萬(wàn)不可拘泥于用例建模的形式,應靈活運用各種方式的長(cháng)處。 3.2 補充規約 補充規約記錄那些在用例模型中不易表述的系統需求,主要包括以下內容。
3.3 詞匯表 詞匯表主要用于定義項目特定的術(shù)語(yǔ),它有助于開(kāi)發(fā)人員對項目中所用的術(shù)語(yǔ)有統一的理解和使用,它也是后續階段中進(jìn)行對象抽象的基礎。
4. 調整用例模型 在一般的用例圖中,我們只表述參與者和用例之間的關(guān)系,即它們之間的通訊關(guān)聯(lián)。除此之外,我們還可以描述參與者與參與者之間的泛化(generalization)、用例和用例之間的包含(include)、擴展(extend)和泛化(generalization)關(guān)系。我們利用這些關(guān)系來(lái)調整已有的用例模型,把一些公共的信息抽取出來(lái)重用,使得用例模型更易于維護。但是在應用中要小心選用這些關(guān)系,一般來(lái)說(shuō)這些關(guān)系都會(huì )增加用例和關(guān)系的個(gè)數,從而增加用例模型的復雜度。而且一般都是在用例模型完成之后才對用例模型進(jìn)行調整,所以在用例建模的初期不必要急于抽象用例之間的關(guān)系。 4.1 參與者之間的關(guān)系 參與者之間可以有泛化(Generalization)關(guān)系(或稱(chēng)為"繼承"關(guān)系)。例如在需求分析中常見(jiàn)的權限控制問(wèn)題(如下圖所示),一般的用戶(hù)只可以使用一些常規的操作,而管理員除了常規操作之外還需要進(jìn)行一些系統管理工作,操作員既可以進(jìn)行常規操作又可以進(jìn)行一些配置操作。 ![]() 在這個(gè)例子中我們會(huì )發(fā)現管理員和操作員都是一種特殊的用戶(hù),他們擁有普通用戶(hù)所擁有的全部權限,此外他們還有自己獨有的權限。這里我們可進(jìn)一步把普通用戶(hù)和管理員、操作員之間的關(guān)系抽象成泛化(Generalization)關(guān)系,管理員和操作員可以繼承普通用戶(hù)的全部特性(包括權限),他們又可以有自己獨有的特性(如操作、權限等)。這樣可以顯著(zhù)減速少用例圖中通訊關(guān)聯(lián)的個(gè)數,簡(jiǎn)化用例模型,使之更易于理解。 ![]() 4.2 用例之間的關(guān)系 用例描述的是系統外部可見(jiàn)的行為,是系統為某一個(gè)或幾個(gè)參與者提供的一段完整的服務(wù)。從原則上來(lái)講,用例之間都是并列的,它們之間并不存在著(zhù)包含從屬關(guān)系。但是從保證用例模型的可維護性和一致性角度來(lái)看,我們可以在用例之間抽象出包含(include)、擴展(extend)和泛化(generalization)這幾種關(guān)系。這幾種關(guān)系都是從現有的用例中抽取出公共的那部分信息,然后通后過(guò)不同的方法來(lái)重用這部公共信息,以減少模型維護的工作量。 4.2.1 包含(include) 包含關(guān)系是通過(guò)在關(guān)聯(lián)關(guān)系上應用<<include>>構造型來(lái)表示的,如下圖所示。它所表示的語(yǔ)義是指基礎用例(Base)會(huì )用到被包含用例(Inclusion),具體地講,就是將被包含用例的事件流插入到基礎用例的事件流中。 ![]() 包含關(guān)系是UML1.3中的表述,在UML1.1中,同等語(yǔ)義的關(guān)系被表述為使用(uses),如下圖。 ![]() 在A(yíng)TM機中,如果查詢(xún)、取現、轉帳這三個(gè)用例都需要打印一個(gè)回執給客戶(hù),我們就可以把打印回執這一部分內容提取出來(lái),抽象成為一個(gè)單獨的用例"打印回執",而原有的查詢(xún)、取現、轉帳三個(gè)例都會(huì )包含這個(gè)用例。每當以后要對打印回執部分的需求進(jìn)行修改時(shí),就只需要改動(dòng)一個(gè)用例,而不用在每一個(gè)用例都作相應修改,這樣就提高了用例模型的可維護性。 ![]() 在基礎用例的事件流中,我們只需要引用被包含用例即可。 查詢(xún)-基本事件流 1. 用戶(hù)插入信用卡 2. 輸入密碼 3. 選擇查詢(xún) 4. 查看賬號余額 5. 包含用例"打印回執" 6. 退出系統,取回信用卡 在這個(gè)例子中,多個(gè)用例需要用到同一段行為,我們可以把這段共同的行為單獨抽象成為一個(gè)用例,然后讓其他的用例來(lái)包含這一用例。從而避免在多個(gè)用例中重復性地描述同一段行為,也可以防止該段行為在多個(gè)用例中的描述出現不一致性。當需要修改這段公共的需求時(shí),我們也只需要修改一個(gè)用例,避免同時(shí)修改多個(gè)用例而產(chǎn)生的不一致性和重復性工作。 有時(shí)當某一個(gè)用例的事件流過(guò)于復雜時(shí),為了簡(jiǎn)化用例的描述,我們也可以把某一段事件流抽象成為一個(gè)被包含的用例。這種情況類(lèi)似于在過(guò)程設計語(yǔ)言中,將程序的某一段算法封裝成一個(gè)子過(guò)程,然后再從主程序中調用這一子過(guò)程。 4.2.2 擴展(extend) 擴展(extend)關(guān)系如下圖所示,基礎用例(Base)中定義有一至多個(gè)已命名的擴展點(diǎn),擴展關(guān)系是指將擴展用例(Extension)的事件流在一定的條件下按照相應的擴展點(diǎn)插入到基礎用例(Base)中。對于包含關(guān)系而言,子用例中的事件流是一定插入到基礎用例中去的,并且插入點(diǎn)只有一個(gè)。而擴展關(guān)系可以根據一定的條件來(lái)決定是否將擴展用例的事件流插入基礎用例事件流,并且插入點(diǎn)可以有多個(gè)。 ![]() 例如對于電話(huà)業(yè)務(wù),可以在基本通話(huà)(Call)業(yè)務(wù)上擴展出一些增值業(yè)務(wù)如:呼叫等待(Call Waiting)和呼叫轉移(Call Transfer)。我們可以用擴展關(guān)系將這些業(yè)務(wù)的用例模型描述如下。 ![]() ![]() 在這個(gè)例子中,呼叫等待和呼叫轉移都是對基本通話(huà)用例的擴展,但是這兩個(gè)用例只有在一定的條件下(如應答方正忙或應答方無(wú)應答)才會(huì )將被擴展用例的事件流嵌入基本通話(huà)用例的擴展點(diǎn),并重用基本通話(huà)用例中的事件流。 值得注意的是擴展用例的事件流往往可以也可抽象為基礎用例的備選流,如上例中的呼叫等待和呼叫轉移都可以作為基本通話(huà)用例的備選流而存在。但是基本通話(huà)用例已經(jīng)是一個(gè)很復雜的用例了,選用擴展關(guān)系將增值業(yè)務(wù)抽象成為單獨的用例可以避免基礎用例過(guò)于復雜,并且把一些可選的操作獨立封裝在另外的用例中。 4.2.3 泛化(generalization) 當多個(gè)用例共同擁有一種類(lèi)似的結構和行為的時(shí)候,我們可以將它們的共性抽象成為父用例,其他的用例作為泛化關(guān)系中的子用例。在用例的泛化關(guān)系中,子用例是父用例的一種特殊形式,子用例繼承了父用例所有的結構、行為和關(guān)系。在實(shí)際應用中很少使用泛化關(guān)系,子用例中的特殊行為都可以作為父用例中的備選流存在。 ![]() 以下是一個(gè)用例泛化關(guān)系的例子,執行交易是一種交易抽象,執行房產(chǎn)交易和執行證券交易都是一種特殊的交易形式。 用例泛化關(guān)系中的事件流示例如下: ![]() 4.3 調整用例模型 用例模型建成之后,我們可以對用例模型進(jìn)行檢視,看是否可以進(jìn)一步簡(jiǎn)化用例模型、提高重用程度、增加模型的可維護性。主要可以從以下檢查點(diǎn)(checkpoints)入手:
5. 管理用例模型復雜度 一般小型的系統,其用例模型中包含的參與者和用例不會(huì )太多,一個(gè)用例圖就可以容納所有的參與者,所有的參與者和用例也可以并存于同一個(gè)層次結構中。對于較復雜的大中型系統,用例模型中的參與者和用例會(huì )大大增加,我們需要一些方法來(lái)有效地管理由于規模上升而造成的復雜度。 5.1 用例包 包(Package)是UML中最常用的管理模型復雜度的機制,包也是UML中語(yǔ)義最簡(jiǎn)單的一種模型元素,它就是一種容器,在包中可以容納其他任意的模型元素(包括其他的包)。在用例模型中,我們可以用構造型(Sterotype)<<use case>>來(lái)擴展標準UML包的語(yǔ)義,這種新的包叫作用例包(Use Case Package),用于分類(lèi)管理用例模型中的模型元素。 我們可以根據參與者和用例的特性來(lái)對它們進(jìn)行分類(lèi),分別置于不同的用例包管理之下。例如對于一個(gè)大型的企業(yè)管理信息系統,我們可以根據參與者和用例的內容將它們分別歸于人力資源、財務(wù)、采購、銷(xiāo)售、客務(wù)服務(wù)這些用例包之下。這樣我們將整個(gè)用例模型劃分成為兩個(gè)層次,在第一層次我們看到的是系統功能總共分為五部分,在第二層次我們可以分別看到每一用例包內部的參與者和用例。 ![]() 一個(gè)用例模型需要有多少個(gè)用例包取決你想怎么樣來(lái)管理用例模型的復雜度(包括參與者和用例的個(gè)數,以及它們之間的相互關(guān)系)。UML中的包其實(shí)就類(lèi)似于文件系統中的目錄,文件數量少的時(shí)候不需要額外的目錄,文件數量一多就需要有多個(gè)目錄來(lái)分類(lèi)管理,同樣一組文件不同的人會(huì )創(chuàng )建不同的目錄結構來(lái)進(jìn)行管理,關(guān)鍵是要保證在目錄結構下每一個(gè)文件都要易于訪(fǎng)問(wèn)。同樣的道理存在于用例建模之中,如何創(chuàng )建用例包以及用例包的個(gè)數取決于不同的系統和系統分析員,但要保證整個(gè)用例模型易于理解。 5.2 用例的粒度 我的系統需要有多少個(gè)用例?這是很多人在用例建模時(shí)會(huì )產(chǎn)生的疑惑。描述同一個(gè)系統,不同的人會(huì )產(chǎn)生不同的用例模型。例如對于各種系統中常見(jiàn)的"維護用戶(hù)"用例,它里面包含了添加用戶(hù)、修改用戶(hù)信息、刪除用戶(hù)等操作,這些操作在該用例的事件流可以表述成為基本流的子事件流(subflow)。 ![]() 維護用戶(hù)-基本事件流 該基本流由三個(gè)子事件流構成: 1) 添加用戶(hù)子事件流 2) 修改用戶(hù) 子事件流 3) 刪除用戶(hù)子事件流 但是你也可以根據該用例中的具體操作把它抽象成為三個(gè)用例,它所表示的系統需求和單個(gè)用例的模型是完全一樣的。 ![]() 應該如何確定用例的粒度呢?在一次技術(shù)研討會(huì )上,有人問(wèn)起Ivar Jacoboson博士,一個(gè)系統需要有多少個(gè)用例?大師的回答是20個(gè),當然他的意思是最好將用例模型的規??刂圃趲资畟€(gè)用例左右,這樣比較容易來(lái)管理用例模型的復雜度。在用例個(gè)數大致確定的條件下,我們就很容易來(lái)確定用例粒度的大小。對于較復雜的系統,我們需要控制用例模型一級的復雜度,所以可以將復雜度適當地移往每一個(gè)用例的內部,也就是讓一個(gè)用例包含較多的需求信息量。對于比較簡(jiǎn)單的系統,我們則可以將復雜度適度地曝露在模型一級,也就是我們可以將較復雜的用例分解成為多個(gè)用例。 用例的粒度不但決定了用例模型級的復雜度,而且也決定了每一個(gè)用例內部的復雜度。我們應該根據每個(gè)系統的具體情況,因時(shí)因宜地來(lái)把握各個(gè)層次的復雜度,在盡可能保證整個(gè)用例模型的易理解性前提下決定用例的大小和數目。 5.3 用例圖 用例圖的主要作用是描述參與者和用例之間的關(guān)系,簡(jiǎn)單的系統中只需要有一個(gè)用例圖就可以把所有的關(guān)系都描述清楚。復雜的系統中可以有多個(gè)用例圖,例如每個(gè)用例包都可以有一個(gè)獨立的用例圖來(lái)描述該用例包中所有的參與者和用例的關(guān)系。 在一個(gè)用例模型中,如果參與者和用例之間存在著(zhù)多對多的關(guān)系,并且他們之間的關(guān)系比較復雜,如果在同一個(gè)用例圖中表述所有的參與者和用例就顯得不夠清晰,這時(shí)我們可創(chuàng )建多個(gè)用例圖來(lái)分別表示各種關(guān)系。 ![]() 如果想要強調某一個(gè)參與者和多個(gè)用例的關(guān)系,你就可以以該參與者為中心,用一個(gè)用例圖表述出該參與者和多個(gè)用例之間的關(guān)系。在這個(gè)用例圖中,我們強調的是該參與者會(huì )使用系統所提供的哪些服務(wù)。 ![]() 如果想要強調某一個(gè)用例和多個(gè)參與者之間的關(guān)系,你就可以以該用例為中心,用一個(gè)用例圖表述出該用例和多個(gè)參與者之間的關(guān)系。在這個(gè)用例圖中,我們強調的是該用例會(huì )涉及到哪些參與者,或者說(shuō)該用例所表示的系統服務(wù)有哪些使用者。 ![]() 總之在用例建模過(guò)程中,你可以根據自己的需要創(chuàng )建任意多個(gè)用例圖,用不同的用例來(lái)強調參與者和用例之間不同的關(guān)系。但是最重要的是要考慮整個(gè)用例模型的可理解性,如果可以用一個(gè)用例圖把意思表述清楚,就不要再用第二個(gè),因為越是簡(jiǎn)潔的模型越易于理解。 |
聯(lián)系客服