[推薦]用例建模指南

                            [推薦]用例建模指南 
                            作者:傅純一 選自: IBM 
                            轉載自:http://www.uml.org.cn/oobject/200607035.htm

 1. 什麼是用例?

   在介始用例方法之前,我們首先來看一下傳統的需求表述方式-"軟件需求規約"(Software Requirement Specification)。傳統的軟件需求規約基本上採用的是功能分解的方式來描述系統功能,在這種表述方式中,系統功能被分解到各個系統功能模塊中,我們通過描述細分的系統模塊的功能來達到描述整個系統功能的目的。一個典型的軟件需求規約可能具有以下形式:

  採用這種方法來描述系統需求,非常容易混淆需求和設計的界限,這樣的表述實際上已經包含了部分的設計在內。由此常常導致這樣的迷惑:系統需求應該詳細到何種程度?一個極端就是需求可以詳細到概要設計,因爲這樣的需求表述既包含了外部需求也包含了內部設計。在有些公司的開發流程中,這種需求被稱爲"內部需求",而對應於用戶的原始要求則被稱之爲"外部需求"

  功能分解方法的另一個缺點是這種方法分割了各項系統功能的應用環境,從各項功能項入手,你很難了解到這些功能項是如何相互關聯來實現一個完成的系統服務的。所以在傳統的SRS文檔中,我們往往需要另外一些章節來描述系統的整體結構及各部分之間的相互關聯,這些內容使得SRS需求更象是一個設計文檔。

1.1 參與者和用例

   從用戶的角度來看,他們並不想了解系統的內部結構和設計,他們所關心的是系統所能提供的服務,也就是被開發出來的系統將是如何被使用的,這就用例方法的基本思想。用例模型主要由以下模型元素構成:

  • 參與者(Actor)
    參與者是指存在於被定義系統外部並與該系統發生交互的人或其他系統,他們代表的是系統的使用者或使用環境。
  • 用例(Use Case)
    用例用於表示系統所提供的服務,它定義了系統是如何被參與者所使用的,它描述的是參與者爲了使用系統所提供的某一完整功能而與系統之間發生的一段對話。
  • 通訊關聯(Communication Association)
    通訊關聯用於表示參與者和用例之間的對應關係,它表示參與者使用了系統中的哪些服務(用例),或者說系統所提供的服務(用例)是被哪些參與者所使用的。  這大三種模型元素在UML中的表述如下圖所示。

       

  以銀行自動提款機(ATM)爲例,它的主要功能可以由下面的用例圖來表示。ATM的主要使用者是銀行客戶,客戶主要使用自動提款機來進行銀行帳戶的查詢、提款和轉帳交易。

           

  通訊關聯表示的是參與者和用例之間的關係,箭頭表示在這一關係中哪一方是對話的主動發起者,箭頭所指方是對話的被動接受者;如果你不想強調對話中的主動與被動關係,可以使用不帶箭頭的關聯實線。在參與者和用例之間的信息流不是由通訊關聯來表示的,該信息流是缺省存在的(用例本身描述的就是參與者和系統之間的對話),並且信息流向是雙向的,它與通訊關聯箭頭所指的方向亳無關係。

1.2 用例的內容

   用例圖使我們對系統的功能有了一個整體的認知,我們可以知道有哪些參與者會與系統發生交互,每一個參與者需要系統爲它提供什麼樣的服務。用例描述的是參與者與系統之間的對話,但是這個對話的細節並沒有在用例圖中表述出來,針對每一個用例我們可以用事件流來描述這一對話的細節內容。如在ATM系統中的"提款"用例可以用事件流表述如下:

  提款-基本事件流
   1. 用戶插入信用卡
   2. 輸入密碼
   3. 輸入提款金額
   4. 提取現金
   5. 退出系統,取回信用卡

  但是這隻描述了提款用例中最順利的一種情況,作爲一個實用的系統,我們還必須考慮可能發生的各種其他情況,如信用卡無效、輸入密碼錯、用戶帳號中的現金餘額不夠等,所有這些可能發生的各種情況(包括正常的和異常的)被稱之爲用例的場景(Scenario),場景也被稱作是用例的實例(Instance)。在用例的各種場景中,最常見的場景是用基本流(Basic Flow)來描述的,其他的場景則是用備選流(Alternative Flow)來描述。對於ATM系統中的"提款"用例,我們可以得到如下一些備選流:

  提款-備選事件流

  備選流一:用戶可以在基本流中的任何一步選擇退出,轉至基本流步驟5

  備選流二:在基本流步驟1中,用戶插入無效信用卡,系統顯示錯誤並退出信用卡,用例結束。

  備選流三:在基本流步驟2中,用戶輸入錯誤密碼,系統顯示錯誤並提示用戶重新輸入密碼,重新回到基本流步驟2;三次輸入密碼錯誤後,信用卡被系統沒收,用例結束。

  

  通過基本流與備選流的組合,就可以將用例所有可能發生的各種場景全部描述清楚。我們在描述用例的事件流的時候,就是要儘可能地將所有可能的場景都描述出來,以保證需求的完備性。

1.3 用例方法的優點

   用例方法完全是站在用戶的角度上(從系統的外部)來描述系統的功能的。在用例方法中,我們把被定義系統看作是一個黑箱,我們並不關心繫統內部是如何完成它所提供的功能的。用例方法首先描述了被定義系統有哪些外部使用者(抽象成爲Actor),這些使用者與被定義系統發生交互;針對每一參與者,用例方法又描述了系統爲這些參與者提供了什麼樣的服務(抽象成爲Use Case),或者說系統是如何被這些參與者使用的。所以從用例圖中,我們可以得到對於被定義系統的一個總體印象。

  與傳統的功能分解方式相比,用例方法完全是從外部來定義系統的功能,它把需求與設計完全分離開來。在面向對象的分析設計方法中,用例模型主要用於表述系統的功能性需求,系統的設計主要由對象模型來記錄表述。另外,用例定義了系統功能的使用環境與上下文,每一個用例描述的是一個完整的系統服務。用例方法比傳統的SRS更易於被用戶所理解,它可以作爲開發人員和用戶之間針對系統需求進行溝通的一個有效手段。

  在RUP中,用例被作爲整個軟件開發流程的基礎,很多類型的開發活動都把用例作爲一個主要的輸入工件(Artifact),如項目管理、分析設計、測試等。根據用例來對目標系統進行測試,可以根據用例中所描述的環境和上下文來完整地測試一個系統服務,可以根據用例的各個場景(Scenario)來設計測試用例,完全地測試用例的各種場景可以保證測試的完備性。

2. 建立用例模型

   使用用例的方法來描述系統的功能需求的過程就是用例建模,用例模型主要包括以下兩部分內容:

  • 用例圖(Use Case Diagram)
    確定系統中所包含的參與者、用例和兩者之間的對應關係,用例圖描述的是關於系統功能的一個概述。
  • 用例規約(Use Case Specification)
    針對每一個用例都應該有一個用例規約文檔與之相對應,該文檔描述用例的細節內容。

  在用例建模的過程中,我們建議的步聚是先找出參與者,再根據參與者確定每個參與者相關的用例,最後再細化每一個用例的用例規約。

2.1 尋找參與者

   所謂的參與者是指所有存在於系統外部並與系統進行交互的人或其他系統。通俗地講,參與者就是我們所要定義系統的使用者。尋找參與者可以從以下問題入手:

  • 系統開發完成之後,有哪些人會使用這個系統?
  • 系統需要從哪些人或其他系統中獲得數據?
  • 系統會爲哪些人或其他系統提供數據?
  • 系統會與哪些其他系統相關聯?
  • 系統是由誰來維護和管理的?

  這些問題有助於我們抽象出系統的參與者。對於ATM機的例子,回答這些問題可以使我們找到更多的參與者:操作員負責維護和管理ATM機系統、ATM機也需要與後臺服務器進行通訊以獲得有關用戶帳號的相關信息。

    

2.1.1 系統邊界決定了參與者

  參與者是由系統的邊界所決定的,如果我們所要定義的系統邊界僅限於ATM機本身,那麼後臺服務器就是一個外部的系統,可以抽象爲一個參與者。

    

如果我們所要定義的系統邊界擴大至整個銀行系統,ATM機和後臺服務器都是整個銀行系統的一部分,這時候後臺服務器就不再被抽象成爲一個參與者。

    

    值得注意的是,用例建模時不要將一些系統的組成結構作爲參與者來進行抽象,如在ATM機系統中,打印機只是系統的一個組成部分,不應將它抽象成一個獨立的參與者;在一個MIS管理系統中,數據庫系統往往只作爲系統的一個組成部分,一般不將其單獨抽象成一個參與者。

2.1.2 特殊的參與者――系統時鐘

  有時候我們需要在系統內部定時地執行一些操作,如檢測系統資源使用情況、定期地生成統計報表等等。從表面上看,這些操作並不是由外部的人或系統觸發的,應該怎樣用用例方法來表述這一類功能需求呢?對於這種情況,我們可以抽象出一個系統時鐘或定時器參與者,利用該參與者來觸發這一類定時操作。從邏輯上,這一參與者應該被理解成是系統外部的,由它來觸發系統所提供的用例對話。

    

2.2 確定用例

  找到參與者之後,我們就可以根據參與者來確定系統的用例,主要是看各參與者需要系統提供什麼樣的服務,或者說參與者是如何使用系統的。尋找用例可以從以下問題入手(針對每一個參與者):

  • 參與者爲什麼要使用該系統?
  • 參與者是否會在系統中創建、修改、刪除、訪問、存儲數據?如果是的話,參與者又是如何來完成這些操作的?
  • 參與者是否會將外部的某些事件通知給該系統?
  • 系統是否會將內部的某些事件通知該參與者?

  綜合以上所述,ATM系統的用例圖可表示如下,

 

    在用例的抽取過程中,必須注意:用例必須是由某一個主角觸發而產生的活動,即每個用例至少應該涉及一個主角。如果存在與主角不進行交互的用例,就可以考慮將其併入其他用例;或者是檢查該用例相對應的參與者是否被遺漏,如果是,則補上該參與者。反之,每個參與者也必須至少涉及到一個用例,如果發現有不與任何用例相關聯的參與者存在,就應該考慮該參與者是如何與系統發生對話的,或者由參與者確定一個新的用例,或者該參與者是一個多餘的模型元素,應該將其刪除。

  可視化建模的主要目的之一就是要增強團隊的溝通,用例模型必須是易於理解的。用例建模往往是一個團隊開發的過程,系統分析員在建模過程中必須注意參與者和用例的名稱應該符合一定的命名約定,這樣整個用例模型才能夠符合一定的風格。如參與者的名稱一般都是名詞,用例名稱一般都是動賓詞組等。

  對於同一個系統,不同的人對於 參與者和用例都可能有不同的抽象結果,因而得到不同的用例模型。我們需要在多個用例模型方案中選擇一種"最佳"(或"較佳")的結果,一個好的用例模型應該能夠容易被不同的涉衆所理解,並且不同的涉衆對於同一用例模型的理解應該是一致的。

2.3 描述用例規約

  應該避免這樣一種誤解――認爲由參與者和用例構成的用例圖就是用例模型,用例圖只是在總體上大致描述了系統所能提供的各種服務,讓我們對於系統的功能有一個總體的認識。除此之外,我們還需要描述每一個有例的詳細信息,這些信息包含在用例規約中,用例模型是由用例圖和每一個用例的詳細描述――用例規約所組成的。RUP中提供了用例規約的模板,每一個用例的用例規約都應該包含以下內容:

  • 簡要說明 (Brief Description)
    簡要介紹該用例的作用和目的。
  • 事件流 (Flow of Event)
    包括基本流和備選流,事件流應該表示出所有的場景。
  • 用例場景 (Use-Case Scenario)
    包括成功場景和失敗場景,場景主要是由基本流和備選流組合而成的。
  • 特殊需求 (Special Requirement)
    描述與該用例相關的非功能性需求(包括性能、可靠性、可用性和可擴展性等)和設計約束(所使用的操作系統、開發工具等)。
  • 前置條件 (Pre-Condition)
    執行用例之前系統必須所處的狀態。
  • 後置條件 (Post-Condition)
    用例執行完畢後系統可能處於的一組狀態。

  用例規約基本上是用文本方式來表述的,爲了更加清晰地描述事件流,也可以選擇使用狀態圖、活動圖或序列圖來輔助說明。只要有助於表達的簡潔明瞭,就可以在用例中任意粘貼用戶界面和流程的圖形化顯示方式,或是其他圖形。如活動圖有助於描述複雜的決策流程,狀態轉移圖有助於描述與狀態相關的系統行爲,序列圖適合於描述基於時間順序的消息傳遞。

2.3.1 基本流

  基本流描述的是該用例最正常的一種場景,在基本流中系統執行一系列活動步驟來響應參與者提出的服務請求。我們建議用以下格式來描述基本流:

  (1) 每一個步驟都需要用數字編號以清楚地標明步驟的先後順序。

  (2) 用一句簡短的標題來概括每一步驟的主要內容,這樣閱讀者可以通過瀏覽標題來快速地瞭解用例的主要步驟。在用例建模的早期,我們也只需要描述到事件流步驟標題這一層,以免過早地陷入到用例描述的細節中去。

  (3) 當整個用例模型基本穩定之後,我們再針對每一步驟詳細描述參與者和系統之間所發生的交互。建議採用雙向(roundtrip)描述法來保證描述的完整性,即每一步驟都需要從正反兩個方面來描述:(1)參與者向系統提交了什麼信息;(2)對此係統有什麼樣的響應。具體例子請參見附錄。

  在描述參與者和系統之間的信息交換時,需指出來回傳遞的具體信息。例如,只表述參與者輸入了客戶信息就不夠明確,最好明確地說參與者輸入了客戶姓名和地址。通常可以利用詞彙表讓用例的複雜性保持在可控範圍內,可以在詞彙表中定義客戶信息等內容,使用例不至於陷入過多的細節。

2.3.2 備選流

  備選流負責描述用例執行過程中異常的或偶爾發生的一些情況,備選流和基本流的組合應該能夠覆蓋該用例所有可能發生的場景。在描述備選流時,應該包括以下幾個要素:

  (1) 起點:該備選流從事件流的哪一步開始;

  (2) 條件:在什麼條件下會觸發該備選流;

  (3) 動作:系統在該備選流下會採取哪些動作;

  (4) 恢復:該備選流結束之後,該用例應如何繼續執行。

  備選流的描述格式可以與基本流的格式一致,也需要編號並以標題概述其內容,編號前可以加以字母前綴A(Alternative)以示與基本流步驟相區別。

2.3.3 用例場景

  用例在實際執行的時候會有很多的不同情況發生,稱之爲用例場景;也可以說場景是用例的實例,我們在描述用例的時候要覆蓋所有的用例場景,否則就有可能導致需求的遺漏。在用例規約中,場景的描述可以由基本流和備選流的組合來表示。場景既可以幫助我們防止需求的遺漏,同時也可以對後續的開發工作起到很大的幫助:開發人員必須實現所有的場景、測試人員可以根據用例場景來設計測試用例。

2.3.4 特殊需求

  特殊需求通常是非功能性需求,它爲一個用例所專有,但不適合在用例的事件流文本中進行說明。特殊需求的例子包括法律或法規方面的需求、應用程序標準和所構建系統的質量屬性(包括可用性、可靠性、性能或支持性需求等)。此外,其他一些設計約束,如操作系統及環境、兼容性需求等,也可以在此節中記錄。

  需要注意的是,這裏記錄的是專屬於該用例的特殊需求;對於一些全局的非功能性需求和設計約束,它們並不是該用例所專有的,應把它們記錄在《補充規約》中。

2.3.5 前置和後置條件

  前置條件是執行用例之前必須存在的系統狀態,後置條件是用例一執行完畢後系統可能處於的一組狀態。

2.4 檢查用例模型

  用例模型完成之後,可以對用例模型進行檢查,看看是否有遺漏或錯誤之處。主要可以從以下幾個方面來進行檢查:

  • 功能需求的完備性
    現有的用例模型是否完整地描述了系統功能,這也是我們判斷用例建模工作是否結束的標誌。如果發現還有系統功能沒有被記錄在現有的用例模型中,那麼我們就需要抽象一些新的用例來記錄這些需求,或是將他們歸納在一些現有的用例之中。
  • 模型是否易於理解
    用例模型最大的優點就在於它應該易於被不同的涉衆所理解,因而用例建模最主要的指導原則就是它的可理解性。用例的粒度、個數以及模型元素之間的關係複雜程度都應該由該指導原則決定。
  • 是否存在不一致性
    系統的用例模型是由多個系統分析員協同完成的,模型本身也是由多個工件所組成的,所以我們要特別注意不同工件之前是否存在前後矛盾或衝突的地方,避免在模型內部產生不一致性。不一致性會直接影響到需求定義的準確性。
  • 避免二義性語義
    好的需求定義應該是無二義性的,即不同的人對於同一需求的理解應該是一致的。在用例規約的描述中,應該避免定義含義模糊的需求,即無二義性。

3. 系統需求

  RUP中根據FURPS+模型將系統需求分爲以下幾類:

  • 功能(Functionality)
  • 可用性(Usability)
  • 可靠性(Reliability)
  • 性能(Performance)
  • 可支持性(Supportability)
  • 設計約束等

  除了第一項功能性需求之外的其他需求都歸之爲非功能性需求。

3.1 需求工件集

  用例模型主要用於描述系統的功能性需求,對於其他的非功能性需要用其他文檔來記錄。RUP中定義瞭如下的需求工件集合。

  • 用例模型:記錄功能性需求
    • 用例圖:描述參與者和用例之間的關係
    • 用例規約:描述每一個用例的細節信息
  • 補充規約:記錄一些全局性的功能需求、非功能性需求和設計約束等
  • 詞彙表:記錄一些系統需求相關的術語

  在實際應用中,除了這些工件之外,我們還可以根據實際需求靈活選用其他形式的文檔來補充說明需求。並不是所有的系統需求都適保合用用例模型來描述的,如編譯器,我們很難用用例方法來表述它所處理的語言的方法規則,在這種情況下,採用傳統的BNF範式來表述更加合適一些。在電信軟件行業中,很多電信標準都是採用SDL語言來描述的,我們也不必用UML來改寫這些標準(UMLSDL存在着這樣的兼容性),只需將SDL形式的電信標準作爲需求工件之一,在其他工件中對其加以引用就可以了。總之,萬萬不可拘泥於用例建模的形式,應靈活運用各種方式的長處。

3.2 補充規約

  補充規約記錄那些在用例模型中不易表述的系統需求,主要包括以下內容。

  • 功能性
    功能性需求主要在用例模型中刻畫,但是也有部分需求不適合在用例中表述。有些功能性需求是全局性的,適用於所有的用例,如出錯處理、I18N支持等,我們不需要在所有的用例中描述這些功能性需求,只需要在補充規約中統一描述就可以了。
  • 可用性
    記錄所有可用性相關的需求,如系統的使用者所需要的培訓時間、是否應附合一些常見的可用性標準如Windows界面風格等。
  • 可靠性
    定義系統可靠性相關的各種指標,包括:
    • 可用性:指出可用時間百分比(xx.xx%),系統處於使用、維護、降級模式等操作的小時數;
    • 平均故障間隔時間(MTBF):通常表示爲小時數,但也可表示爲天數、月數或年數;
    • 平均修復時間(MTTR):系統在發生故障後可以暫停運行的時間;
    • 精確度:指出系統輸出要求具備的精密度(分辨率)和精確度(按照某一已知的標準);
    • 最高錯誤或缺陷率:通常表示爲bugs/KLOC(每千行代碼的錯誤數目)或bugs/function-point(每個功能點的錯誤數目)。
  • 性能
    記錄系統性能相關的各種指標,包括:
    • 對事務的響應時間(平均、最長);
    • 吞吐量(例如每秒處理的事務數);
    • 容量(例如系統可以容納的客戶或事務數);
    • 降級模式(當系統以某種形式降級時可接受的運行模式);
    • 資源利用情況:內存、磁盤、通信等。
  • 可支持性
    定義所有與系統的可支持性或可維護性相關的需求,其中包括編碼標準、命名約定、類庫、如何來對系統進行維護操作和相應的維護實用工具等。
  • 設計約束
    設計約束代表已經批准並必須遵循的設計決定,其中包括軟件開發流程、開發工具、系統構架、編程語言、第三方構件類庫、運行平臺和數據庫系統等等。

3.3 詞彙表

  詞彙表主要用於定義項目特定的術語,它有助於開發人員對項目中所用的術語有統一的理解和使用,它也是後續階段中進行對象抽象的基礎。

4. 調整用例模型

  在一般的用例圖中,我們只表述參與者和用例之間的關係,即它們之間的通訊關聯。除此之外,我們還可以描述參與者與參與者之間的泛化(generalization)、用例和用例之間的包含(include)、擴展(extend)和泛化(generalization)關係。我們利用這些關係來調整已有的用例模型,把一些公共的信息抽取出來重用,使得用例模型更易於維護。但是在應用中要小心選用這些關係,一般來說這些關係都會增加用例和關係的個數,從而增加用例模型的複雜度。而且一般都是在用例模型完成之後纔對用例模型進行調整,所以在用例建模的初期不必要急於抽象用例之間的關係。

4.1 參與者之間的關係

  參與者之間可以有泛化(Generalization)關係(或稱爲"繼承"關係)。例如在需求分析中常見的權限控制問題(如下圖所示),一般的用戶只可以使用一些常規的操作,而管理員除了常規操作之外還需要進行一些系統管理工作,操作員既可以進行常規操作又可以進行一些配置操作。

     

     在這個例子中我們會發現管理員和操作員都是一種特殊的用戶,他們擁有普通用戶所擁有的全部權限,此外他們還有自己獨有的權限。這裏我們可進一步把普通用戶和管理員、操作員之間的關係抽象成泛化(Generalization)關係,管理員和操作員可以繼承普通用戶的全部特性(包括權限),他們又可以有自己獨有的特性(如操作、權限等)。這樣可以顯著減速少用例圖中通訊關聯的個數,簡化用例模型,使之更易於理解。

 


 

 

 

 

 

 

 

 

 

 

4.2 用例之間的關係

  用例描述的是系統外部可見的行爲,是系統爲某一個或幾個參與者提供的一段完整的服務。從原則上來講,用例之間都是並列的,它們之間並不存在着包含從屬關係。但是從保證用例模型的可維護性和一致性角度來看,我們可以在用例之間抽象出包含(include)、擴展(extend)和泛化(generalization)這幾種關係。這幾種關係都是從現有的用例中抽取出公共的那部分信息,然後通後過不同的方法來重用這部公共信息,以減少模型維護的工作量。

4.2.1 包含(include)

  包含關係是通過在關聯關係上應用<<include>>構造型來表示的,如下圖所示。它所表示的語義是指基礎用例(Base)會用到被包含用例(Inclusion),具體地講,就是將被包含用例的事件流插入到基礎用例的事件流中。


  包含關係是UML1.3中的表述,在UML1.1中,同等語義的關係被表述爲使用(uses),如下圖。

   


  ATM機中,如果查詢、取現、轉帳這三個用例都需要打印一個回執給客戶,我們就可以把打印回執這一部分內容提取出來,抽象成爲一個單獨的用例"打印回執",而原有的查詢、取現、轉帳三個例都會包含這個用例。每當以後要對打印回執部分的需求進行修改時,就只需要改動一個用例,而不用在每一個用例都作相應修改,這樣就提高了用例模型的可維護性。

       


  在基礎用例的事件流中,我們只需要引用被包含用例即可。

  查詢-基本事件流

  1. 用戶插入信用卡

  2. 輸入密碼

  3. 選擇查詢

  4. 查看帳號餘額

  5. 包含用例"打印回執"

  6. 退出系統,取回信用卡

  在這個例子中,多個用例需要用到同一段行爲,我們可以把這段共同的行爲單獨抽象成爲一個用例,然後讓其他的用例來包含這一用例。從而避免在多個用例中重複性地描述同一段行爲,也可以防止該段行爲在多個用例中的描述出現不一致性。當需要修改這段公共的需求時,我們也只需要修改一個用例,避免同時修改多個用例而產生的不一致性和重複性工作。

  有時當某一個用例的事件流過於複雜時,爲了簡化用例的描述,我們也可以把某一段事件流抽象成爲一個被包含的用例。這種情況類似於在過程設計語言中,將程序的某一段算法封裝成一個子過程,然後再從主程序中調用這一子過程。

4.2.2 擴展(extend)

  擴展(extend)關係如下圖所示,基礎用例(Base)中定義有一至多個已命名的擴展點,擴展關係是指將擴展用例(Extension)的事件流在一定的條件下按照相應的擴展點插入到基礎用例(Base)中。對於包含關係而言,子用例中的事件流是一定插入到基礎用例中去的,並且插入點只有一個。而擴展關係可以根據一定的條件來決定是否將擴展用例的事件流插入基礎用例事件流,並且插入點可以有多個。


  例如對於電話業務,可以在基本通話(Call)業務上擴展出一些增值業務如:呼叫等待(Call Waiting)和呼叫轉移(Call Transfer)。我們可以用擴展關係將這些業務的用例模型描述如下。

    

   在這個例子中,呼叫等待和呼叫轉移都是對基本通話用例的擴展,但是這兩個用例只有在一定的條件下(如應答方正忙或應答方無應答)纔會將被擴展用例的事件流嵌入基本通話用例的擴展點,並重用基本通話用例中的事件流。

  值得注意的是擴展用例的事件流往往可以也可抽象爲基礎用例的備選流,如上例中的呼叫等待和呼叫轉移都可以作爲基本通話用例的備選流而存在。但是基本通話用例已經是一個很複雜的用例了,選用擴展關係將增值業務抽象成爲單獨的用例可以避免基礎用例過於複雜,並且把一些可選的操作獨立封裝在另外的用例中。

4.2.3 泛化(generalization)

  當多個用例共同擁有一種類似的結構和行爲的時候,我們可以將它們的共性抽象成爲父用例,其他的用例作爲泛化關係中的子用例。在用例的泛化關係中,子用例是父用例的一種特殊形式,子用例繼承了父用例所有的結構、行爲和關係。在實際應用中很少使用泛化關係,子用例中的特殊行爲都可以作爲父用例中的備選流存在。


  以下是一個用例泛化關係的例子,執行交易是一種交易抽象,執行房產交易和執行證券交易都是一種特殊的交易形式。

  用例泛化關係中的事件流示例如下:


4.3 調整用例模型

  用例模型建成之後,我們可以對用例模型進行檢視,看是否可以進一步簡化用例模型、提高重用程度、增加模型的可維護性。主要可以從以下檢查點(checkpoints)入手:

  • 用例之間是否相互獨立?如果兩個用例總是以同樣的順序被激活,可能需要將它們合併爲一個用例。
  • 多個用例之間是否有非常相似的行爲或事件流?如果有,可以考慮將它們合併爲一個用例。
  • 用例事件流的一部分是否已被構建爲另一個用例?如果是,可以讓該用例包含(include)另一用例。
  • 是否應該將一個用例的事件流插入另一個用例的事件流中?如果是,利用與另一個用例的擴展關係(extend)來建立此模型。

5. 管理用例模型複雜度

  一般小型的系統,其用例模型中包含的參與者和用例不會太多,一個用例圖就可以容納所有的參與者,所有的參與者和用例也可以並存於同一個層次結構中。對於較複雜的大中型系統,用例模型中的參與者和用例會大大增加,我們需要一些方法來有效地管理由於規模上升而造成的複雜度。

5.1 用例包

  包(Package)UML中最常用的管理模型複雜度的機制,包也是UML中語義最簡單的一種模型元素,它就是一種容器,在包中可以容納其他任意的模型元素(包括其他的包)。在用例模型中,我們可以用構造型(Sterotype)<<use case>>來擴展標準UML包的語義,這種新的包叫作用例包(Use Case Package),用於分類管理用例模型中的模型元素。

  我們可以根據參與者和用例的特性來對它們進行分類,分別置於不同的用例包管理之下。例如對於一個大型的企業管理信息系統,我們可以根據參與者和用例的內容將它們分別歸於人力資源、財務、採購、銷售、客務服務這些用例包之下。這樣我們將整個用例模型劃分成爲兩個層次,在第一層次我們看到的是系統功能總共分爲五部分,在第二層次我們可以分別看到每一用例包內部的參與者和用例。

        


  個用例模型需要有多少個用例包取決你想怎麼樣來管理用例模型的複雜度(包括參與者和用例的個數,以及它們之間的相互關係)。UML中的包其實就類似於文件系統中的目錄,文件數量少的時候不需要額外的目錄,文件數量一多就需要有多個目錄來分類管理,同樣一組文件不同的人會創建不同的目錄結構來進行管理,關鍵是要保證在目錄結構下每一個文件都要易於訪問。同樣的道理存在於用例建模之中,如何創建用例包以及用例包的個數取決於不同的系統和系統分析員,但要保證整個用例模型易於理解。

5.2 用例的粒度

  我的系統需要有多少個用例?這是很多人在用例建模時會產生的疑惑。描述同一個系統,不同的人會產生不同的用例模型。例如對於各種系統中常見的"維護用戶"用例,它裏面包含了添加用戶、修改用戶信息、刪除用戶等操作,這些操作在該用例的事件流可以表述成爲基本流的子事件流(subflow)


  維護用戶-基本事件流

  該基本流由三個子事件流構成:

  (1) 添加用戶子事件流

  (2) 修改用戶 子事件流

  (3) 刪除用戶子事件流

  但是你也可以根據該用例中的具體操作把它抽象成爲三個用例,它所表示的系統需求和單個用例的模型是完全一樣的。

         


  應該如何確定用例的粒度呢?在一次技術研討會上,有人問起Ivar Jacoboson博士,一個系統需要有多少個用例?大師的回答是20個,當然他的意思是最好將用例模型的規模控制在幾十個用例左右,這樣比較容易來管理用例模型的複雜度。在用例個數大致確定的條件下,我們就很容易來確定用例粒度的大小。對於較複雜的系統,我們需要控制用例模型一級的複雜度,所以可以將複雜度適當地移往每一個用例的內部,也就是讓一個用例包含較多的需求信息量。對於比較簡單的系統,我們則可以將複雜度適度地曝露在模型一級,也就是我們可以將較複雜的用例分解成爲多個用例。

  用例的粒度不但決定了用例模型級的複雜度,而且也決定了每一個用例內部的複雜度。我們應該根據每個系統的具體情況,因時因宜地來把握各個層次的複雜度,在儘可能保證整個用例模型的易理解性前提下決定用例的大小和數目。

5.3 用例圖

  用例圖的主要作用是描述參與者和用例之間的關係,簡單的系統中只需要有一個用例圖就可以把所有的關係都描述清楚。複雜的系統中可以有多個用例圖,例如每個用例包都可以有一個獨立的用例圖來描述該用例包中所有的參與者和用例的關係。

  在一個用例模型中,如果參與者和用例之間存在着多對多的關係,並且他們之間的關係比較複雜,如果在同一個用例圖中表述所有的參與者和用例就顯得不夠清晰,這時我們可創建多個用例圖來分別表示各種關係。

       


  如果想要強調某一個參與者和多個用例的關係,你就可以以該參與者爲中心,用一個用例圖表述出該參與者和多個用例之間的關係。在這個用例圖中,我們強調的是該參與者會使用系統所提供的哪些服務。

 


  如果想要強調某一個用例和多個參與者之間的關係,你就可以以該用例爲中心,用一個用例圖表述出該用例和多個參與者之間的關係。在這個用例圖中,我們強調的是該用例會涉及到哪些參與者,或者說該用例所表示的系統服務有哪些使用者。

      


  總之在用例建模過程中,你可以根據自己的需要創建任意多個用例圖,用不同的用例來強調參與者和用例之間不同的關係。但是最重要的是要考慮整個用例模型的可理解性,如果可以用一個用例圖把意思表述清楚,就不要再用第二個,因爲越是簡潔的模型越易於理解。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章