為什么要學(xué)習(xí)統(tǒng)一建模語言UML?
面向?qū)ο缶幊谭椒▽W(xué)是面向?qū)ο缶幊痰闹笇?dǎo)思想。進(jìn)行面向?qū)ο缶幊叹幊痰牡谝徊绞抢脤?duì)象建模技術(shù)(Object Modeling Technique,OMT)來分析目標(biāo)問題,抽象出相關(guān)對(duì)象的共性,對(duì)它們進(jìn)行分類,并分析各類之間的關(guān)系,再用類來描述同一類對(duì)象,歸納出類之間的關(guān)系。Coad和Yourdon在對(duì)象建模技術(shù)、面向?qū)ο缶幊毯椭R(shí)庫系統(tǒng)的基礎(chǔ)之上設(shè)計(jì)了一整套面向?qū)ο蟮姆椒?,分為面向?qū)ο蠓治?Object-Oriented Analysis,OOA)和面向?qū)ο笤O(shè)計(jì)(Object-Oriented Design,OOD)。對(duì)象建模技術(shù)、面向?qū)ο蠓治龊兔嫦驅(qū)ο笤O(shè)計(jì)共同構(gòu)成了系統(tǒng)設(shè)計(jì)的過程,如圖所示。這是編寫代碼的基礎(chǔ)。
在進(jìn)行對(duì)象建模、面向?qū)ο蠓治龊驮O(shè)計(jì)的過程中,需要使用建模語言來描述分析的過程和結(jié)果。統(tǒng)一建模語言(Unified Modeling Language,UML)是為了這個(gè)目標(biāo)而設(shè)計(jì)的一種標(biāo)準(zhǔn)通用的設(shè)計(jì)語言。任何想要真正理解面向?qū)ο缶幊趟枷氲娜?,都需要具備一定的UML知識(shí)。
在這個(gè)專題中我們會(huì)陸續(xù)介紹統(tǒng)一建模語言UML中的用例圖(use case diagram)、類圖(class diagram)、對(duì)象圖(object diagram)、序列圖(sequence diagram)、狀態(tài)圖(statechart diagram)、活動(dòng)圖(activity diagram)、組件圖(component diagram)和部署圖(deployment diagram)。
統(tǒng)一建模語言UML簡(jiǎn)介
UML不是一種方法學(xué),而是一種描述語言,它提供了多種類型的模型描述圖(diagram),當(dāng)在某種給定的方法學(xué)中使用這些圖時(shí),人們就能更容易理解和交流設(shè)計(jì)思想。UML的圖可劃分為如下三種類型。
— 靜態(tài)圖(static diagram):描述了那些不發(fā)生變化的軟件元素的邏輯結(jié)構(gòu),描繪了類、對(duì)象、數(shù)據(jù)結(jié)構(gòu)及其存在于它們之間的關(guān)系。
— 動(dòng)態(tài)圖(dynamic diagram):展示了在運(yùn)行期間的軟件實(shí)體的變化,描繪了執(zhí)行流程、實(shí)體改變狀態(tài)的方式。
— 物理圖(physical diagram):顯示了軟件實(shí)體的不變化的物理結(jié)構(gòu),描繪庫文件、字節(jié)文件、數(shù)據(jù)文件等,以及存在于它們之間的關(guān)系。
下表說明了三類圖中最常用的一些UML圖,以及它們適用的軟件開發(fā)階段。
提示 Microsoft Visio可以用來方便地繪制UML圖。Visual Studio 2005的類關(guān)系圖也可以顯示類似UML的圖,但是與標(biāo)準(zhǔn)的UML稍有不同。
統(tǒng)一建模語言UML用例圖
用例圖描述了系統(tǒng)提供的一個(gè)功能單元。用例圖的主要目的是幫助開發(fā)團(tuán)隊(duì)以一種可視化的方式來理解系統(tǒng)的功能需求,包括基于基本流程的“角色”之間的關(guān)系,以及系統(tǒng)內(nèi)用例之間的關(guān)系。用例圖一般用于表示用例的組織關(guān)系,要么是整個(gè)系統(tǒng)的全部用例,要么是完成具有功能(例如,所有安全管理相關(guān)的用例)的一組用例。
用例(use case)指的是系統(tǒng)的功能,它是系統(tǒng)某個(gè)功能的所有執(zhí)行動(dòng)作的集合。用例是從一個(gè)用戶的觀點(diǎn)來描述的。這個(gè)用戶告訴系統(tǒng)去做一些特定的事情。一個(gè)用例捕獲一個(gè)事件的可視化序列,這個(gè)事件是一個(gè)系統(tǒng)對(duì)單個(gè)用戶的激勵(lì)(stimulus)的響應(yīng)過程。
動(dòng)作者(actor)表示系統(tǒng)用戶能扮演的角色(role) 。這些用戶可能是人,也可能是其他的計(jì)算機(jī)、一些硬件,或者甚至是其他的軟件系統(tǒng)。對(duì)用例的唯一要求是,它們必須位于用例描述的系統(tǒng)部分之外,它們必須能刺激系統(tǒng)部分,并接收返回。
用例描述了當(dāng)動(dòng)作者之一給系統(tǒng)特定的刺激時(shí)的系統(tǒng)活動(dòng)。這些活動(dòng)用文本來描述。它描述了觸發(fā)用例的刺激的本質(zhì),輸入和輸出到其他活動(dòng)者,以及從輸入到輸出的活動(dòng)。用例文本通常也描述每一個(gè)活動(dòng)可能的錯(cuò)誤和系統(tǒng)應(yīng)采取的補(bǔ)救措施。
在用例圖中,用橢圓來表示用例,并將用例的名稱放在橢圓的中心或橢圓下面的中間位置。人形符號(hào)用來表示角色(用戶)。角色和用例之間的關(guān)系使用簡(jiǎn)單的線段來描述,表示角色可以操作此用例。
在用例圖中,用一個(gè)方框來表示系統(tǒng)的邊界。所有系統(tǒng)用例都放在框內(nèi),所有動(dòng)作者都位于框外。動(dòng)作者和用例之間用直線相連。方框內(nèi)的每一件事物都是系統(tǒng)的一部分,方框外的每一件事物都是系統(tǒng)的外部。用例圖也可以表示方框內(nèi)的系統(tǒng)用例之間的關(guān)系,最常見的是“使用關(guān)系”,用帶箭頭的直線來表示,箭頭指向被使用的用例。還有一種關(guān)系是擴(kuò)展關(guān)系,用來表示繼承。
圖6-2顯示了一個(gè)用例圖。用例圖通常用于表達(dá)系統(tǒng)或者系統(tǒng)范疇的高級(jí)功能。在圖中可以很容易地看出該系統(tǒng)所提供的功能。這個(gè)系統(tǒng)允許樂隊(duì)經(jīng)理查看樂隊(duì)CD的銷售統(tǒng)計(jì)報(bào)告及排行榜報(bào)告。它也允許唱片經(jīng)理查看特定CD的銷售統(tǒng)計(jì)報(bào)告和這些CD在排行榜的報(bào)告。這個(gè)圖還告訴我們,系統(tǒng)將通過一個(gè)名為“排行榜報(bào)告服務(wù)”的外部系統(tǒng)來提供排行榜報(bào)告。
用例圖不會(huì)列出系統(tǒng)不能完成的功能。下圖所示的系統(tǒng)不能提供給樂隊(duì)經(jīng)理收聽排行榜上不同專輯中的歌曲的方法,也就是說,系統(tǒng)沒有引用一個(gè)叫做“收聽排行榜上的歌曲”的用例。如果在用例圖中提供清楚的、簡(jiǎn)要的用例描述,項(xiàng)目贊助商就能很容易地看出系統(tǒng)是否提供了必需的功能。
posted @ 2010-03-04 14:05 Silver.Lee 閱讀(193) 評(píng)論(0) 編輯
如何寫好最外圍用例
2003 年,我曾經(jīng)在網(wǎng)上看到一篇技術(shù)文章《 沒頭沒尾—項(xiàng)目開發(fā)筆記:如何編寫最外層用例 ?! 》,這篇文章寫得很好,真實(shí)記述、反映了用例寫作中的一些常見現(xiàn)象和誤區(qū)。 然而,該文的前后兩個(gè)用例實(shí)際上都不是針對(duì)客戶的真正的“最外層用例”,盡管作者作了些改進(jìn),但這些用例在具體的內(nèi)容和寫法上還存在一些問題。
1.引言
“本系統(tǒng)的目標(biāo)是制作出一個(gè)跨企業(yè)的信息平臺(tái),為目標(biāo)公司的客戶進(jìn)行服務(wù)。這些服務(wù)分成很多的方面,比如提供給銀行的公司財(cái)務(wù)情況查詢,提供給生產(chǎn)廠商銷售情況的報(bào)告。提供給銷售的商場(chǎng)以及店鋪貨源的情況,提供給物流,安裝服務(wù)公司送貨以及安排信息。從中賺取提高銷售效率,減少運(yùn)輸損耗的費(fèi)用。設(shè)定目標(biāo)公司為 A公司,信息平臺(tái)名稱B系統(tǒng)?!?br />
從上面介紹的內(nèi)容來看,我猜 B 系統(tǒng)是 一個(gè) 類似于供應(yīng)鏈 應(yīng)用 的 企業(yè) 門戶 系統(tǒng),這里所說的 A 公司好像是一家從事商品分銷的企業(yè)。通過該門戶, A 公司可以有效地聯(lián)系上家—生產(chǎn)商(供貨商),下家—商場(chǎng)、店鋪以及銀行、物流公司、安裝服務(wù)公司等客戶或合作伙伴。
在討論這個(gè)案例前,首先讓我們重溫一下什么是最外圍用例( the outermost use cases ,根據(jù) Cockburn 的定義改寫) :
對(duì)于每一個(gè)用例找到它仍能適用的最外圈的設(shè)計(jì)范圍,針對(duì)該范圍為它編寫一個(gè)概要用例; 對(duì)于一個(gè)將要設(shè)計(jì)的系統(tǒng), 我們 通??梢哉业揭粋€(gè)更廣的設(shè)計(jì)范圍,而使主用角( PA , Primary Actor )仍然處于該范圍之外,如果不斷擴(kuò)大該范圍,可以找到一個(gè)臨界點(diǎn),主用角就會(huì)被包含在當(dāng)前的范圍之內(nèi),這個(gè)臨界點(diǎn)就是最外圈的范圍; 最外圍用例是通過把同一個(gè)范圍內(nèi)具有相似目標(biāo)的主用角合并到一起而創(chuàng)建出來的,它們把與這些用角有關(guān)的所有低層用例都匯聚到了一起。
如何獲取最外圍用例呢? Cockburn 給了一些步驟建議 :
(1) 從一個(gè)用戶目標(biāo)開始。
(2) 問“這個(gè)目標(biāo)對(duì)主用角 AA (最好在組織外部)提供什么服務(wù)?”,用角 AA 是我們想要收集用例的最終主用角。
(3) 找出最外圈的設(shè)計(jì)范圍 S ,使得 AA 仍然在 S 之外,給 S 命名。
(4) 找出最終主用角 AA 在設(shè)計(jì)范圍 S 中的所有用戶目標(biāo)。
(5) 找出 AA 對(duì)系統(tǒng) S 的概要目標(biāo) GG 。
(6) 為 GG 編寫出概要用例。這個(gè)用例就是我們要找的最外圍用例,它將一些海平面(用戶目標(biāo)層)的用例維系在一起。
值得注意的是,這里 Cockburn 所說的“系統(tǒng)” S 不一定都是指軟件,它可能是軟件系統(tǒng)(如 B 系統(tǒng)),也可能是業(yè)務(wù)系統(tǒng)(如 A 公司、企業(yè)、部門等)。 在下面第 2 、第 3 小節(jié)中我將按照 Cockburn 的最外圍用例 定義 來考察 原文中的兩個(gè)最外圍用例 ,逐個(gè)分析存在的錯(cuò)誤。用第 1 個(gè)例子說明以“操作人員”為 主用角 、最外圈范圍為軟件系統(tǒng)( B 系統(tǒng))的正確寫法,用第 2 個(gè)例子說明以“客戶”為主用角 、最外圈范圍為業(yè)務(wù)系統(tǒng)( A 公司)的正確寫法。
2.軟件用例 - 業(yè)務(wù)管理
用例名稱: 最外圍用例
錯(cuò)誤分析: 顯然這不是一個(gè)正確的用例名稱。建議改為“業(yè)務(wù)管理”,解釋如下文。
簡(jiǎn)要說明:
A 公司決定讓其業(yè)務(wù)合作伙伴以及最終的用戶通過互聯(lián)網(wǎng)訪問 B 系統(tǒng)以達(dá)到減少 A 公司本地人員的工作量以及提升工作效率的目的。 B 系統(tǒng)負(fù)責(zé)完成進(jìn)銷存業(yè)務(wù)、其它業(yè)務(wù)處理以及報(bào)表管理。一些系統(tǒng)維護(hù)人員還負(fù)責(zé)管理基礎(chǔ)信息的認(rèn)定與實(shí)現(xiàn)。包括四個(gè)用例:基礎(chǔ)設(shè)置子系統(tǒng),進(jìn)銷存子系統(tǒng),其它業(yè)務(wù)處理子系統(tǒng),報(bào)表子系統(tǒng)。
錯(cuò)誤分析: 首先,用例的名稱、內(nèi)容中不應(yīng)該出現(xiàn)“子系統(tǒng)”這個(gè)術(shù)語, subsystem 屬于系統(tǒng)設(shè)計(jì)范疇。
從業(yè)務(wù)介紹來看,操作人員主要進(jìn)行“進(jìn)銷存、報(bào)表和其他業(yè)務(wù)”的處理,系統(tǒng)維護(hù)人員主要進(jìn)行基礎(chǔ)信息管理,所以這 4 個(gè)概要用例(風(fēng)箏層)分屬不同的 PA 。這兩種角色在概要白云層似乎沒有必要嚴(yán)格區(qū)分,所以我們把系統(tǒng)維護(hù)人員和操作人員合并成“操作維護(hù)人員”,并且把這 4 個(gè)用例合并成 1 個(gè)最外圍用例“業(yè)務(wù)管理”,并在此處描述。
用例范圍: 跨企業(yè)信息平臺(tái)
主執(zhí)行者( PA ): 客戶
錯(cuò)誤分析: 從用例范圍和基本流的內(nèi)容看, 這里的 PA 應(yīng)該是“操作維護(hù)人員”(客戶作為 PA 的最外圍用例見第 3 小節(jié))。
用例層次: 白云(最高層次)
觸發(fā)事件: 客戶有購貨的需求
錯(cuò)誤分析: 這里應(yīng)該描述可以檢測(cè)到的事件(動(dòng)作、狀態(tài)的改變等),我們?cè)趺粗揽蛻粲匈徹浀男枨竽兀空_的說法可能是:客戶以各種方式請(qǐng)求服務(wù)。
主成功場(chǎng)景(基本流)
· 系統(tǒng)維護(hù)人員操作基礎(chǔ)設(shè)置子系統(tǒng)維護(hù)基礎(chǔ)設(shè)置的數(shù)據(jù)。
· 操作人員操作進(jìn)銷存子系統(tǒng)完成進(jìn)銷存業(yè)務(wù)。
· 操作人員通過報(bào)表系統(tǒng)分析查詢業(yè)務(wù)結(jié)果。
· 操作人員通過其它的業(yè)務(wù)子系統(tǒng)完成對(duì)系統(tǒng)中的其它業(yè)務(wù)處理。(注,其它業(yè)務(wù)子系統(tǒng)包括財(cái)務(wù)資金等等子系統(tǒng),將會(huì)子用例描述中強(qiáng)調(diào))
小結(jié):
從以上分析看,原用例存在著基本的概念錯(cuò)誤,用例的主用角( PA) 、范圍和基本流的內(nèi)容相互之間存在不一致的現(xiàn)象。這 個(gè)最外圍用例可以改寫如下:
用例名稱:
業(yè)務(wù)管理
范圍:
B 系統(tǒng)
層次:
概要 / 白云
主用角:
系統(tǒng)操作維護(hù)人員
觸發(fā)事件:
客戶通過電話、郵件等方式向操作維護(hù)人員提出服務(wù)請(qǐng)求(如購貨)。
基本流:
操作維護(hù)人員通過 B 系統(tǒng)可完成以下任務(wù):
1. 基礎(chǔ)信息管理。
2. 處理進(jìn)銷存業(yè)務(wù)。
3. 進(jìn)行報(bào)表管理,查詢、分析業(yè)務(wù)結(jié)果。
4. 處理其他業(yè)務(wù)(如財(cái)務(wù)資金管理)。
[ 用例結(jié)束 ]
3.業(yè)務(wù)用例 - 客戶服務(wù)
用例名稱: 最外圍用例
錯(cuò)誤分析: 顯然這不是一個(gè)正確的用例名稱,建議改為“客戶服務(wù)”。
簡(jiǎn)要說明:
A 公司決定讓其業(yè)務(wù)合作伙伴以及最終的用戶通過互聯(lián)網(wǎng)訪問 B 系統(tǒng)以達(dá)到減少 A 公司本地人員的工作量以及提升工作效率。 B 系統(tǒng)負(fù)責(zé)完成銷售業(yè)務(wù)以及報(bào)告銷售情況。一些系統(tǒng)維護(hù)人員還必須為客戶和職員設(shè)置安全存取級(jí)別。包括四個(gè)用例:增加服務(wù)( A 公司本地),增加服務(wù)(客戶),報(bào)告業(yè)務(wù)情況,管理安全存取權(quán)限。
錯(cuò)誤分析: 這段話其實(shí)不太像用例簡(jiǎn)述。最外圍用例應(yīng)該從 A 公司向客戶提供服務(wù)的角度來敘述,比方說,可以請(qǐng)求服務(wù),查詢業(yè)務(wù)銷售報(bào)表等。在本例中我們進(jìn)行黑盒業(yè)務(wù)建模,涉及到 B 系統(tǒng)和系統(tǒng)維護(hù)人員的內(nèi)容,比如安全級(jí)別設(shè)置,不應(yīng)在此處反映。
用例范圍: 跨企業(yè)平臺(tái)
錯(cuò)誤分析: 我們選定了 A 公司的客戶作為 PA ,那么按照最外圍用例的定義,最大范圍邊界應(yīng)為 A 公司而不是 B 系統(tǒng)。實(shí)際上這是一個(gè)業(yè)務(wù)用例( Business Use Case )。雖然客戶也可以直接訪問 B 系統(tǒng),但是對(duì)于客戶而言,B 系統(tǒng) 不是最大的范圍 。
用例層次: 白云(最高層次)
主執(zhí)行者( PA ): 客戶
主成功場(chǎng)景(基本流):
·客戶通過電話,郵件聯(lián)系 A 公司操作人員,請(qǐng)求一個(gè)新的服務(wù)。 A 公司的操作人員通過 B 系統(tǒng)處理服務(wù)請(qǐng)求。
·客戶直接通過 B 系統(tǒng)的客戶端,請(qǐng)求與處理新的服務(wù)。
·客戶通過 B 的系統(tǒng)可以查詢出銷售情況以及其它相關(guān)情況的報(bào)表。
·B 的系統(tǒng)維護(hù)人員將要對(duì)客戶以及操作人員進(jìn)行安全存取權(quán)限的設(shè)置。
錯(cuò)誤分析: 在最外圍業(yè)務(wù)用例的基本流中,主要包含一些用戶目標(biāo)層或概要層的用例,所以此處不應(yīng)該出現(xiàn)與 B 系統(tǒng)、操作人員、系統(tǒng)維護(hù)人員相關(guān)的內(nèi)容,它們?cè)谖覀兌x的范圍邊界( A 公司)之內(nèi)。 根據(jù)以上分析,我將該 最外圍用例改寫如下:
用例名稱:
客戶服務(wù)
范圍:
A 公司 / 業(yè)務(wù)
層次:
概要 / 白云
主用角 :
客戶
觸發(fā)事件:
客戶提出服務(wù)請(qǐng)求
基本流:
客戶可以下列 2 種方式獲得服務(wù):
1. 服務(wù)請(qǐng)求處理:客戶通過電話、郵件、客戶端軟件等方式請(qǐng)求服務(wù), A 公司接收請(qǐng)求后進(jìn)行相應(yīng)處理,并把處理結(jié)果以恰當(dāng)?shù)姆绞椒祷亟o客戶。
2. 銷售查詢:客戶通過客戶端軟件直接查詢銷售情況及相關(guān)報(bào)表。
[ 用例結(jié)束 ]
4.總結(jié)
有人認(rèn)為:“ 也許針對(duì)一個(gè)項(xiàng)目可以有很多‘正確的'最外層用例的設(shè)計(jì)方法。上面兩種劃分方式應(yīng)該說只從最外層用例的角度來說都是正確的 ” 。我不同意這種開脫的說法,針對(duì) 1 個(gè)項(xiàng)目抽取最外圍用例實(shí)際上只有 1 種“最優(yōu)解”。為什么?道理很簡(jiǎn)單,因?yàn)樽钔鈬美?Cockburn 提出的,他給出了找到最外圍用例的步驟和方法,而這種方法是明確的、無二義性的。人們找錯(cuò)了最外圍用例,多半是因?yàn)闆]有理解和掌握這套方法。
概括一下,原文主要存在以下錯(cuò)誤:
1 )由于用例的主用角 、范圍與基本流的內(nèi)容不一致,導(dǎo)致那兩個(gè)用例都不是真正的最外圍用例。實(shí)際上,針對(duì)“客戶”的最外圈范圍是 A 公司,而針對(duì)“操作維護(hù)人員”的最外圈范圍是 B 系統(tǒng)。
2 )在用例的功能描述中出現(xiàn)了軟件內(nèi)部設(shè)計(jì)的內(nèi)容,不符合需求提取、分析的要求。
最終,由于原作者對(duì)于為什么要編寫用例,用例與傳統(tǒng)結(jié)構(gòu)化方法的功能總體描述究竟有何實(shí)質(zhì)上的不同,用例有哪些特點(diǎn),缺乏準(zhǔn)確而深入的理解,導(dǎo)致編寫用例的時(shí)候思路凌亂,把幾種內(nèi)容混雜在一起,做成了一碗“雜燴面”。 這個(gè)案例給我們的重要啟迪是,抽取用例最關(guān)鍵的一步是首先明確 SuD ( System Under Discussion or Design )范圍的定義 以 及針對(duì)這個(gè)范圍的主用角 。 如果用 傳統(tǒng) “結(jié)構(gòu)化”的老思路來套用例的格式,換湯不換藥,那對(duì) IT/軟件項(xiàng)目開發(fā)將起不到真正的效果,甚至可能產(chǎn)生負(fù)作用,如果那樣還不如不寫用例。 最外圍用例便于我們將關(guān)注的焦點(diǎn)轉(zhuǎn)向用戶真正需要什么,從而真正地從用戶的角度出發(fā)來考慮問題
posted @ 2010-03-04 14:04 Silver.Lee 閱讀(70) 評(píng)論(0) 編輯
統(tǒng)一用例分析
一、用例基礎(chǔ)
1.1用例簡(jiǎn)史
用例技術(shù)大體上經(jīng)歷了萌芽、成熟和發(fā)展3個(gè)階段[12],最早可追溯到上世紀(jì)60年代末UML(統(tǒng)一建模語言)、RUP(Rational統(tǒng)一過程)之父Ivar Jacobson(伊瓦·亞克申)博士在著名的瑞典愛立信公司領(lǐng)導(dǎo)程控電話交換機(jī)開發(fā)時(shí)采用的traffic case(話務(wù)案例),1986年前后亞克申博士在OOPSLA大會(huì)上發(fā)表的論文[4]標(biāo)志著用例的正式誕生。1992年,亞克申博士在其名著《面向?qū)ο筌浖こ?用例驅(qū)動(dòng)方法》[3]中正式推出了當(dāng)時(shí)已相當(dāng)完善的用例方法,用例驅(qū)動(dòng)成為了Objectory過程(RUP前身之一)的核心內(nèi)容,從此用例在國外軟件工程界得以迅速普及,并于90年代中后期被RUP和UML吸收為核心要素,亞克申博士在《統(tǒng)一軟件開發(fā)過程之路》[4]和《統(tǒng)一軟件開發(fā)過程》[5]中對(duì)此作了精彩的闡述,這些書因?yàn)槌蔀榱私馄溆美枷氲闹匾鳌H缃?,作為必不可少的關(guān)鍵內(nèi)容,用例技術(shù)總是被所有的當(dāng)代需求工程名著所引用,而“用例”本身也幾乎成為功能需求的代名詞。(注:考慮到歷史上的淵源關(guān)系,為了方便起見,以下我們用術(shù)語“亞克申方法”或“亞克申用例”來統(tǒng)稱RUP、UML及其支持者所采用的用例方法,盡管它們彼此之間可能存在細(xì)微的差別,而且也不一定全部是由亞克申博士本人所提出或贊成的。)
用例另一支主流派別代表人物Alistair Cockburn(阿里斯代·寇本)上世紀(jì)90代初從亞克申那里學(xué)習(xí)了用例,隨后通過十年認(rèn)真廣泛的實(shí)踐對(duì)其進(jìn)行了繼承和發(fā)展。寇本于1995至1997年間提出了著名的“基于目標(biāo)的用例”方法[2],他的方法和思想集中體現(xiàn)在《Writing Effective Use Cases》(以下簡(jiǎn)稱為WEUC)[1]中,以結(jié)構(gòu)化/半結(jié)構(gòu)化文本用例為中心是寇本方法的一大特色,該書可以說是迄今為止最為詳細(xì)的一本用例教材,對(duì)于指導(dǎo)實(shí)踐者如何寫好文本用例具有很高的價(jià)值。
1.2用例定義
下面,先讓我們從什么是用例開始討論。亞克申定義[7]強(qiáng)調(diào)用例是系統(tǒng)執(zhí)行的一個(gè)動(dòng)作序列(注:這其中也包括與用戶的交互),這些動(dòng)作必須對(duì)某個(gè)特定的使用者(Actor)產(chǎn)生可觀測(cè)的、有價(jià)值的結(jié)果。(注:Actor實(shí)質(zhì)上是用戶所扮演的一種角色)
那么到底什么結(jié)果叫“可觀測(cè)、有價(jià)值”呢?雖然兩種用例本質(zhì)上是一致的,但亞克申定義對(duì)此沒有明說,而寇本定義[1]則更加完善和明確。它首先強(qiáng)調(diào)用例是各種系統(tǒng)受益人(Stakeholder,又譯“干系人”)之間的一種行為契約(注:行為包括對(duì)象的活動(dòng)、動(dòng)作和對(duì)象之間的交互等),建立契約的目的是為了達(dá)成某種目標(biāo),因此每一個(gè)用例及其名稱實(shí)際上都應(yīng)代表一個(gè)用戶目標(biāo),這個(gè)目標(biāo)是否得到真正滿足正是判斷我們抽取的某個(gè)用例是否“有價(jià)值”的關(guān)鍵。寇本還點(diǎn)出了要通過用例的具體執(zhí)行來展現(xiàn)Actor的目標(biāo)是如何實(shí)現(xiàn)或失敗的,而一個(gè)用例其實(shí)就是多個(gè)在不同條件下執(zhí)行并可能導(dǎo)致許多不同后續(xù)狀態(tài)的情節(jié)(scenario,又譯“場(chǎng)景”)的疊加,這就是用例結(jié)果的“可觀測(cè)”。
因此綜合起來,我們只要抓住這樣幾個(gè)關(guān)鍵詞:目標(biāo)、行為契約、行為(事件)序列(動(dòng)作和交互)、情節(jié)、可觀測(cè)、有價(jià)值,就可以比較準(zhǔn)確地描述出用例的本質(zhì)特征。
1.3用例的重要性
為什么用例如此重要?一言以蔽之,這是因?yàn)橛美且环N普遍存在的客觀現(xiàn)實(shí),而實(shí)踐證明,用例技術(shù)是迄今為止最為深刻、準(zhǔn)確和有效的系統(tǒng)功能需求描述方法。
功能需求是指系統(tǒng)輸入到輸出的映射以及它們的不同組合[9],任何功能必然要通過外部環(huán)境與系統(tǒng)之間的交互才能完成,這不正是用例所要反映的內(nèi)容嗎?因此,我們可以在內(nèi)容和形式上把用例和系統(tǒng)的功能需求等同起來,并且得出推論:只要是軟件,必然都存在用例(雖然有時(shí)候不一定非要用某種具體的用例格式來描述),其中即包含數(shù)據(jù)流,也包含控制流,既包含消息發(fā)送和數(shù)據(jù)交換(交互),也包括活動(dòng)/動(dòng)作的執(zhí)行以及狀態(tài)的變遷。這些就是用例的本質(zhì)(現(xiàn)象背后那個(gè)真實(shí)的、抽象的“胚”),而各種格式文本、UML圖形(我們至少可以用4種UML動(dòng)態(tài)圖來描述用例)不過是用例的外部表現(xiàn)形式。所以,與其說亞克申博士發(fā)明了用例,還不如說亞克申博士早在20年前就發(fā)現(xiàn)了用例這種客觀現(xiàn)實(shí),并最終發(fā)明了用例表示和用例驅(qū)動(dòng)軟件過程的方法。
那么,什么情況下不太適合采用用例方法?主要有兩種情況:(1)用戶很少或沒有,接口也很少,如科學(xué)計(jì)算/仿真軟件、殺病毒軟件、編譯程序、內(nèi)存管理程序等[9];(2)功能需求非常簡(jiǎn)單,非功能需求和約束占主導(dǎo)地位。顯然,如今絕大部分的應(yīng)用軟件、系統(tǒng)軟件,尤其像電信、銀行、保險(xiǎn)、稅務(wù)、制造業(yè)、企業(yè)信息化等領(lǐng)域的復(fù)雜系統(tǒng),都是符合用例適用條件的,這從一個(gè)側(cè)面反映出用例技術(shù)的廣泛適用性。請(qǐng)注意,即使在上面兩種情況下也并不是說這些軟件的用例就不存在了,而只是表明它們的功能需求很簡(jiǎn)明或不太重要,除用例之外可能還有更加適用的方法。
正確有效的軟件需求必須是可測(cè)試、可驗(yàn)證的。過去我們描述功能需求可能采用了很多種方法,除嚴(yán)格的形式化方法外,普遍的缺點(diǎn)就是粒度太粗、精度不夠,大多停留在受益人要求(request)和特性(feature)這一層[9]。比方說,針對(duì)某個(gè)“打印報(bào)表”功能,通常僅用一段話來描述它的靜態(tài)輸入和輸出是不夠的,還應(yīng)該描述出用戶打印報(bào)表的具體操作流程,它有哪些特殊條件和選項(xiàng)設(shè)置,以及它與其他需求的依賴關(guān)系等等。很多團(tuán)隊(duì)在需求尚未細(xì)化到用例這一層次時(shí)就開始匆匆編碼了,結(jié)果往往導(dǎo)致大量需求風(fēng)險(xiǎn)乃至架構(gòu)風(fēng)險(xiǎn)被隱藏到構(gòu)造、移交階段才發(fā)現(xiàn),這必然造成頻繁的返工和嚴(yán)重的資源浪費(fèi)。及時(shí)準(zhǔn)確地抓住需求契約——用例這一關(guān)鍵,可以幫助我們?cè)诓皇?shí)用性、靈活性的情況下,有效地避免項(xiàng)目后期大量非正常的需求變化,為進(jìn)度愈來愈緊的項(xiàng)目贏得寶貴的時(shí)間,提高項(xiàng)目的成功率。
1.4相關(guān)譯法
借此機(jī)會(huì),順便談?wù)剬?duì)use case有關(guān)術(shù)語翻譯的看法。
筆者認(rèn)為“用例”是目前較好的譯法,這個(gè)詞可能來源于大家熟知的“測(cè)試用例”。有人認(rèn)為把use case翻譯成“用例”是錯(cuò)誤的[11],理由是:“‘例’是被列舉出來以說明某種情況的個(gè)別事物,use case是對(duì)一項(xiàng)系統(tǒng)功能使用情況的普遍適應(yīng)的描述,而不是對(duì)個(gè)別actor或者在個(gè)別條件下使用這項(xiàng)功能才適應(yīng),它也不是通過舉例的方式來描述的”,所以不能叫作“用例”。此種說法不盡全面,而且有些牽強(qiáng)(先不管它正確與否),其實(shí)use case到底是個(gè)別的,還是群體的(普遍適應(yīng)),取決于我們的視點(diǎn)。雖然對(duì)于單個(gè)的scenario來說,use case是多個(gè)情節(jié)的疊加,是一個(gè)整體的復(fù)合概念,但是我們知道,一個(gè)系統(tǒng)的功能必定是可數(shù)的、有限的,而每一個(gè)功能都可以表示為一個(gè)use case,所以在觀察系統(tǒng)提供的所有功能需求的集合這個(gè)層面上,use case又是一個(gè)一個(gè)可數(shù)的個(gè)體(“橢圓”),每一個(gè)都代表了不同的用戶目標(biāo),適用于個(gè)別的actor和個(gè)別特定的前置條件。同一個(gè)事物既是個(gè)體的又是整體的,這種現(xiàn)象并不足怪,例如在UML對(duì)象-類-類元關(guān)系中,通常對(duì)象是類的實(shí)例,而類又是類元的實(shí)例,對(duì)類元來說,類、接口、子系統(tǒng)、use case等等就是一個(gè)個(gè)個(gè)體的概念,類既是其對(duì)象實(shí)例的集合又是其類元集合的個(gè)別元素。可見,把use case的“case”譯成“例”并沒有錯(cuò)。
有的地方把use case翻譯成“用況”,即“使用的情況”之意,意思的確不錯(cuò)(use case的另一種說法是“使用的方式”)!可我總感覺這個(gè)詞比較突兀、拗口,類似的還有“用案”,把scenario叫作“案況”,大概這些詞讀起來不太符合大家的習(xí)慣(類似地,既然可以叫“用況”,為什么不能叫“用情”呢?),所以現(xiàn)在“用例”的叫法還是越來越多了。
其實(shí)“用例”這個(gè)譯法還有個(gè)附帶的好處,通過它我們很容易把原本就存在緊密聯(lián)系的use case和test case(test case來自于對(duì)scenario的分析,而scenario是用例的一次執(zhí)行)從中文名稱上也方便地統(tǒng)一起來。不過,這里我們需要做一個(gè)小小的改進(jìn)。中文的“測(cè)試用例”到底是指test case(帶定語的名詞詞組)呢,還是指對(duì)用例進(jìn)行測(cè)試(testing the use cases,動(dòng)賓詞組)呢?顯然這兩者不易分辨,而且若“用例”和“測(cè)試用例”兩個(gè)詞同時(shí)出現(xiàn)在一啰個(gè)句子或一段話中,常常會(huì)讓人感覺嗦和便扭。為了消除歧義,干脆以后把test case都叫做“測(cè)例”,這樣不但比以前的叫法更加簡(jiǎn)潔明了,而且無論字面上還是語義上都很貼切。當(dāng)然,用例和測(cè)例是不同層面的“例”。
現(xiàn)在市面上Actor也有多種譯法,常見的包括“參與者、執(zhí)行者、主角”等等?!皡⑴c者、執(zhí)行者”的問題主要是不準(zhǔn)確。首先,“參與者” 通常讓大家馬上想到的詞是participant,而且請(qǐng)注意,一個(gè)用例的真正參與者決不是只有外部的Actor,它們必然還包括系統(tǒng)本身及其內(nèi)部的各種元素。“執(zhí)行者”的問題與此類似:一個(gè)用例的真正執(zhí)行者應(yīng)該是系統(tǒng)本身!因此嚴(yán)格地講這樣譯是錯(cuò)誤的,興許叫作“外部參與者”、“外部執(zhí)行者”才更為恰當(dāng)?!爸鹘恰钡淖g法同樣存在著矛盾。如果把Actor叫作“主角”,那么Primary Actor就應(yīng)該叫作“主主角”了??磥鞟ctor的譯法中是不能含有“主”的,那么就剩下“角”了,而UML已經(jīng)有了一個(gè)專門術(shù)語role(角色),我們又不能把Actor直接叫作“角色”。
目前看來,把Actor意譯成“使用者”是比較妥當(dāng)?shù)?。在大多?shù)情況下Actor的的確確就是用戶(確切地說是系統(tǒng)用戶所扮演的一種角色),所以我們可以用“使用者”這個(gè)詞從字面上與“用戶”(user)進(jìn)行區(qū)分,但同時(shí)又保持兩者語義上的聯(lián)系。我們還可以把為系統(tǒng)服務(wù)的Supporting/Secondary Actor(見下文)叫做“被使用者”(為了簡(jiǎn)化可以省略“被”字)或“輔使用者”。除了指系統(tǒng)的用戶之外,“使用者”還有另一層含義,即Actor是use case的使用者(或被使用者),這種關(guān)系在UML用例圖上應(yīng)該可視化地表示為它們之間的連線(關(guān)聯(lián))。這樣解釋不但說的通,而且更便于不熟悉軟件技術(shù)的業(yè)務(wù)人員理解。
當(dāng)然,我們也不排除將來會(huì)找到“use case”、“actor”等術(shù)語更好的譯法。
二、統(tǒng)一用例方法
2.1 理由
為什么要提出統(tǒng)一用例方法(UUCM),有這個(gè)必要嗎?
我們發(fā)現(xiàn),雖然寇本用例起源于亞克申用例,但兩種用例方法各自經(jīng)過十多年的發(fā)展,彼此之間逐漸出現(xiàn)了一些顯著的差異,而且由于商業(yè)或其他方面的原因,目前我們尚未看到兩者將要融合的明顯趨勢(shì)。兩種方法各有優(yōu)缺點(diǎn),寇本強(qiáng)調(diào)基于目標(biāo)的文本格式,亞克申用例則更突出UML的作用,如下文所示,兩者的差別至少有10處之多。對(duì)于實(shí)踐者來說,如何處理好這些明顯差異,避免使用上的誤區(qū),再者能否巧妙地做出取舍,實(shí)現(xiàn)熊掌與魚兼得,這些都是非?,F(xiàn)實(shí)的在實(shí)踐中必須面對(duì)的問題。
筆者認(rèn)為采用統(tǒng)一的用例方法,把亞克申和寇本用例兩者結(jié)合起來,甚至融合其他的用例方法(據(jù)說已知的各種用例表示方法多達(dá)18種以上[2][6]),在理論和實(shí)踐上均是可行和必要的,這可能是我們目前可以采取的最佳策略。但是,UUCM本身并不是一種全新的用例方法,而只是一種特定的處理方案。它是在對(duì)亞克申、寇本用例方法繼承的基礎(chǔ)上,試圖消除這兩種經(jīng)典方法的不一致和矛盾,并探索可能的優(yōu)化改進(jìn)和后續(xù)發(fā)展,所以UUCM起到的作用與亞克申、寇本用例方法相比是次要的和微小的。
以下我們對(duì)兩種方法的異同進(jìn)行比較分析,并同時(shí)給出UUCM的建議。
2.2層次
明確提出用例的層次和范圍劃分,是寇本“基于目標(biāo)的用例方法”的精華所在[2]。顯然,每個(gè)用例存在的意義是為了完成一定的用戶目標(biāo)。寇本把用例劃分為3個(gè)目標(biāo)層次:概要層、用戶目標(biāo)層和子功能層,并通過引入巧妙的Why/How技術(shù)幫助分析者找到合適的目標(biāo)層次,從而可以有效地把握用例的粒度(真正的用例最終應(yīng)落實(shí)到用戶目標(biāo)層),防止用例情節(jié)的爆炸。
亞克申方法及其相關(guān)文獻(xiàn)在介紹如何有效地控制用例的粒度方面,大體上只有這樣兩條基本的判定規(guī)則:(1)通過判斷內(nèi)容是否有價(jià)值可以防止用例過小(例如,“輸入發(fā)貨地址”的粒度就太小,這不是一個(gè)真正的用例,相當(dāng)于寇本的子功能層用例);(2)通過判斷具體內(nèi)容是否可觀測(cè),可以防止用例過大(例如,“用戶管理”就比較空洞,這不是一個(gè)有效的用例名稱,相當(dāng)于寇本的概要用例)。但如前所述,究竟什么叫“有價(jià)值”,什么叫“可觀測(cè)”,如何把握好這個(gè)度,亞克申方法對(duì)此語焉不詳,給RUP和UML的使用者帶來了不少困惑,而寇本方法恰好出色地回答了這個(gè)問題。
UUCM:
通過寇本的分析,我們發(fā)現(xiàn)用例有縱向(層次)和橫向(范圍)之分,這些是非常有價(jià)值的概念,它們是對(duì)亞克申基礎(chǔ)用例方法的豐富和完善,兩者是不沖突的,完全可以在RUP相關(guān)的實(shí)踐中加以運(yùn)用。
值得注意的是,我們?cè)趯?shí)踐中應(yīng)該尤其關(guān)注用戶目標(biāo)層用例。寇本引入概要層用例的主要目的是為了包含一個(gè)或多個(gè)用戶目標(biāo)層用例,為系統(tǒng)提供全局功能視圖,提出子功能層用例則是為了表達(dá)用戶目標(biāo)層用例的具體實(shí)現(xiàn)步驟。雖然有時(shí)為了簡(jiǎn)便,我們也把后兩者叫做“用例”,但其實(shí)它們都不是真正的用例。
可能是為了防止濫用、誤用用例的分解(這很容易引誘人倒退到結(jié)構(gòu)化的功能分解),亞克申方法沒有提及甚至有意回避用例的層次問題。亞克申博士在最近的一篇文章中[12]引入了用例片段的概念,這意味著我們應(yīng)該把寇本方法中的子功能層用例叫做用例片段以避免名稱上的混淆,看來這是今后一種比較好的處理辦法。
2.3范圍
關(guān)于用例范圍的處理,兩種方法基本上是一致的,都可分為業(yè)務(wù)用例、系統(tǒng)用例兩種,區(qū)別在于寇本強(qiáng)調(diào)在格式上用圖標(biāo)或文字顯式地表示出每個(gè)用例的范圍,并且在用例層次劃分的基礎(chǔ)上提出了最外層(或最外圍)用例的概念[13],這在亞克申方法中是沒有的。
UUCM:
用例的本質(zhì)就是對(duì)象之間的一種協(xié)作和交互,這些內(nèi)容是屬于需求還是屬于設(shè)計(jì),關(guān)鍵就看你劃定的討論邊界。我們不僅可以用它來描述發(fā)生在系統(tǒng)邊界上的功能需求(用例的常規(guī)定義),而且還可以同樣的方式描述系統(tǒng)內(nèi)部發(fā)生在子系統(tǒng)、構(gòu)件、接口或類/對(duì)象邊界上的黑盒交互,不過后者往往涉及到系統(tǒng)設(shè)計(jì)范疇,屬于用例的特殊用法,在做項(xiàng)目的需求分析時(shí)一般不予考慮。
正如寇本所提到的,同樣一個(gè)用例名稱,比如“取款”,可能實(shí)質(zhì)上代表著兩個(gè)截然不同的用例:一個(gè)是ATM取款(系統(tǒng)用例),另一個(gè)是銀行柜臺(tái)取款(業(yè)務(wù)用例)。所以在一個(gè)用例中明確標(biāo)記出它的范圍,是很有必要的。我們既可以用特定的圖標(biāo),也可以用專門的格式字段來表明用例的范圍,還可以對(duì)用例的名稱加以修飾以便區(qū)分,比如“柜臺(tái)取款”,“ATM取款”。
當(dāng)前的討論邊界(SuD,the System under Discussion)一般比較容易確定,那么如何從用例的范圍上判斷一個(gè)用例是系統(tǒng)用例,還是業(yè)務(wù)用例呢?(這是一個(gè)出現(xiàn)率很高的FAQ)。有個(gè)小竅門:如果某個(gè)SuD或者用例的范圍包含了人以及由人組成的團(tuán)隊(duì)、部門、組織的活動(dòng),那么針對(duì)這個(gè)SuD寫出的用例必然是業(yè)務(wù)用例;如果該SuD僅僅是一些軟件、硬件、機(jī)電設(shè)備或由它們組成的系統(tǒng),并不涉及到人的業(yè)務(wù)活動(dòng),那么根據(jù)這個(gè)SuD寫出來的肯定是系統(tǒng)用例。
由于系統(tǒng)(注意,這里的“系統(tǒng)”是指由軟、硬件組成的IT系統(tǒng))往往是業(yè)務(wù)的一部分,我們還可以得出推論:對(duì)于某個(gè)系統(tǒng)用例suc,通??偸强梢哉业揭粋€(gè)業(yè)務(wù)用例buc,buc的范圍要大于或等于suc的范圍;當(dāng)這兩個(gè)用例的范圍相等時(shí),buc就是suc,或者buc的層次要高于suc的層次。
2.4 包含與擴(kuò)展
由于各方面復(fù)雜的原因,如何更好地表示用例之間的關(guān)系一直是個(gè)爭(zhēng)議不斷的問題,而且恐怕在將來較長(zhǎng)的一段時(shí)間內(nèi)對(duì)此還難有定論。我們發(fā)現(xiàn),寇本與亞克申方法在用例的擴(kuò)展、包含、繼承等關(guān)系的使用細(xì)節(jié)上存在著一些明顯差異,其中很大一部分原因可能是由于現(xiàn)有文獻(xiàn)對(duì)用例關(guān)系的定義不夠精準(zhǔn)和完善,導(dǎo)致大家在應(yīng)用時(shí)各取所需、各自解釋造成的。如果我們?cè)趯?shí)踐中對(duì)這一情況不加以留意,就可能給需求的溝通和交流帶來障礙。
2.4.1一頭霧水
同樣一對(duì)用例之間的關(guān)系,在寇本用例模型中是包含關(guān)系,在亞克申模型中卻可能被表示成擴(kuò)展關(guān)系。例如:
圖1、寇本畫法[1]
圖2、《UML參考手冊(cè)》畫法[10]
UUCM:
為什么會(huì)有如此差別?為了說明問題,還是讓我們先看看這幾個(gè)用例的文本描述?!禪ML參考手冊(cè)》寫道:
基用例ATM會(huì)話:
顯示當(dāng)天廣告
include(識(shí)別顧客)
include(驗(yàn)證賬戶)
-------------------------- <可能的事務(wù)>(擴(kuò)展點(diǎn)1)
打印憑條標(biāo)題
-------------------------- <憑條細(xì)節(jié)>(擴(kuò)展點(diǎn)2)
登出
擴(kuò)展用例取款:
收到取款請(qǐng)求
指定取款數(shù)量
-------------------------- <產(chǎn)生的請(qǐng)求>(擴(kuò)展點(diǎn)3)
付款
看到這里,我們就不難解釋為什么圖2把ATM會(huì)話與取款之間的關(guān)系畫成擴(kuò)展了(注:這本身可能不符合亞克申擴(kuò)展用例的原則[4])。由于在身份驗(yàn)證通過后,顧客具體執(zhí)行什么操作是不定的,可以是取款、存款、轉(zhuǎn)賬、查詢等事務(wù)中的任何一個(gè),將來甚至還有可能添加(擴(kuò)展)新的功能,而ATM打印的憑條根據(jù)用戶操作的不同,內(nèi)容也將有所不同。這些內(nèi)容的發(fā)生都需要具備一定的條件,屬于可能的情況,這一點(diǎn)似乎很符合擴(kuò)展用例的定義。考慮到這些因素,作者于是采用了圖2的策略,把可能的操作和打印內(nèi)容都從基用例中抽走。
然而不要忘了,除了擴(kuò)展用例只有在特定條件下才能被觸發(fā)之外,把一段內(nèi)容提取為擴(kuò)展用例還要求即使在沒有該擴(kuò)展用例插入的情況下,基用例本身的執(zhí)行也不應(yīng)受到任何影響。因此,如果我們把上段文字中的兩個(gè)擴(kuò)展點(diǎn)拿掉(只看左邊的文字)并參照寇本目標(biāo)用例的標(biāo)準(zhǔn),可以發(fā)現(xiàn)該基用例完全不是一個(gè)目標(biāo)得以完整執(zhí)行的用例。上述寫法是有問題的,它不完整,而且效率不高,似乎模仿了一些編程語言的寫法和思路,在實(shí)踐中不值得推廣。
下面再讓我們看看寇本版的“使用ATM”[1]:
1. 顧客插卡,輸入PIN。
2. ATM驗(yàn)證顧客賬戶和PIN。
3. 顧客執(zhí)行下列任一事務(wù):
取款
存款
轉(zhuǎn)賬
查詢
顧客執(zhí)行以上事務(wù)直到選擇退出。

4. ATM退卡。
在這里,取款、存款等事務(wù)操作明確地出現(xiàn)在用例的基本流中,顯然它們都是被“使用ATM”所包含的用例。注意,在寇本用例中每個(gè)動(dòng)作步驟不一定都是順序執(zhí)行的,可以有循環(huán),有選擇,甚至可以是任意順序,例如上面的步驟3。在WEUC中寇本還指出,實(shí)際上取款、存款、轉(zhuǎn)賬等操作都是顧客執(zhí)行一次交易事務(wù)的特例和具體化,所以還可以進(jìn)一步畫成類似圖3的形式。。我們可以看到圖1其實(shí)是圖3的簡(jiǎn)化。
圖 3、更為準(zhǔn)確的畫法
應(yīng)該如何判定一個(gè)用例關(guān)系是包含關(guān)系還是擴(kuò)展關(guān)系?有些情況還是比較明確的,例如對(duì)于“驗(yàn)證身份”和“吞卡”,大家可能都毫無異議,一致認(rèn)為它們分別是“使用ATM”的包含用例和擴(kuò)展用例。但是,一旦出現(xiàn)上例的情況時(shí),就較難處理了。不過,我們通常可以據(jù)此判定:如果觸發(fā)條件中含有基用例負(fù)責(zé)的事物,即基用例知道附加用例何時(shí)、何處、為什么發(fā)生,那么基用例應(yīng)該包含(調(diào)用或引用)它;如果觸發(fā)條件中含有附加用例負(fù)責(zé)的事物,即附加用例知道它應(yīng)該何時(shí)、何處、為什么發(fā)生,那么應(yīng)該讓附加用例擴(kuò)展基用例[1]。這兩條規(guī)則還是很管用的。此外,根據(jù)筆者經(jīng)驗(yàn),還可以參考這樣一條簡(jiǎn)單法則:凡是在用例基本流中出現(xiàn)的附加用例都應(yīng)作為包含用例,而在擴(kuò)展流中出現(xiàn)的附加用例必然是擴(kuò)展用例。顯然,圖3符合以上規(guī)則。
問題似乎得以解決了。然而,在UML 2.0上層結(jié)構(gòu)規(guī)范草中,我們卻看到了類似圖4的方案:
圖4、另一種近似的畫法
有人要問了,為什么針對(duì)同一段用例文本描述,卻存在兩種矛盾的UML畫法,同一個(gè)用例“取款”在圖3中是包含,在圖4中卻是繼承,到底哪個(gè)是對(duì)的?其實(shí),圖4與圖3這兩種用例模型在整體上所描述的內(nèi)容是完全一致的,問題就出在用例名稱上。分析、比較用例之間的關(guān)系,請(qǐng)務(wù)必關(guān)注用例的內(nèi)容——?jiǎng)幼鞑襟E。我們可以發(fā)現(xiàn),圖4中的“取款”用例與圖3中的“取款”用例所包含的實(shí)質(zhì)內(nèi)容是不一樣的,一大,一小。所以,假使我們把它們的名稱分別改為“取款交易”和“取款(事務(wù))操作” ,并約定前者“大于”后者,就可以在一定程度上消除二義性,這樣兩個(gè)圖就近似等價(jià)了。不管如何,圖3、圖4都一致地沒有把“取款”、“存款”、“轉(zhuǎn)賬”等用例作為基用例的擴(kuò)展。筆者認(rèn)為,經(jīng)過改進(jìn),這兩種畫法目前都是可行的,而圖3可能更好一些。
關(guān)于用例包含、擴(kuò)展和繼承關(guān)系方面的更深層探討,值得寫一篇專述文章,在這里不可能展開。在目前眾說紛紜的情況下,建議大家像寇本建議的那樣,如果實(shí)在搞不清兩個(gè)用例到底是什么關(guān)系,不如干脆都先定為包含關(guān)系,這樣做并不影響后續(xù)的系統(tǒng)分析設(shè)計(jì)和使用,因?yàn)橛美旧淼膬?nèi)容寫得如何才是問題的實(shí)質(zhì)、真正的關(guān)鍵??傊瑢?shí)踐者不要指望只通過看幾個(gè)用例的名字就能準(zhǔn)確地判斷出它們之間的關(guān)系??煽康囊罁?jù)來自于用例內(nèi)部,不必在弄清用例的關(guān)系上浪費(fèi)太多時(shí)間,這個(gè)問題可以留待學(xué)者和研究人員來解決。
2.4.2 sub use case之爭(zhēng)
寇本在WEUC中把包含用例稱為sub use case,即subordinate use case之意,但其實(shí)subordinate use case(筆者將其譯為“分用例”)在亞克申方法中有專門的用途(在亞克申博士早就提出的對(duì)大規(guī)模系統(tǒng)建模的SystemOf InterconnectedSystems模式中,有超系統(tǒng)/超用例和分系統(tǒng)/分用例之分[4])。而寇本采用的sub use case叫法很容易被直譯成中文“子用例”,從而造成新的誤解,因?yàn)槲覀冎馈案缸印币徽f在OO方法中通常是用來形容對(duì)象類之間的繼承關(guān)系的,子類是父類的派生類,顯然這與包含用例的真實(shí)語義不符。
在UML[10]中,把包含用例、擴(kuò)展用例統(tǒng)稱為附加(additional)用例,被包含、被擴(kuò)展的用例叫做基用例,在用例的繼承關(guān)系中則采用父用例、子用例的說法,這樣做是妥當(dāng)?shù)摹?br />
UUCM:
建議在實(shí)踐中盡量回避寇本sub use case的說法,可以用“包含用例”或“附加用例”來代稱,同時(shí)明確約定在中文中凡是提到“子用例”的地方,就是指用例的繼承或一般化。
2.5 Actor
寇本用例的Actor類型有7種之多,包括[1]:
Actor(something with behavior)、
External actor(an actor outside SuD)、
Stakeholder(an external actor entitled to have its interests protected by the system)、
Primary actor(a stakeholder who requests that the system deliver a goal)、
Supporting/secondary actor(a system against which the SuD has a goal)、
Offstage/tertiary actor(a stakeholder who is not the PA)、
Internal actor(either the SuD, a subsystem or an active component of the SuD)。
RUP關(guān)于Actor的定義[7]是: Someone or something, outside the system or business that interacts with the system or business。UML的定義是: An actor specifies a role played by a user or any other system that interacts with the subject。
UUCM:
亞克申用例與寇本用例對(duì)于Actor的定義存在著明顯區(qū)別。亞克申及UML的Actor是系統(tǒng)之外的人或物,而寇本Actor的含義(可能來自早期的亞克申版本)比較籠統(tǒng),其范圍要大得多,有內(nèi)外Actor之分。既然我們確定Actor的主要目的之一是為了劃定系統(tǒng)(或業(yè)務(wù))的邊界,那么應(yīng)該始終把Actor當(dāng)作系統(tǒng)外部的事物,這樣才比較妥當(dāng),內(nèi)部Actor是不必要的概念。而且,在實(shí)際應(yīng)用中Actor即重要也不重要[1],識(shí)別Actor的主要目的是為了幫助提取用例,通常不需要對(duì)各種Actor類型加以如此細(xì)致的區(qū)分。
另外,寇本關(guān)于stakeholder的定義與通常的理解也有所差別??鼙菊J(rèn)為stakeholder是一種外部Actor(注:這本身與寇本自己對(duì)用例的定義明顯存在矛盾[1]),這不對(duì)。按常理,所有利益相關(guān)人包括內(nèi)部Actor、外部Actor都應(yīng)該屬于stakeholder之列,尤其當(dāng)我們討論的是業(yè)務(wù)組織的時(shí)候。
2.6后置條件
與亞克申用例相比,寇本對(duì)用例的后置條件進(jìn)行了細(xì)分,提出了最小保證、成功保證等概念,這樣做是有意義的。最小保證描述了系統(tǒng)不管在任何情況下,尤其當(dāng)用例失敗、目標(biāo)未達(dá)成時(shí),都應(yīng)滿足的起碼條件和應(yīng)采取的措施。
UUCM:
建議采納寇本方法的最小保證和成功保證劃分。此外,在前置、后置條件(最小保證和成功保證)中除了說明必須滿足的條件外,還可以分別說明系統(tǒng)在用例開始前和結(jié)束后的狀態(tài),包括各種成功和失敗狀態(tài)以及對(duì)失敗狀態(tài)的處理。
2.7動(dòng)作步驟
寇本用例步驟采用獨(dú)特的編號(hào)方式,基本流采用1,2,3…順序編號(hào),擴(kuò)展流的條件和擴(kuò)展步驟采用數(shù)字、字母間隔的方式,如1a、1a1、5c、5c3b1等等,而且還可以使用宏代符*,可以指定任意數(shù)目步驟的條件,如1-9a、2,7-9c等等,使用起來非常方便。RUP的基本流、擴(kuò)展流步驟完全采用自然分節(jié)的順序編號(hào),如1.1、2.3.4.1等等,不便于閱讀者找到用例具體的引用位置,在指定擴(kuò)展位置時(shí)顯得較為麻煩。
另一方面,RUP用例的每個(gè)步驟都可以附上一個(gè)名稱,這叫做“命名步驟”。
如果一個(gè)步驟內(nèi)容較多,用一個(gè)短語標(biāo)記來概括說明該步驟執(zhí)行的大致內(nèi)容,確實(shí)比較方便,而且將來需要畫用例的活動(dòng)圖時(shí)也可以作為快速參考。
UUCM:
建議采納寇本的步驟編號(hào)方式和RUP的命名步驟方法。
2.8文本與UML
亞克申用例方法與UML、RUP三者之間有著天然的緊密聯(lián)系。用例驅(qū)動(dòng)、可視化建模是RUP的兩大特征,若用例和UML缺席,RUP也就稱不上RUP了。在亞克申方法中,除了可以用RUP的格式文本描述用例外,還推薦適當(dāng)?shù)剡x擇利用UML用例圖、序列圖、協(xié)作圖、活動(dòng)圖和狀態(tài)圖5種圖示從各個(gè)角度來描述用例,可謂手段充足、武器齊備。
寇本代表作WEUC的主基調(diào)是用結(jié)構(gòu)化/半結(jié)構(gòu)化的文本描述用例。雖然他也提到了UML,但討論主要集中在如何正確對(duì)待UML的用例圖和相關(guān)CASE工具等問題上,對(duì)UML用于描述動(dòng)態(tài)行為的其他4種圖的作用和意義強(qiáng)調(diào)得不夠充分,其實(shí)這些圖的作用遠(yuǎn)比用例圖要重要得多,也是UML強(qiáng)大描述能力之體現(xiàn)。
UUCM:
如前所述,文本用例本質(zhì)上是對(duì)對(duì)象交互過程的執(zhí)行步驟的羅列。用例本身即每個(gè)“橢圓”內(nèi)部的東西才是最為關(guān)鍵和重要的,用例之間的關(guān)系相對(duì)來說要次要些,在這一點(diǎn)上,可以說亞克申方法和寇本方法的看法是一致的[1][4]。實(shí)踐中,我們發(fā)現(xiàn)很多時(shí)候,先寫文本系統(tǒng)用例,后照著已有的文字說明畫UML圖比先畫圖或完全依賴于圖形來描述系統(tǒng)用例要容易得多。可見對(duì)于軟件需求分析,我們應(yīng)該首先把更多的精力放在寫好文本用例上(這正是寇本方法的強(qiáng)項(xiàng))。
但是,寇本認(rèn)為“Sequence diagrams are not a good form for expression use cases”[1],這種說法有失準(zhǔn)確和全面??v觀全書,寇本主要是從工具使用的角度來分析的,他在書中對(duì)當(dāng)時(shí)那些不那么先進(jìn)的CASE工具頗有微詞,認(rèn)為它們不如文本寫作更加便捷和有效。然而,事實(shí)上這只是問題的一個(gè)方面,UML工具的缺陷并不能簡(jiǎn)單地等同于UML語言本身的缺陷。正確地使用UML及其工具不僅僅是為了獲得形象直觀、交叉引用、超鏈接、名稱自動(dòng)變更等一目了然的好處,更重要的一個(gè)原因是,通過合適的UML圖形,比如SSD(系統(tǒng)序列圖),來精確地定義和描述系統(tǒng)事件與作為其響應(yīng)的系統(tǒng)操作(也就是系統(tǒng)的輸入和輸出)[8]之間的契約,這正是后續(xù)系統(tǒng)分析和設(shè)計(jì)的起點(diǎn)。序列圖在用例分析中其實(shí)起到相當(dāng)關(guān)鍵的作用,在實(shí)踐中用它來刻畫每一個(gè)重要的系統(tǒng)用例也是非常普遍的做法。
而且,在分析復(fù)雜的業(yè)務(wù)流程/業(yè)務(wù)用例時(shí),人們好像更習(xí)慣于首先畫活動(dòng)圖(可能與人類自身的思維習(xí)慣有關(guān)),反而不太愿意采用繁瑣的文字說明。對(duì)于復(fù)雜和關(guān)鍵的用例,除了一些必要的文本描述之外,再輔之以UML活動(dòng)圖、序列圖或狀態(tài)圖進(jìn)行可視化,是行之有效的好做法,有助于澄清問題本質(zhì)、迅速抓住要領(lǐng)。對(duì)于復(fù)雜的用例模型,通過用例圖描述用例之間的關(guān)系,提供全局瀏覽視圖,也是非常必要的。
用例的UML圖形與文本描述之間不是誰取代誰的關(guān)系,而是相輔相成、優(yōu)勢(shì)互補(bǔ),應(yīng)該因地制宜地加以運(yùn)用。不僅如此,同時(shí)擁有用例的結(jié)構(gòu)/半結(jié)構(gòu)化文
本和UML圖形,往往還有助于彼此之間相互比對(duì)、確認(rèn),能顯著提高用例描述和分析的正確性。根據(jù)本人經(jīng)驗(yàn),把兩者結(jié)合起來運(yùn)用效果才是最好的,沒有必要過份地強(qiáng)調(diào)某一方面。
2.9黑盒白盒
亞克申博士發(fā)明的用例實(shí)現(xiàn)(UCR,Use Case Realization)[5]在RUP、UML中是一個(gè)非常重要的概念,它描述了內(nèi)部對(duì)象如何相互協(xié)作共同實(shí)現(xiàn)一個(gè)用例,理論上每一個(gè)用例都應(yīng)該至少有一個(gè)UCR與其對(duì)應(yīng),因而UCR在亞克申方法中起到了聯(lián)接問題域和解決域、貫穿整個(gè)軟件分析設(shè)計(jì)過程的關(guān)鍵作用。在寇本方法中,不存在UCR這個(gè)術(shù)語,只有黑盒用例(需求)、白盒用例之分(需求的實(shí)現(xiàn))。
UUCM:
首先,既然談及基于用例表示的功能需求,那么它就應(yīng)該是黑盒的、透明的。如果我們看到了系統(tǒng)內(nèi)部的情況(白盒、不透明),那么這其實(shí)已經(jīng)是需求的一種實(shí)現(xiàn)了。所以,我們應(yīng)該在需求分析時(shí)盡量避免“白盒用例”這種矛盾的說法。嚴(yán)格地區(qū)分UC和UCR,有助于項(xiàng)目團(tuán)隊(duì)在實(shí)踐中消除需求和實(shí)現(xiàn)不分的情況。這一點(diǎn)過去在被拉來寫需求的程序員當(dāng)中比較普遍,受習(xí)慣性思維的影響,他們往往寫到最后就變成寫軟件設(shè)計(jì)方案了,這是很糟糕的。
2.10格式模板
寇本在WEUC中一共列出了5種主要的用例格式模板:完整型、簡(jiǎn)易型、單列表式、雙列表式和RUP樣式。在此,我們推薦以完整型(寇本本人最喜歡的)為基礎(chǔ),結(jié)合了單列表式和RUP樣式特點(diǎn)的UUCM模板:
用例名稱:
層次:
+ | ! | -
范圍:
簡(jiǎn)述/背景:
主使用者及利益:
其他受益人及利益:
受益人1:
受益人2:
最小保證:
狀態(tài)1:
狀態(tài)2:
后置
條件
成功保證:
前置條件:
條件1:
條件2:
狀態(tài)1:
狀態(tài)2:
觸發(fā)事件:
基本流:
1. 步驟1
2. <可選名稱>.步驟2
…
n. 步驟n
<結(jié)束>
擴(kuò)展流:
1a. 條件1:
1a1. 步驟1
1a2. 步驟2
擴(kuò)展點(diǎn):
名稱1:位置1
名稱2:位置2
技術(shù)和數(shù)據(jù)變化:
1a.
2a.
非功能需求:
業(yè)務(wù)規(guī)則:
備注:
其他必要字段
……
表1、UUCM模板v1.0
雙列表式較多地被用來描述用戶界面需求,有些人偏愛它,但我們發(fā)現(xiàn)雙列表不夠簡(jiǎn)潔,比較占空間,而且很多情況并不適用,比如參與者多于兩個(gè)的情況。
三、結(jié)語
寇本用例方法以基于目標(biāo)的結(jié)構(gòu)化/半結(jié)構(gòu)化文本描述見長(zhǎng),亞克申用例方法更重視UML可視化建模和用例驅(qū)動(dòng)過程。兩者盡管同宗同源[1],卻在一些使用細(xì)節(jié)上存在著明顯差異,而且各自還在沿著既有軌道繼續(xù)向前發(fā)展。 本文提出的統(tǒng)一用例方法并不是一種全新的方法,UUCM僅僅是個(gè)符號(hào)或代稱(也許可以有其他更好的名稱),它實(shí)質(zhì)上代表了一種解決方案和思路,目的是吸收亞克申和寇本用例方法的長(zhǎng)處,消除兩者的不一致,從而幫助實(shí)踐者盡可能規(guī)避使用上的誤區(qū),發(fā)揮用例和UML方法“1+1〉2”的聯(lián)合優(yōu)勢(shì)。這既是實(shí)踐的選擇,也是現(xiàn)實(shí)的需要。
話說天下IT之勢(shì),合久必分,分久必合。UUCM不是句號(hào),而是一個(gè)新的起點(diǎn)。出于商業(yè)、私人或其他方面的原因,國內(nèi)外許多技術(shù)流派分呈的局面會(huì)長(zhǎng)久持續(xù)下去,這本身是一件好事。不過,對(duì)于我們實(shí)踐者來說,選擇實(shí)用的工程技術(shù)時(shí)不應(yīng)有門派分割的障礙。對(duì)于特定的場(chǎng)合、特定的項(xiàng)目,企業(yè)人往往只有一個(gè)明智的選擇,那就是:用最小的成本創(chuàng)造最大的客戶價(jià)值。所以,對(duì)于實(shí)用型技術(shù)我們完全可以采取拿來主義的態(tài)度,防止guru-locked-in,適用的即是最好的!
posted @ 2010-03-04 14:03 Silver.Lee 閱讀(459) 評(píng)論(0) 編輯
統(tǒng)一建模語言UML輕松入門之用例
目前,在的內(nèi)地版《神雕俠侶》中,楊過和小龍女有一份不為人知的默契與浪漫,那就是他們所繪制的并肩小人圖。這樣的小人圖,是UML用例圖的一部分,被稱為參與者。
2.1 用例與用例圖
用例是需求分析中最重要的概念,需求表征了一個(gè)系統(tǒng)的設(shè)計(jì)特性、特征和行為,描述一個(gè)系統(tǒng)的需求意味著描述了建立在該系統(tǒng)外部的事物與系統(tǒng)之間的契約,契約上聲明了期望系統(tǒng)做什么。
需求獲取(Requirement Elicitation) 是需求工程的主體,其主要工作是建立待開發(fā)系統(tǒng)的模型,而用例就是用于建立這種模型的良好方法。用例最初由Ivar Jackboson博士提出,后被綜合到UML規(guī)范之中,成為需求表述的標(biāo)準(zhǔn)化體系。前文已經(jīng)提到,整個(gè)RUP流程都是"用例驅(qū)動(dòng)"的,各種類型的開發(fā)活動(dòng)包括項(xiàng)目管理、分析、設(shè)計(jì)、測(cè)試、實(shí)現(xiàn)等以用例為主要輸入工件,用例模型奠定了整個(gè)系統(tǒng)軟件開發(fā)的基礎(chǔ),用例被認(rèn)作第二代面向?qū)ο蠹夹g(shù)的標(biāo)志,可見其重要性非同一般。
我們先來給出一個(gè)具體而簡(jiǎn)單的用例圖,即"圖書管理系統(tǒng)"用例圖,如圖2.1。在用例圖中主要涉及到參與者(又稱角色、執(zhí)行者)、用例以及二者之間的通訊關(guān)聯(lián)。
圖2.1 圖書管理系統(tǒng)用例圖
參與者
參與者是與系統(tǒng)、子系統(tǒng)或類發(fā)生交互的外部用戶、進(jìn)程或其他系統(tǒng)。參與者可以是人、另一個(gè)計(jì)算機(jī)系統(tǒng)或一些可運(yùn)行的進(jìn)程。在圖2.1中,"讀者"和"管理員"即為參與者。
參與者之間可以存在泛化關(guān)系,例如,在圖2.1所示圖書館管理系統(tǒng)用例圖中,可以認(rèn)為"讀者"是"學(xué)生讀者"和"教師讀者"的泛化,而"學(xué)生讀者"還可以具體化為"本科生讀者"和"研究生讀者";同樣,"圖書管理人員"也是"采購員"、"編目員"及"借閱人員"的泛化。圖2.2表示出了參與者之間的泛化關(guān)系。
圖2.2 參與者泛化關(guān)系
用例
用例是外部可見的一個(gè)系統(tǒng)功能,這些功能由系統(tǒng)所提供,并通過與參與者之間消息的交換來表達(dá)。用例的用途是在不揭示系統(tǒng)內(nèi)部構(gòu)造的情況下定義行為序列,它把系統(tǒng)當(dāng)作一個(gè)黑箱,表達(dá)整個(gè)系統(tǒng)對(duì)外部用戶可見的行為。
鑒于用例的特點(diǎn),用例一般被命名為一個(gè)能夠說明目標(biāo)的動(dòng)名詞組。如圖2.1中的"借書"、"還書"和"管理圖書"皆為動(dòng)名詞組。
用例之間也可以存在包含、擴(kuò)展和泛化等關(guān)系:
(1)包含關(guān)系:用例可以簡(jiǎn)單地包含其他用例具有的行為,并把它所包含的用例行為做為自身行為的一部分,這被稱作包含關(guān)系。
(2)擴(kuò)展關(guān)系:擴(kuò)展關(guān)系是從擴(kuò)展用例到基本用例的關(guān)系,它說明為擴(kuò)展用例定義的行為如何插入到為基本用例定義的行為中。它是以隱含形式插入的,也就是說,擴(kuò)展用例并不在基本用例中顯示。在以下幾種情況下,可使用擴(kuò)展用例:
a.表明用例的某一部分是可選的系統(tǒng)行為(這樣,您就可以將模型中的可選行為和必選行為分開);
b.表明只在特定條件(如例外條件)下才執(zhí)行的分支流;
c.表明可能有一組行為段,其中的一個(gè)或多個(gè)段可以在基本用例中的擴(kuò)展點(diǎn)處插入。所插入的行為段和插入的順序取決于在執(zhí)行基本用例時(shí)與主角進(jìn)行的交互。
圖2.3給出了一個(gè)擴(kuò)展關(guān)系的例子,在還書的過程中,只有在例外條件(讀者遺失書籍)的情況下,才會(huì)執(zhí)行賠償遺失書籍的分支流。
圖2.3用例擴(kuò)展關(guān)系
(3)泛化關(guān)系:用例可以被特別列舉為一個(gè)或多個(gè)子用例,這被稱做用例泛化。當(dāng)父用例能夠被使用時(shí),任何子用例也可以被使用。如在圖2.4中,訂票是電話訂票和網(wǎng)上訂票的抽象。
圖2.4用例泛化關(guān)系
通訊關(guān)聯(lián)
通訊關(guān)聯(lián)用于表示參與者和用例之間的對(duì)應(yīng)關(guān)系,它表示參與者使用了系統(tǒng)中的哪些用例(或者說系統(tǒng)所提供的用例被哪些參與者使用)。
通訊關(guān)聯(lián)以箭頭或?qū)嵕€表示。若使用箭頭,箭頭所指方將是對(duì)話的被動(dòng)接受者;如果不強(qiáng)調(diào)對(duì)話中的主動(dòng)與被動(dòng)關(guān)系,則可以使用不帶箭頭的關(guān)聯(lián)實(shí)線。
2.2建立用例模型
知道了用例與用例圖的概念,我們還需要懂得怎樣建立用例模型,即怎樣找出參與者、用例以及定義用例的過程。一般來說,建立用例模型的步驟為:
(1)確定誰會(huì)直接使用該系統(tǒng),即參與者(Actor),為了發(fā)現(xiàn)參與者,我們可以嘗試問如下問題:
a. 誰/什么使用系統(tǒng)?
b. 誰/什么從系統(tǒng)獲得信息?
c. 誰/什么向系統(tǒng)提供信息?
d. 誰/什么支持、維護(hù)系統(tǒng)?
e. 哪些其它系統(tǒng)使用此系統(tǒng)?
f. 公司的哪個(gè)部門使用系統(tǒng)?
…
(2)選取其中一個(gè)參與者;
(3)定義該參與者希望系統(tǒng)做什么,參與者希望系統(tǒng)做的每件事成為一個(gè)用例,為了發(fā)現(xiàn)用例,我們可以嘗試問如下問題:
a. 為什么該參與者想要使用此系統(tǒng)?
b. 該參與者是否要?jiǎng)?chuàng)建、保存、更改、移動(dòng)或讀取系統(tǒng)的數(shù)據(jù)?如果是,為什么?
c. 該參與者是否要通知系統(tǒng)外部事件或變化?
d. 該參與者是否需要知道系統(tǒng)內(nèi)部的特定事件?
…
(4)對(duì)每件事來說,何時(shí)參與者會(huì)使用系統(tǒng),通常會(huì)發(fā)生什么,這就是用例的基本過程;
(5)描述該用例的基本過程;
(6)考慮一些可變情況,把他們創(chuàng)建為擴(kuò)展用例;
(7)復(fù)審不同用例的描述,找出其中的相同點(diǎn),抽出相同點(diǎn)作為共同的用例;
(8)重復(fù)步驟2-7找出每一個(gè)用例。
參與者檢查的參考標(biāo)準(zhǔn)如下:
(1)是否您已找到所有的參與者?也就是說,是否您已經(jīng)對(duì)系統(tǒng)環(huán)境中的所有參與者都進(jìn)行了說明和建模?
(2)每個(gè)參與者是否至少涉及到一個(gè)用例?
(3)您能否列出至少兩名可以作為特定參與者的人員?
(4)是否有參與者擔(dān)任與系統(tǒng)相關(guān)的相似參與者?如果有,您應(yīng)該將他們合并到一個(gè)參與者中。
用例檢查的參考標(biāo)準(zhǔn)如下:
(1)用例模型的簡(jiǎn)介部分簡(jiǎn)明清晰地概述此系統(tǒng)的目的和功能;
(2)所有的用例已確定,這些用例共同說明所有的必要行為;
(3)所有的功能性需求都至少映射到一個(gè)用例;
(4)該用例模型不包含多余的行為,所有的用例都可回溯到某個(gè)功能性需求來證明其合理性。
用例圖從總體上大致描述了系統(tǒng)所能提供的各種服務(wù),讓我們對(duì)于系統(tǒng)的功能有一個(gè)總體的認(rèn)識(shí),僅此還是不夠的,我們還需要描述每一個(gè)用例的詳細(xì)信息,即用例規(guī)約。用例模型正是由用例圖和每一個(gè)用例的詳細(xì)描述――用例規(guī)約所組成的。RUP中提供了用例規(guī)約的模板,包含以下內(nèi)容:
(1)簡(jiǎn)要說明 (Brief Description):簡(jiǎn)要介紹該用例的作用和目的;
(2)事件流 (Flow of Event):包括基本流和備選流,事件流應(yīng)該表示出所有的場(chǎng)景;
(3)用例場(chǎng)景 (Use-Case Scenario) :包括成功場(chǎng)景和失敗場(chǎng)景,場(chǎng)景主要是由基本流和備選流組合而成的;
(4)特殊需求 (Special Requirement):描述與該用例相關(guān)的非功能性需求(包括性能、可靠性、可用性和可擴(kuò)展性等)和設(shè)計(jì)約束(所使用的操作系統(tǒng)、開發(fā)工具等);
(5)前置條件 (Pre-Condition):執(zhí)行用例之前系統(tǒng)必須所處的狀態(tài);
(6)后置條件 (Post-Condition):用例執(zhí)行完畢后系統(tǒng)可能處于的一組狀態(tài)。
用例規(guī)約基本上是用文本方式來表述的,為了更加清晰地描述事件流,也可以選擇使用狀態(tài)圖、活動(dòng)圖或序列圖來輔助說明(狀態(tài)圖有助于描述與狀態(tài)相關(guān)的系統(tǒng)行為,活動(dòng)圖有助于描述復(fù)雜的決策流程,序列圖適合于描述基于時(shí)間順序的消息傳遞)。另外,只要對(duì)簡(jiǎn)潔明了地表達(dá)用例有幫助,我們就可以在用例中任意粘貼用戶界面、流程的圖形化顯示方式及其他圖形。
posted @ 2010-03-04 14:01 Silver.Lee 閱讀(101) 評(píng)論(0) 編輯
用例建模技巧
從參與者的角度并以主動(dòng)語態(tài)編寫用例。
應(yīng)該以主動(dòng)語態(tài):“學(xué)生表明參加研習(xí)班意向”,而不是被動(dòng)語態(tài)“研習(xí)班意向被學(xué)生表明”來編寫用例。而且,應(yīng)該從參與者的角度來編寫用例。畢竟,用例的目的是理解用戶如何對(duì)系統(tǒng)進(jìn)行操作。
編寫方案文本,而非功能需求。
用例描述的是對(duì)參與者來說有價(jià)值的一系列行動(dòng),而不是特性集。例如,“招收研習(xí)班的學(xué)生”用例描述的是學(xué)生如何與系統(tǒng)交互來參加研習(xí)班。它沒有描述用戶界面看上去是什么樣子,或者它是如何工作的。有一些其它的模型來描述這些重要的信息,例如用戶界面模型和增補(bǔ)規(guī)范。面向?qū)ο蠓治龇浅?fù)雜,因此需要對(duì)它使用幾種模型,并且應(yīng)該適當(dāng)?shù)貞?yīng)用每一種模型。
用例只記載行為需求。
用例既不是類規(guī)范,也不是數(shù)據(jù)規(guī)范。這是應(yīng)該由概念性模型捕捉的一種信息,在對(duì)象世界中,它是通過 UML 類模型建模的。您往往會(huì)引用概念性模型中描述的類,例如,“參加研習(xí)班”用例包括了“研習(xí)班”和“學(xué)生”等概念,它們都將由概念性模型描述。
不要忘記用戶界面。
系統(tǒng)用例經(jīng)常引用主用戶界面 (UI) 元素,這些元素常常稱為“邊界”或“用戶界面”項(xiàng),例如 HTML 頁面和報(bào)表。用例有時(shí)也引用一些次要的 UI 元素,例如按鈕或數(shù)據(jù)輸入字段,但這種級(jí)別的細(xì)節(jié)并不太常見。
創(chuàng)建用例模板。
用例包含了相當(dāng)數(shù)量的信息,這些信息可以輕易地以常見格式記載。您應(yīng)該考慮開發(fā)自己的模板(請(qǐng)參閱技巧“記載用例”)。
始終如一地組織用例圖。
一般的做法是垂直地繪制繼承 (inheritance) 和擴(kuò)展 (extend) 關(guān)聯(lián),在父/基本用例下面繪制繼承/擴(kuò)展用例。同樣,通常水平繪制包含 (include) 關(guān)聯(lián)。請(qǐng)注意,這些是簡(jiǎn)單的經(jīng)驗(yàn)法則 -- 只要始終遵循這些法則,產(chǎn)生的圖將很容易理解。
不要忘記系統(tǒng)對(duì)參與者行動(dòng)的響應(yīng)。
用例既應(yīng)該描述參與者是如何與系統(tǒng)交互的,也應(yīng)該描述系統(tǒng)如何響應(yīng)這些交互。例如,在“參加研習(xí)班”用例中,如果系統(tǒng)在學(xué)生表明他們希望參加研習(xí)班時(shí)沒有做出響應(yīng),學(xué)生就會(huì)很沮喪地離開。
備選行動(dòng)過程非常重要。
如果一切順利,使用的將是基本行動(dòng)過程 -- 但也不要忘記備選過程。引入備選過程是為了描述潛在的使用錯(cuò)誤以及商業(yè)邏輯錯(cuò)誤和異常。這些重要的信息對(duì)于驅(qū)動(dòng)系統(tǒng)的設(shè)計(jì)來說很有必要,因此不要忘記在用例中對(duì)它們建模。
不要被 <<include>> 和 <<extend>> 關(guān)聯(lián)所困擾。
我不是很確定到底發(fā)生了什么事,但我總是在想包含 (include) 和擴(kuò)展 (extend) 關(guān)聯(lián),以及舊版本 UML 中使用 (uses) 和擴(kuò)展 (extends) 關(guān)聯(lián)的正確使用從來沒有得到很好的描述。結(jié)果,用例建模小組往往在這些關(guān)聯(lián)的正確應(yīng)用上爭(zhēng)論不休,在整個(gè)建模技術(shù)中一些有趣但次要的部分上浪費(fèi)了驚人的時(shí)間。我曾在一個(gè)組織中工作,這家組織居然取締了 <<include>> 和 <<extend>> 原型的使用,幾個(gè)星期后,當(dāng)意識(shí)到公司仍然需要這些概念時(shí)不得不撤消了這種極端的解決方案,而這時(shí)該組織對(duì)它們的正確使用還沒有達(dá)成共識(shí)。
讓用例帶動(dòng)用戶文檔。
用戶文檔的目的是描述如何使用系統(tǒng)。每個(gè)用例都描述了參與者通過使用系統(tǒng)所采取的一系列動(dòng)作。簡(jiǎn)而言之,用例包含從中開始編寫問黨用戶穩(wěn)當(dāng)?shù)男畔?。例如,可以使用“參加研?xí)班”用例作為基礎(chǔ)來編寫系統(tǒng)用戶文檔的“如何參加研習(xí)班”一節(jié)。
讓用例帶動(dòng)演示。
軟件開發(fā)過程中的一部分是向項(xiàng)目資金管理者通報(bào)工作成果,因此有時(shí)需要提供演示。因?yàn)橛美菑挠脩舻慕嵌染帉懙?,它們包含了演示中?duì)資金管理者可能希望聽到的事物的有價(jià)值的深刻見解。換句話說,用例通常包含制定演示稿所需的邏輯。
參考資料 The Object Primer 2nd Edition,由 Scott W. Ambler 著。New York: Cambridge University Press, 2001。
The Unified Process Inception Phase,由 Scott W. Ambler 和 Larry L. Constantine 合著。Gilroy, CA: R&D Books, 2000。
Software For Use: A Practical Guide to the Models and Methods of Usage-Centered Design,由 Larry L. Constantine and Lucy A.D. Lockwood 合著。
The Unified Modeling Language Reference Manual,由 James Rumbaugh、Grady Booch 和 Ivar Jacobson 合著。Reading, MA: Addison-Wesley Longman, Inc., 1999。
posted @ 2010-03-04 14:00 Silver.Lee 閱讀(67) 評(píng)論(0) 編輯
2010年2月22日
SQL Server不允許進(jìn)行遠(yuǎn)程連接的解決辦法
剛剛安裝的數(shù)據(jù)庫系統(tǒng),按照默認(rèn)安裝的話,很可能在進(jìn)行遠(yuǎn)程連接時(shí)報(bào)錯(cuò),通常是錯(cuò)誤:"在連接到SQLServer2005時(shí),在默認(rèn)的設(shè)置下SQLServer不允許進(jìn)行遠(yuǎn)程連接可能會(huì)導(dǎo)致此失敗。(provider:命名管道提供程序,error:40-無法打開到SQLServer的連接)",現(xiàn)在針對(duì)此問題總結(jié)如下:
明白了SQLServer是個(gè)網(wǎng)絡(luò)數(shù)據(jù)庫就可迎刃而解了,簡(jiǎn)單的分為下面的幾種情況。
◆1.數(shù)據(jù)庫引擎沒有啟動(dòng)。有兩種啟動(dòng)方式:
(1)開始->程序->MicrosoftSQLServer2005->SQLServer2005外圍應(yīng)用配置器,在打開的界面單擊"服務(wù)的連接的外圍應(yīng)用配置器",在打開的界面中找到DatabaseEngine,單擊"服務(wù)",在右側(cè)查看是否已啟動(dòng),如果沒有啟動(dòng)可單擊"啟動(dòng)",并確保"啟動(dòng)類型"為自動(dòng),不要為手動(dòng),否則下次開機(jī)時(shí)又要手動(dòng)啟動(dòng);
(2)可打開:開始->程序->MicrosoftSQLServer2005->配置工具->SQLServerConfigurationManager,選中SQLServer2005服務(wù)中SQLServer(MSSQLSERVER),并單擊工具欄中的"啟動(dòng)服務(wù)"按鈕把服務(wù)狀態(tài)改為啟動(dòng);
使用上面兩種方式時(shí),有時(shí)候在啟動(dòng)的時(shí)候可能會(huì)出現(xiàn)錯(cuò)誤,不能啟動(dòng),這時(shí)就要查看"SQLServer2005配置管理器"中的SQLServer2005網(wǎng)絡(luò)配置->MSSQLSERVER協(xié)議中的VIA是否已啟用,如果已啟用,則把它禁止.然后再執(zhí)行上述一種方式操作就可以了.
◆2.是否已經(jīng)允許遠(yuǎn)程連接。這個(gè)部分可以簡(jiǎn)單的分為4個(gè)方面,分別是在SQLServer上啟用遠(yuǎn)程連接、啟用SQLServer瀏覽服務(wù)、在Windows防火墻中為SQLServer2005創(chuàng)建例外和在Windows防火墻中為“SQLBrowser”創(chuàng)建例外。下面是幾個(gè)具體的操作方式:
在SQLServer實(shí)例上啟用遠(yuǎn)程連接
◆1.指向“開始->程序->MicrosoftSQLServer2005->配置工具->SQLServer外圍應(yīng)用配置器”
◆2.在“SQLServer2005外圍應(yīng)用配置器”頁,單擊“服務(wù)和連接的外圍應(yīng)用配置器”
◆3.然后單擊展開“數(shù)據(jù)庫引擎”,選中“遠(yuǎn)程連接”,在右邊選中“本地連接和遠(yuǎn)程連接”,
再選擇要使用的協(xié)議,(這個(gè)地方應(yīng)當(dāng)啟用TCP/IP和命名管道服務(wù)!)單擊“應(yīng)用”,您會(huì)看到下消息:
“直到重新啟動(dòng)數(shù)據(jù)庫引擎服務(wù)后,對(duì)連接設(shè)置所做的更改才會(huì)生效。”,單擊“確定”按鈕返回
◆4.展開“數(shù)據(jù)庫引擎”,選中“服務(wù)”,在右邊單擊“停止”,等到MSSQLSERVER服務(wù)停止,
然后單擊“啟動(dòng)”,重新啟動(dòng)MSSQLSERVER服務(wù)。
啟用SQLServer瀏覽器服務(wù)
◆1.指向“開始->程序->MicrosoftSQLServer2005->配置工具->SQLServer外圍應(yīng)用配置器”
◆2.在“SQLServer2005外圍應(yīng)用配置器”頁,單擊“服務(wù)和連接的外圍應(yīng)用配置器”
◆3.然后單擊展開“SQLServerBrowser”,選中“服務(wù)”,在右邊“啟動(dòng)類型”選擇“自動(dòng)”,
再單擊“啟動(dòng)”,單擊“確定”按鈕返回
在Windows防火墻中為“SQLServer2005”創(chuàng)建例外
◆1.在Windows防火墻設(shè)置界面中,選擇“例外”選項(xiàng)卡,然后單擊“添加程序”
◆2.在“添加程序窗口”中單擊“瀏覽”
◆3.然后找到“C:ProgramFilesMicrosoftFilesMicrosoftSQLServerMSSQL.1MSSQLBinnsqlservr.exe”,
單擊“確定”返回
注意:路徑可能會(huì)根據(jù)SQLServer2005安裝不同而不同。MSSQL.1是占位符,對(duì)應(yīng)數(shù)據(jù)庫實(shí)例ID。
◆4.對(duì)每個(gè)需要打開遠(yuǎn)程訪問的SQLServer2005實(shí)例,重復(fù)步驟1至3。
在Windows防火墻中為“SQLBrowser”創(chuàng)建例外
◆1.在Windows防火墻設(shè)置界面中,選擇“例外”選項(xiàng)卡,然后單擊“添加程序”
◆2.在“添加程序窗口”中單擊“瀏覽”
◆3.然后找到“C:ProgramFilesMicrosoftFilesMicrosoftSQLServer90Sharedsqlbrowser.exe”,
單擊“確定”返回
注意:路徑可能會(huì)根據(jù)SQLServer2005安裝不同而不同。在使用.NET開發(fā)進(jìn)行時(shí),會(huì)遇到使用連接字符串連接SQLServer2005數(shù)據(jù)庫使用機(jī)器名稱和localhost都能連接,但是使用IP地址卻不能連接的問題,解決的辦法是在SQLServer實(shí)例上啟用本地和遠(yuǎn)程連接,并且在選擇協(xié)議的時(shí)候使用TCP/IP和命名管道服務(wù)即可解決。
posted @ 2010-02-22 15:39 Silver.Lee 閱讀(31) 評(píng)論(0) 編輯
2010年2月5日
為什么要使用代理模式
代理這個(gè)詞大家肯定已經(jīng)非常熟悉,因?yàn)楝F(xiàn)實(shí)中接觸的很多,其實(shí)現(xiàn)實(shí)中的東西恰恰可以非常形象和直觀地反映出模式的抽象過程以及本質(zhì)。現(xiàn)在房子不是吵得熱火朝天嗎?我們就以房子為例,來撥開代理的面紗。
假設(shè)你有一套房子要賣,一種方法是你直接去網(wǎng)上發(fā)布出售信息,然后直接帶要買房子的人來看房子、過戶等一直到房子賣出去,但是可能你很忙,你沒有時(shí)間去處理這些事情,所以你可以去找中介,讓中介幫你處理這些瑣碎事情,中介實(shí)際上就是你的代理。本來是你要做的事情,現(xiàn)在中介幫助你一一處理,對(duì)于買方來說跟你直接交易跟同中介直接交易沒有任何差異,買方甚至可能覺察不到你的存在,這實(shí)際上就是代理的一個(gè)最大好處。
接下來我們?cè)偕钊肟紤]一下為什么你不直接買房子而需要中介?其實(shí)一個(gè)問題恰恰解答了什么時(shí)候該用代理模式的問題。
原因一:你可能在外地上班,買房子的人沒法找到你直接交易。
對(duì)應(yīng)到我們程序設(shè)計(jì)的時(shí)候就是:客戶端無法直接操作實(shí)際對(duì)象。那么為什么無法直接操作?一種情況是你需要調(diào)用的對(duì)象在另外一臺(tái)機(jī)器上,你需要跨越網(wǎng)絡(luò)才能訪問,如果讓你直接coding去調(diào)用,你需要處理網(wǎng)絡(luò)連接、處理打包、解包等等非常復(fù)雜的步驟,所以為了簡(jiǎn)化客戶端的處理,我們使用代理模式,在客戶端建立一個(gè)遠(yuǎn)程對(duì)象的代理,客戶端就象調(diào)用本地對(duì)象一樣調(diào)用該代理,再由代理去跟實(shí)際對(duì)象聯(lián)系,對(duì)于客戶端來說可能根本沒有感覺到調(diào)用的東西在網(wǎng)絡(luò)另外一端,這實(shí)際上就是Web Service的工作原理。另一種情況雖然你所要調(diào)用的對(duì)象就在本地,但是由于調(diào)用非常耗時(shí),你怕影響你正常的操作,所以特意找個(gè)代理來處理這種耗時(shí)情況,一個(gè)最容易理解的就是Word里面裝了很大一張圖片,在word被打開的時(shí)候我們肯定要加載里面的內(nèi)容一起打開,但是如果等加載完這個(gè)大圖片再打開Word用戶等得可能早已經(jīng)跳腳了,所以我們可以為這個(gè)圖片設(shè)置一個(gè)代理,讓代理慢慢打開這個(gè)圖片而不影響Word本來的打開的功能。申明一下我只是猜可能Word是這么做的,具體到底怎么做的,俺也不知道。
原因二:你不知道怎么辦過戶手續(xù),或者說除了你現(xiàn)在會(huì)干的事情外,還需要做其他的事情才能達(dá)成目的。
對(duì)應(yīng)到我們程序設(shè)計(jì)的時(shí)候就是:除了當(dāng)前類能夠提供的功能外,我們還需要補(bǔ)充一些其他功能。最容易想到的情況就是權(quán)限過濾,我有一個(gè)類做某項(xiàng)業(yè)務(wù),但是由于安全原因只有某些用戶才可以調(diào)用這個(gè)類,此時(shí)我們就可以做一個(gè)該類的代理類,要求所有請(qǐng)求必須通過該代理類,由該代理類做權(quán)限判斷,如果安全則調(diào)用實(shí)際類的業(yè)務(wù)開始處理。可能有人說為什么我要多加個(gè)代理類?我只需要在原來類的方法里面加上權(quán)限過濾不就完了嗎?在程序設(shè)計(jì)中有一個(gè)類的單一性原則問題,這個(gè)原則很簡(jiǎn)單,就是每個(gè)類的功能盡可能單一。為什么要單一,因?yàn)橹挥泄δ軉我贿@個(gè)類被改動(dòng)的可能性才會(huì)最小,就拿剛才的例子來說,如果你將權(quán)限判斷放在當(dāng)前類里面,當(dāng)前這個(gè)類就既要負(fù)責(zé)自己本身業(yè)務(wù)邏輯、又要負(fù)責(zé)權(quán)限判斷,那么就有兩個(gè)導(dǎo)致該類變化的原因,現(xiàn)在如果權(quán)限規(guī)則一旦變化,這個(gè)類就必需得改,顯然這不是一個(gè)好的設(shè)計(jì)。
好了,原理的東西已經(jīng)講得差不多了,要是再講個(gè)沒完可能大家要扔磚頭了。呵呵,接下來就看看怎么來實(shí)現(xiàn)代理。
代理模式的實(shí)現(xiàn):
其實(shí)代理模式還是很容易實(shí)現(xiàn)的,隨便舉個(gè)例子,比如你有一個(gè)類負(fù)責(zé)返回員工的薪資信息,如下:
Java代碼
publicclassBusinessClass
{
publicdoubleGetPayroll(stringemployee)
{
//返回薪資結(jié)果
return1000;
}
}
由于薪資信息是公司的機(jī)密信息,不是誰都能調(diào)用查看,所以我們?yōu)樵擃愖鲆粋€(gè)代理來做用戶身份的驗(yàn)證,代碼如下:
publicclassProxy
{
privateBusinessClassbc;
publicProxy(BusinessClassbc)
{
this.bc=bc;
}
publicdoubleGetPayroll(stringuser)
{
//判斷user權(quán)限
//如果不符合返回null,或者拋出異常
if(IsManage(user))
{
returnbc.GetPayroll(”張三”);
}
thrownewException(”你沒有該權(quán)限?!?;
}
}
注意:代理類需要使用被代理類來做業(yè)務(wù)邏輯,所以代理類需要包含被代理類的實(shí)例,這跟適配器模式是一樣的。
到目前為止目的其實(shí)已經(jīng)達(dá)到了,但是現(xiàn)實(shí)中我們常常會(huì)再為代理類和被代理類抽象出一個(gè)公共接口,如下:
publicinterfaceIBusinessClass
{
doubleGetPayroll(stringuser);
}
很多人肯定會(huì)問為什么要抽象這個(gè)接口呢?其實(shí)抽象接口有一個(gè)最大的原因就是約束雙方的行為!什么意思呢?其實(shí)就是我逼迫Proxy必須實(shí)現(xiàn)某些方法,而這些方法恰恰是對(duì)外公開的主要業(yè)務(wù)方法。當(dāng)然也可以靠程序員自律,但是多一個(gè)約束總歸是好的,至少如果沒有實(shí)現(xiàn)指定方法我們可以在編譯期就發(fā)現(xiàn)錯(cuò)誤,總比執(zhí)行時(shí)才能發(fā)現(xiàn)錯(cuò)誤要好。另外的原因可能都得歸結(jié)到使用接口的好處上去了,這里不再贅述,自己去查接口的文章介紹了。
posted @ 2010-02-05 17:48 Silver.Lee 閱讀(560) 評(píng)論(0) 編輯
Single Responsibility Principle (SRP) - OO設(shè)計(jì)的單一職責(zé)原則
前言
Robert C. Martin氏為我們總結(jié)了在面向?qū)ο蟮脑O(shè)計(jì)(OOD)中應(yīng)該遵循的原則,這些原則被稱為“Principles of OOD”,關(guān)于“Principles of OOD”的相關(guān)文章可以從Object Menter 得到。
本文介紹“Principles of OOD”中的單一職責(zé)原則:Single Responsibility Principle (SRP)。
可以從這里查看Single Responsibility Principle (SRP)的原文 。
概要
There should never be more than one reason for a class to change.
永遠(yuǎn)不要讓一個(gè)類存在多個(gè)改變的理由。
換句話說,如果一個(gè)類需要改變,改變它的理由永遠(yuǎn)只有一個(gè)。如果存在多個(gè)改變它的理由,就需要重新設(shè)計(jì)該類。
SRP(Single Responsibility Principle)原則的核心含意是:只能讓一個(gè)類有且僅有一個(gè)職責(zé)。這也是單一職責(zé)原則的命名含義。
為什么一個(gè)類不能有多于一個(gè)以上的職責(zé)呢?
如果一個(gè)類具有一個(gè)以上的職責(zé),那么就會(huì)有多個(gè)不同的原因引起該類變化,而這種變化將影響到該類不同職責(zé)的使用者(不同用戶):
1,一方面,如果一個(gè)職責(zé)使用了外部類庫,則使用另外一個(gè)職責(zé)的用戶卻也不得不包含這個(gè)未被使用的外部類庫。
2,另一方面,某個(gè)用戶由于某個(gè)原因需要修改其中一個(gè)職責(zé),另外一個(gè)職責(zé)的用戶也將受到影響,他將不得不重新編譯和配置。
這違反了設(shè)計(jì)的開閉原則,也不是我們所期望的。
職責(zé)的劃分
既然一個(gè)類不能有多個(gè)職責(zé),那么怎么劃分職責(zé)呢?
Robert.C Martin給出了一個(gè)著名的定義:所謂一個(gè)類的一個(gè)職責(zé)是指引起該類變化的一個(gè)原因。
If you can think of more than one motive for changing a class, then that class has more than one responsibility.
如果你能想到一個(gè)類存在多個(gè)使其改變的原因,那么這個(gè)類就存在多個(gè)職責(zé)。
Single Responsibility Principle (SRP)的原文 里舉了一個(gè)Modem的例子來說明怎么樣進(jìn)行職責(zé)的劃分,這里我們也沿用這個(gè)例子來說明一下:
SRP違反例:
Modem.java
interface Modem {
public void dial(String pno);//撥號(hào)
public void hangup();//掛斷
public void send(char c);//發(fā)送數(shù)據(jù)
public char recv();//接收數(shù)據(jù)
}
咋一看,這是一個(gè)沒有任何問題的接口設(shè)計(jì)。但事實(shí)上,這個(gè)接口包含了2個(gè)職責(zé):第一個(gè)是連接管理(dial, hangup);另一個(gè)是數(shù)據(jù)通信(send, recv)。很多情況下,這2個(gè)職責(zé)沒有任何共通的部分,它們因?yàn)椴煌睦碛啥淖儯徊煌糠值某绦蛘{(diào)用。
所以它違反了SRP原則。
下面的類圖將它的2個(gè)不同職責(zé)分成2個(gè)不同的接口,這樣至少可以讓客戶端應(yīng)用程序使用具有單一職責(zé)的接口:
讓ModemImplementation實(shí)現(xiàn)這兩個(gè)接口。我們注意到,ModemImplementation又組合了2個(gè)職責(zé),這不是我們希望的,但有時(shí)這又是必須的。通常由于某些原因,迫使我們不得不綁定多個(gè)職責(zé)到一個(gè)類中,但我們至少可以通過接口的分割來分離應(yīng)用程序關(guān)心的概念。
事實(shí)上,這個(gè)例子一個(gè)更好的設(shè)計(jì)應(yīng)該是這樣的,如圖:
小結(jié)
Single Responsibility Principle (SRP)從職責(zé)(改變理由)的側(cè)面上為我們對(duì)類(接口)的抽象的顆粒度建立了判斷基準(zhǔn):在為系統(tǒng)設(shè)計(jì)類(接口)的時(shí)候應(yīng)該保證它們的單一職責(zé)性。
愛華網(wǎng)


