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