第三章 領域模組化與系統行為分析 用例模型原則上不是面向對象的,它描述的是系統的功能,隻是建立系統的最初的輸入,為了更細膩的分析需求,從面向對象的角度,可以建立領域模型。 識别一個豐富的對象集或者領域類集,是面向對象分析的核心工作,做好這項工作,将會在設計和實作期間獲得豐富的回報。 第一節 領域模組化的思想和方法 領域模型是作為設計軟體對象的啟發來源,也是後續工件的必須輸入。 領域模型是說明問題域裡(對模組化者來說)有意義的 領域類,它是面向對象分序的時候要建立的最重要的工作(必須說明,用例雖然也是一個重要的分析工作,但它并不是面向對象的,它是強調的概念的過程視圖)。 一、領域模組化的思想及其方法學問題 什麼是“問題域”和“領域模組化”? 問題域 : 現實世界中系統所要解決問題的領域為“問題域”,如“銀行業務”屬于“銀行的問題域”。 領域模組化 : 1.我們設計一個系統,總是希望它能解決一些問題,這些問題總是會映射到現實問題和概念。 2, 對這些問題進行歸納、分析的過程就是領域模組化(這個域,指的就是問題域)。 建立領域模型的好處: 1,通過建立領域模型能夠從現實的問題域中找到最有代表性的概念對象 2,并發現出其中的類和類之間的關系,因為所捕捉出的類是回報問題域本質内容的資訊。 經典的面向對象的分析或調研的步驟,是把一個相關的領域,分解為單個領域類或者對象(是一個我們能夠了解的概念)。 領域模型是領域類或者是我們感興趣的現實對象的可視化表示。 它們也被稱之為:概念模型、領域對象模型、分析對象模型等。 在UML中,領域模型是不定義操作(方法)的一組類圖來說明,它主要表達: 1, 領域對象或者領域類 2, 領域類之間的關聯 3, 領域類的屬性 屬性用以表達對象的狀态。 ( 1 )三種領域類 1 ,邊界對象:參與者使用該對象與系統進行交流,也即邊界對象代表系統的内部工作和它所處環境之間的互動。 邊界對象将系統的其它部分和外部的相關事物隔離和保護起來。其主要的責任是:輸入、輸出和過濾。 2 ,實體對象:代表要儲存到持續存儲體中的資訊。實體類通常用業務域中的術語命名。 通過它可以表達和管理系統中的資訊。在模型中,系統中的關鍵概念以實體對象來表現。其主要的責任是:業務行為的主要承載體 3 ,控制對象:它協調其他類的工作,每個用例通常有一個控制類,控制用例中的時間順序。 它可能是與其它對象協作以實作用例的行為,控制類也稱管理類。其主要的責任:控制事件流,負責為實體類配置設定責任 有四個規則對應上面的三種分析類對象間的互動 1,用例的參與者隻能與邊界對象互動(這相當于結構化分析裡面的自動化邊界) 2,邊界對象隻能與控制對象和動作者互動(即不能直接通路實體對象) 3,實體對象隻能與控制對象互動 4,控制對象可以和邊界對象互動,也可以和實體互動,但是不能和動作者互動 三種領域類的UML的圖示如下: (2 )領域模組化的簡單例子 下面舉個簡單的例子,說明領域模組化的基本概念。 1 )問題的描述 例如:兩個領域類Payment(支付)Sale(售出)在領域模型中以一種有意義的方式關聯。 2 )關鍵概念 仔細考察上面的圖,可以看出,領域模型實際上是可視化了領域中的單詞或領域類,并且為這些單詞建立了領域類。 也就是說,領域模型是抽象了一個可視化字典。 模型展現了部分視圖或抽象,而忽略了模組化者不感興趣的細節。 它充分利用了人類的特點—大腦善于可視化思維。 3 )領域模型不是軟體元件的模型 領域模型視相關現實世界領域中事務的可視化表示,不是Java或者C#類這樣的軟體元件。 下面這些元素不适合在領域模型中表述: 1,軟體工件(視窗或資料庫) 2,職責或者方法:方法是個純粹的軟體概念,在設計工作期間考慮對象職責是非常重要的,但領域模型不考慮這些問題,在這裡考慮職責的正确方法是,給對象配置設定角色(比如收銀員)。 4 )領域類 領域模型表示領域中的領域類或詞彙,一個不是太準确的描述:一個領域類就是一個觀點、事務或者對象。 比較準确的表達: 領域類可以按照它的符号、内涵和外延來考慮。 l 符号:代表一個領域類的單詞或者圖檔。 l 内涵:領域類的定義。 l 外延:領域類定義的一組執行個體。 二、領域類的識别 我們的目标是在相關領域中建立有意義的領域類。 比如說建立“處理銷售”用例中的相關領域類。 一般來說,用大量細粒度的領域類來充分描述領域模型,比粗略描述要好。 下面是識别領域類的一些指導原則: l 不要認為領域模型中領域類越少越好,情況往往恰恰相反。 l 在初始識别階段往往會漏掉一些領域類,在後面考慮屬性和關聯的時候才會發現它,這是應該把它加上。 l 不要僅僅因為需求中沒有要求保留一些領域類的資訊,或者因為領域類沒有屬性,就排除掉這個領域類。 l 無屬性的領域類,或者在問題域裡面僅僅擔當行為的角色,而非資訊的角色的領域類,都可以是有效的領域類。 1 )識别領域類的政策 下面提供了兩種識别領域類的技巧。 1. 使用領域類分類清單。 2. 識别名詞短語。 2 )使用領域類分類清單 通過建立一個候選的領域類的清單,來開始建立模型。下面是一個從商店和航空訂票領域中抽取出來的概念清單(注意,排列不考慮重要性)。
領域類分類 | 示例 |
實體或具體對象 | (略) |
事物的設計、描述、或規範 | |
位置 | |
交易 | |
交易項目 | |
人的角色 | |
其它事物的容器 | |
容器包含的元素 | |
在該計算機之外的其它計算機或電子機械系統 | |
抽象名詞的概念 | |
組織 | |
過程(通常不表示一個概念,但可以被表示成一個概念) | |
規則和政策 | |
分類 | |
有關工作、契約和法律事務的記錄 | |
财務設施及服務 | |
手冊、文檔、引用論文、書籍 |
3 )根據名詞短語識别找出領域類 曾經有人提出了用名詞短語分析找出領域類的方法,然後把它們作為候選的領域類或者屬性。使用這種方法必須十分小心,從名詞機械的映射肯定是不行的,而且自然語言中的單詞本來就是模棱兩可的。 不過,這仍然是靈感的另一種來源,比如,我們來看一看原來寫出來的“處理銷售”的用例:
基本流程: 1.顧客攜帶購買的商品到達POS機收費口 2.收銀員開始一次新的銷售 3.收銀員輸入商品辨別 4.….. 重複 3 – 4 步,直到結束。 5.……… ……. 10.顧客攜帶商品和收據離開 |
仔細研究其中的名詞,可以看到很多有用的領域類(“記賬”、“提成”),也可能有些是屬性,請研究我們後面要讨論的關于區分屬性的和類的讨論。 這種方法的缺點就是不精确,但對我們研究問題會非常有用。 推薦: 把領域類分類,和詞語分析一起使用。 三、領域模組化的指導原則 1 )事物的命名和模組化 領域模型是問題域中的概念或這是事物的地圖,是以地圖繪制員的政策,也适用于領域模型的模組化。 l 使用地域中已有的地名(和城市名相同) l 排除不相關的特性(比如居民人數) l 不添加不屬于某個地方的事物(比如虛構的山川) 以此,我們建議使用如下的原則: l 給領域模型模組化,要使用問題域中的詞彙。 l 把和目前不相關的領域類排除在問題域之外。 l 領域模型應該排除不在目前考慮下的問題域中的事物。 2 )在識别領域類的時候一個常犯的錯誤 在建立領域模型的時候,最常犯的一個錯誤就是把原本是類的事物當作屬性來處理。 Store(商店)是Sale(出售)的一個屬性呢?還是單獨的領域類Store? 大部分的屬性有一個特征,就是它的性質是數字或者文本。 而商店不是數字和文本,是以Store應該是個類。 另一個例子: 考慮一下飛機訂票的問題,Destination(目的地)應該是Flight(航班)的屬性呢還是一個單獨的類Airport(包括屬性name)。 在現實世界中,目的地機場并不是數字和文本,它是一個占地面積很大的事物,是以應該是個領域類。 建議: 如果我們舉棋不定,最好把這樣的事物當做一個單獨的領域類,因為領域模型中,屬性非常少見。 四、分析相似的領域類 有一些情況是比較不太容易處理的。 舉個例子,我們來分析一下“Register(記錄)”和“POST(終端)”這兩個概念。 POST作為一個銷售終端,可以是用戶端任何終點的裝置(使用者PC,無線PDA),但早期商店是需要一個裝置來記錄(Register)銷售。 而POST實際上也需要這個能力。 可見,Register是一個更具抽象性的概念,在領域模型中,是不是應該用Register而不是POST嗎? 我們應該知道,領域模型其實沒有絕對正确和錯誤之分,隻有可用性大小的區分。 根據繪圖員原則,POST是一個領域中常見的術語,從熟悉和傳遞資訊的角度,POST是一個有用的符号。 但是,從模型的抽象和軟體實作互相獨立的目标來看,Register是一個更具吸引力和可用性的表達,它可以友善的表達記錄銷售位置的概念,也可以表達不同的終端裝置(如POST)。 兩種方式各具優點,關鍵是看你的領域類重點是表達什麼資訊。 這也是一個架構師必備的能力—抓住重點。 五、為非現實世界模組化 一些業務領域有自己獨特的概念,隻要這些概念是在業内被認可的,同樣可以建立領域類,比如在電信業可以建立這樣的領域類: 消息(Message)、連接配接(Connection)、端口(Port)、對話(Dialog)、路由(Route)、協定(Protocol)等。 六、規格說明或者描述領域類 在領域模型中,對領域類作規格說明的需求是相當普遍的,是以它值得我們來強調。 假定有下面的情形: l 一個Item執行個體代表商店中一個實際存在的商品 l 一個Item表達一個實際存在的商品,它有價格,ID兩個描述資訊 l 每次賣掉一個商品,就從軟體中删掉一個執行個體。 如果我們是這樣來表達: 那很可能會認為随着商品的賣出,它的價格也删掉了,顯然這是不對的。 比較好的表達方式是這樣的: 1 )何時需要規格說明類 在下面的情況下,需要添加領域類的說明類: l 商品或服務的資訊描述,獨立于商品或者服務目前已經存在的任何執行個體。 l 删除所描述的事物,會導緻維護資訊的丢失。 l 希望減少備援或者重複的資訊。 2 )服務的描述 作為領域類的執行個體可以是一次服務而不是一件商品,比如航空公司的航班服務。 假定航空公司由于事故取消了6個月的航班,這時它對應的Flight(航班)軟體對象也在計算機中删除了,那麼,航空公司就不再有航班記錄了。 是以比較好的辦法是添加一個FlightDestination(航班目的)的規格描述類,請看下面的例子。 七、統一過程中的領域模型 根據“ 統一過程的時間及其時間安排”的那張表,在UP中,通常在細化階段開始并完成領域模型的模組化。事實上,對于一個有經驗的系統構架師,在每次疊代裡開發領域模型,隻需要幾個小時就夠了。 在UP中,有一個業務對象模型(BOM),但實際上并不通用,而領域模型實際上是BOM的一個正是的變體。在RUP中,BOM是這樣來定義的:它是業務員和業務實體如何相關聯,以及為了完成業務如何寫作的抽象。 BOM可以用多種不同的圖(類圖、活動圖、順序圖)來表示,這些圖說明整個企業應該如何運作。 不過對于單個軟體的應用,這似乎是個不太通用的活動。盡管它還有一些變通,但是在系統架構設計中,領域模型仍然是最為廣泛的被采用的。 第二節 領域模型的關聯 一、找出關聯 關聯,是類(事實上是執行個體)訓示有意義或相關連接配接的一種關系。 關聯事實上表示是一種“知道”。 如果不寫箭頭,關聯的方向一般是“從上到下,從左到右”。 我們可以使用下面的表來找出關聯
分類 | 示例 |
A在實體上是B的一部分 | (略) |
A在邏輯上是B的一部分 | |
A在實體上包含在B中/依賴于B | |
A在邏輯上包含在B中 | |
A是對B的描述 | |
A是交易或者報表B中的一項 | |
A為B所知道/為B所記錄/為B所撲獲 | |
A是B的一個成員 | |
A是B的一個組織子單元 | |
A使用或者管理B | |
A與B通信 | |
A與一個交易B有關 | |
A是一個與另一個B有關的事物 | |
A與B相鄰 | |
A為B所擁有 | |
A是一個與B有關的事件 |
二、關聯的指導原則 l 把注意力集中在那些需要把概念之間的關系資訊保持一段時間的關聯(“需要知道”型關聯)。 l 太多的關聯不但不能有效的表示領域模型,分而會使領域模型變的混亂,有的時候發現某些關聯很費時間,但帶來的好處并不大。 l 避免顯示備援或者導出的關聯。 三、角色和多重性 關聯的每一端稱之為“角色”。 角色可選的具有: 名稱; 多重性表達式; 導航性。 多重性 多重性表示一個執行個體,在一個特定的時刻,而不是一段時間内,可以和多個執行個體發生關聯。 “*”表示多個。 “1”表示一個。 “0..1”表示1或者沒有,比如一個商品在貨架上,可能售出,也可能被丢掉了,這種情況,用“0..1”是合理的。問題是我們需要關心這樣的觀點嗎?如果是資料庫,可能表達這個資料存在,或者損壞。但在領域模型并不表示軟體對象,通常我們隻對我們有興趣的内容模組化,從這個觀點出發,也可能隻有“1”或者“*”是合理的。 再一次提醒,發現領域類比發現關聯更重要,花費在領域模型建立的大部分時間,應該被用于發現領域類,而不是關聯。 四、兩種類型之間的多重關聯 兩種類型之間的多重關聯是可能存在的。 比如航空公司的例子,Flight-to和Flight-from可能會同時存在,應該把它們都标出來。 第三節 領域模型的屬性 發現和識别領域類的屬性,是很有意義的。 屬性是個邏輯對象的值。 屬性主要用于保留對象的狀态。 一、有效的屬性類型 大部分屬性應該是簡單資料類型。 當然也可以使其它的一些必要的類型,比如:Color(顔色)、Address(位址)、PhoneNumber(電話号碼)等。 二、非原始的資料類型類 在領域類中,可以把原始資料類型改成非原始資料類型,請應用下面的指導原則: l 由分開的段組成資料(電話号碼,人名) l 有些操作和它的資料有關,如分析和驗證等(社會安全号碼) l 包含其它屬性的資料(促銷價格的開始和結束時間) l 帶有機關的資料值(支付金額有一個貨币機關) l 對帶有上述性質的一個或多個抽象(商品條目辨別符) 如果屬性是一個資料類型,應該顯示在屬性框裡面。 第四節 泛化模組化 泛化和特化是概念模組化的基本概念,另外,領域類的層次,往往是軟體類層次的基本源泉,軟體類可以利用繼承來減少代碼的重複。 一、領域模型的概念提取 UP的領域模型,是在不斷考慮疊代需求的相關概念的過程中發展起來的。 很多人對概念模組化都有一些細膩的模組化問題的讨論。比如,有一個有一定作用的概念,就是概念分類表(Concept Category List)。 1 )概念分類表 本次疊代所涉及的一些顯著概念,可以列出一個表來。
類别 | 示例 |
實體或者實際的對象 | CreditCard(信用卡),Check(支票) |
事物的說明、設計或描述 | |
位置 | |
交易 | CashPayment(現金支付) CreditPayment(信用卡支付) Check Payment(支票支付) |
交易的項目 | |
人的角色 | |
其它事物的容器 | |
容器中的事物 | |
系統之外其它計算機或電子機械系統 | CreditAuthorizationService(信用卡支付授權服務) CheckAuthorizationService(支票支付授權服務) |
抽象名詞概念 | |
組織 | CreditAuthorizationService(信用卡支付授權服務) CheckAuthorizationService(支票支付授權服務) |
事件 | |
規則及政策 | |
目錄 | |
财務、工作、合約、法律事務的記錄 | AccountsReceivable賬目接受 |
金融工作和服務 | |
手冊、書籍 |
2 )從用例中得到名詞對照的概念 再次重申,不能機械的用名詞與概念的對照來識别領域模型的有關概念。由于自然語言的模棱兩可,文本中的相關概念并不總是明确和清晰的,是以我們必須判斷并作合适的抽象處理。不過,由于名詞和概念對照的直覺性,它仍然是概念模組化的一個實用技術。 每一次疊代,實際上都要反過來研究用例并進行需求分析,利用需求驅動項目進一步精化。在這次疊代中,我們将處理銷售過程(Process Sale)用例的信用卡和支票的支付場景,下面顯示擴充場景中一些名詞對照的概念。
用例1 :Process Sale |
…… 擴充: 7b. 信用卡支付 1. 顧客輸入 信用卡賬号資訊。 2. 系統向外部 信用卡支付授權服務系統發出 授權支付請求和 準許支付的請求 2a. 系統檢測到和外部信用卡授權服務系統通信故障 1.系統通知收銀員發生了錯誤 2.收銀員向客戶請求更換支付方式 3. 系統收到 支付準許并通知收銀員 3a. 系統收到 支付拒絕的通知 1.系統通知收銀員系統拒絕支付 2.收銀員要求顧客改變支付方式 4.系統記錄 信用卡的支付情況,包括支付授權 5.系統出示信用卡簽名的輸入方式 6.收銀員要求顧客為信用卡支付簽名,顧客簽名 7c. 用支票支付 1. 顧客簽發 支票,将 支票和 駕駛執照一起交收銀員 2. 收銀員把駕駛執照号碼記錄在支票上,将其輸入,發出 支票支付授權請求。 3. 生成一個 支票支付請求,将其發送到外部的 支票授權系統。 4. 系統收到支票支付授權并通知收銀員。 5. 系統記錄 支票的支付情況,其中包括 支付準許。 ………… |
其中,粗體的就是我們發現的概念名詞。 3 )授權服務的交易 由名詞對照,我們還可以發掘出諸如CreditPaymentRequest(信用卡付款請求)以及 CreditApprovalReply(信用卡準許應答)這樣一類概念,這些概念都可以視為外部服務的不同類型的交易。 一般來說,識别這些交易非常有用,因為許多活動和處理都是圍繞交易而進行的。 這些交易概念,不需要代表計算機中的記錄,也不需要代表連線上的比特資料,它們代表了獨立于執行方式的交易的抽象。 比如,信用卡支付方式可以通過打電話或者計算機送出請求來完成。 二、泛化及其應用 CashPayment(現金支付)、CreditPayment(信用卡支付)和Check Payment(支票支付)這幾個概念非常接近,可以組織成一個泛化的類層次,其中超類Payment(支付)具有更普遍的概念,而子類是一個更具體的概念。 注意,這裡讨論的是領域類,而不是軟體類。 泛化(generalization)是在多個概念之間識别共性,定義超類和子類關系的活動,它是構件概念分類的一種方式,并且在類的層次中得到說明。 在領域模型中,識别超類和子類及其有價值,因為通過它們,我們就可以用更普遍、更細化和更抽象的方式來了解概念。進而使概念的表達簡約,減少概念資訊的重複。 三、定義概念性超類和子類 由于識别概念性的超類和子類具有價值,是以根據類定義和類集,準确的了解泛化、超類、子類是很有意義的,下面我們将讨論這些概念。 1 )泛化和概念性類的定義 定義: 一個概念性超類的定義,比一個概念性子類的定義更為普遍或者範圍更廣。 在前面的例子中,Payment(支付),是一個比具體的支付方法更為普遍的定義。 2 )泛化與類集 概念性子類與概念性超類,在集的關系上是相關的。 所有概念性子類集的成員,都是它們超類集的成員。 3 )概念性子類定義的一緻性 一旦建立了類的層次,有關超類的聲明也将适用于子類。 一般的說,子類和超類一緻是一個“100%規則”,這種一緻包括“屬性”和“關聯”。 4 )概念性子類集的一緻性 一個概念性子類應該是超類集中的一個成員。 通俗的講,概念性子類是超類的一種類型(is a kind of),這種表達也可以簡稱為is-a。 這種一緻性稱之為Is-a規則。 是以,這樣的陳述是可以的: “信用卡支付是一個支付”(CreditPayment is a Payment)。 5 )什麼是正确的概念性子類呢 從上面的讨論,我們可以使用下面的測試,來定義一個正确的子類: l 100%規則(定義的一緻性) l is-a規則(集合成員關系的一緻性) 6 )何時定義一個概念性子類 舉個例子,把顧客(Customer)劃分為男顧客(MaleCustomer)和女顧客(FemaleCustomer),從正确性來說是可以的,但這樣劃分有意義嗎? 這樣劃分是沒有意義的,是以我們必須讨論動機問題。 把一個領域類劃分為不同子類的強烈動機為: 當滿足如下條件之一的時候,為超類建立一個概念性的子類: l 子類具有額外的相關屬性。 l 子類具有額外的相關關聯。 l 子類在運作、處理、反應或者操作等相關方式上,與超類或者其它子類不同。 l 子類代表一個活動的事務(例如:動物、機器人),它們與超類的其它子類在相關的行為方式上也不同。 由此看來,把顧客(Customer)劃分為男顧客(MaleCustomer)和女顧客(FemaleCustomer)是不恰當的,因為它們沒有額外的屬性和關聯,在運作(服務)方式上也沒什麼不同。 盡管男人和女人的購物習慣不同,但對目前的用例來說不相關。這就是說,規則必須和我們研究的問題相結合。 7 )何時定義一個概念性超類 在多個潛在的子類之間,一旦發現共同特征,就可以暗示可以泛化得到一個超類。 下面是泛化和定義超類的動機: l 潛在的概念子類代表一個相似概念的變體。 l 子類遵守100%的is-a規則。 l 所有的子類具有共同的屬性,可以提取出來并在超類中表示。 l 所有子類具有相同關聯,可以提取并與超類相關。 8 )發現領域類的執行個體 Payment類: 授權服務類: 注意,在構造超類的時候,層次不宜太多,關鍵是表達清晰。 事實上,額外的泛化不會增加明顯的價值,相反帶來很大的負面影響,沒有帶來好處的複雜性是不可取的。 四、抽象領域類 在領域模型裡面,識别抽象類是有用的,因為它們限制了哪些類可能具有具體的執行個體。 如果一個類的成員,必須是它子類的成員,那麼稱它為抽象領域類。 在上面的例子裡,Payment必須用更具體的CreditPayment、CheckPayment做執行個體,而Payment本身并不能執行個體化,是以Payment是一個抽象的領域類。 第五節 精化領域模組化及若幹難以确定的要素 在前面讨論的基礎上,我們需要把領域模型進一步的精化。 一、關聯類 下面的概念需求,需要考慮關聯類的問題: l 在通訊過程中,授權服務為每個商店配置設定一個店主ID。 l 從商店發送到授權服務的支付請求,需要店主的ID以辨別這個商店。 l 進一步,對每一個授權服務,每一個商店都有一個不同的店主ID。 在UP的概念模組化中,商店的ID的屬性到地方在什麼地方呢? 把merchantID(店主ID)置于Store(商店)類中是不正确的,因為一個Store類會有多個merchantID值。 注意,屬性表示了對象的狀态,是以,一個對象的屬性,同時隻能有一個值。 把merchantID置于AuthorizationService(授權服務)類中也是不恰當的,因為它同樣也有多個值。 通過上面的讨論,我們就可以得出下面的模組化原則: 在概念模組化中,如果一個類C的屬性A 同時具有多個值,那麼不要把屬性A放到類C中,而是把屬性A 放到與C關聯的關聯類裡面去。 出現下面的情況可以在領域模型中加入關聯類: l 一個屬性和關聯有關。 l 關聯類的生命周期依賴于關聯。 l 在兩個概念之間存在多對多的關聯或者關聯本身具有某些待表示的資訊。 下面的例子,表達一個人可能受雇于多個公司。 二、聚叢集組合 聚集(Aggregation)是用于整體—部分關系模組化的一種關聯,整體稱之為 組合(composite)。 1 )組合聚集 組和聚集用實心菱形表達,原來的意義,它表達部分的存在依賴于組合。 比如:一隻手和手指,手指的存在依賴于手。 在設計模型中,組合的含義很清楚,它表達某一個對象的生命周期,依賴于另一個對象(全局性的定義,并且在構造的同時執行個體化)。 但是在領域模型中,這種整體的建立對部分的影響并不太清楚(一個實際的銷售并不可能建立實際的銷售商品),是以,花功夫發現這種關系并沒有什麼實際意義。 2 )共享聚集 共享聚集的圖是空心菱形,它表示組合末端(菱形處)的多重性可能大于一。 它的含義是,部分可能同時屬于多個組合執行個體。 在設計模型中,這種共享聚集和關聯有幾乎相同的實作方法(全局性的定義,但對象構造的時機待定)。 但是,在實際的實體集合中,很少能找到相似的例子。 注意,發現和使用聚集在設計模型中相當有意義,但與設計模型不同,在領域模型中識别和說明聚集并不會産生深遠影響。 學院派的模組化理論花了很多時間來讨論這些關聯上的細膩差别,但是,很多經驗豐富的模組化者最終發現,它們在關聯的細微含義上浪費了太多的無謂的時間。 是以,在領域模型的關聯問題上,我們将排除這種表示方式。 三、 案例:訂單處理子系統 我們還是以網上電源裝置銷售子系統的案例,來讨論領域模組化的過程。 領域模組化的目的,是用類來表達一個對象集,如果這個類是長久存在的(或者說是持久的)一個業務實體,比如,Customer、Order、Shipment等等,這樣的類通常被稱為 實體類。實體類往往代表着一個資料庫的一個持久化對象,是以,這裡的領域實體模型的建立,直接影響到資料庫設計。 實體類定義了任何資訊系統的本質,是以需求分析上很大程度上是發現實體對象。不過,從功能上來說,發現其它的功能類也是必要的。 有時候這樣類的模組化一直需要延續到設計階段。 1 )從需求中尋找類 下面我們從功能需求的表中找到這個類。
編号 | 需求 | 實體類 |
1 | 客戶使用制造商的Web頁面檢視所選擇的 電源裝置标配,同時顯示價格。 | Customer 客戶 ES: StandardConfiguration 标準配置 Product 産品 |
2 | 客戶檢視配置細節,可以更改配置,同時計算價格。 | Customer 客戶 ConfiguredES: ConfiguredProduct 配置的電源:配置的産品 ConfigurationItem 配置項目 |
3 | 客戶選擇訂購,也可以要求 銷售人員在 訂單真正發出之前和自己聯系,解釋有關細節。 | Customer 客戶 ConfiguredES 配置的電源 Order 訂單 Salesperson 銷售人員 |
4 | 要發出訂單, 客戶必須填寫表格,包括位址,付款細節(信用卡還是支票)等。 | Customer 客戶 Order 訂單 Salesperson 銷售人員 Shipment 出貨 Invoice 發票 Payment 付款 |
5 | 客戶訂單送到系統之後, 銷售人員發送電子請求到 倉庫,并且附上配置細節。 | Customer 客戶 Order 訂單 Salesperson 銷售人員 ConfiguredES 配置的電源 ConfigurationItem 配置項目 |
6 | 事務的細節(包括訂單号和客戶帳戶号), 銷售人員要e-mail給客戶,使得 客戶可以線上查詢訂單狀态。 | Customer 客戶 Order 訂單 OrderStatus 訂購狀況 |
7 | 倉庫從 銷售人員處擷取發票,并且向客戶運送電源裝置 | Invoice 發票 Shipment 出貨 |
尋找領域類是一個疊代式的任務,需要反複思索,也可以試着回答下面的問題: 這個概念是一個資料容器嗎? 它有取不同值的不同屬性嗎? 它已經有實體對象了嗎? 它在應用領域的範圍之内嗎? 針對這張表我們還可以思考很多問題,比如: 1,ConfiguredES(自己選擇配置的電源)和Orde(訂單)的差別到底在哪裡?畢竟我們不打算存儲選擇配置的電源,除非它的訂單被送出。 2,第4号和第7号需求中的Shipment(出貨)的含義是一樣的嗎?可能不一樣,如果我們知道了運送是倉庫的責任,這個類是不是還需要呢? 3,ConfigurationItem (配置項目)為什麼不能是ConfiguredES中的一組屬性呢? 4,OrderStatus(訂購狀況)為什麼不能是Order(訂單)的一個屬性呢? 5,Salesperson(銷售人員)是一個類,還是Order(訂單)還是Invoice(發票)中的一個屬性呢? 回答這些問題是不容易的,這需要對需求進行深入的研究,假定我們研究的結果出現了下面這些類(其中Customer實際上是用例中的參與者,是以是從用例的角度出現的)。 2 )确定屬性 我們可以進一步定義一些屬性,這些屬性首先被想到的是原始類型的屬性,其實定義屬性确實是有很大的随意性的,這需要一些經驗。 3 )發現關聯 我們可以根據需求的了解,來發現一些關聯。 但是在确定多重性的時候,可以作一些假定: 訂單來自于單個客戶,而客戶可以送出多個訂單。 訂單除非在付款已經被說明之後才被接受,因而是一對一關聯。 訂單不一定要有一個所關聯的發票,但發票總是和單個訂單所聯系。 一個訂單是為一個或者多個自配置電源建立的,一個自配置電源可以被訂購多次或者一次也沒有。 這樣就可以畫出關聯來。 4 )發現聚集 聚集是關聯更強的形式出現的,不過事實上并不一定需要刻意的發現聚集,這裡用聚集表達主要是為了強調這種關聯的重要。 一個電源具備一個或者多個配置項目。 同樣,一個自定義配置的電源也具有一個或者多個配置項目。 5 )泛化模組化 面向對象的分析很重視泛化模組化,這樣一來可以大大簡化和清晰化所建立的模型。 在這裡,電源(ES)變成了一個更抽象的類,兩個子類為“标準配置電源”和“自定義配置的電源”。 6 )包括屬性的最後結果 第六節 系統行為分析中必須關注的問題 對一個軟體應用程式進行邏輯設計之前,對系統進行研究,并把它的行為當作“黑箱”來考慮是有益的。 系統行為描述一個系統做什麼,而不解釋系統如何做。描述系統行為一部分是靠順序圖,另外一部分是靠用例和系統契約(以後會加以讨論)。 互動視圖包括順序圖(Sequence Diagram)和合作圖(Collaboration Diagram)和兩種,主要解決描述對象之間的互動問題。 對象間的互相作用展現了對象的行為。 這種互相作用可以描述成兩種互補的方式: 1)以獨立的對象為中心進行考察; 2)以互相作用的一組對象為中心進行考察。 狀态圖的描述範圍不寬,但它描述了對象深層次的行為,是單獨考察每一個對象的“微縮”視圖。 對狀态圖的說明是精确的并且可直接用于代碼。 然而,在了解系統的整個功能時存在困難,因為狀态圖一個時刻隻集中描述一個對象,要确定整個系統的行為必需同時結合多個狀态圖進行考察。 互動視圖更适合于描述一組對象的整體行為。 互動視圖是對象間協作關系的模型。 協作: 協作描述了在一定的語境中一組對象以及用以實作某些行為的這些對象間的互相作用。 它描述了為實作某種目的而互相合作的“對象社會”。 互動: 互動是協作中的一個消息集合,這些消息被類元角色通過關聯角色交換。當協作在運作時,受類元角色限制的對象通過受關聯角色限制的連接配接交換消息執行個體。互動作用可對操作的執行、用例或其他行為實體模組化。 消息是兩個對象之間的單路通信,從發送者到接收者的控制資訊流。消息具有用于在對象間傳值的參數。消息可以是信号(一種明确的、命名的、對象間的異步通信)或調用(具有傳回控制機制的操作的同步調用)。 建立一個新的對象在模型中被表達成一個事件,這個事件由建立對象所引起并由對象所在的類本身所接受。 建立事件:作為從頂層初始狀态出發的轉換的目前事件。對于新執行個體是可行的。 消息可以被組織成順序的控制線程。分離的線程代表并發的幾個消息集合。線程間的同步通過不同線程間消息的限制模組化。同步結構能夠對分叉控制、結合控制和分支控制模組化。 消息序列可以用兩種圖來表示:順序圖(突出消息的時間順序)和協作圖(突出交換消息的對象間的關系)。 一、從整體的角度研究系統行為 用例描述外部參與者與我們建立的軟體之間如何互動。 互動期間,參與者産生一個發送給系統的事件,通常要求系統響應這個操作。 比如: 收銀員輸入一個商品的ID的時候,收銀員将請求POS系統記錄商品的銷售,這個請求将觸發一個系統的操作。 為了表達這些外部參與者與系統互動的過程,使用UML順序圖是可取的。 一個系統順序圖(SSD),是一個用來表示用例特定場景、外部參與者産生的事件。所有的系統都被當作黑箱,圖的重點是從參與者跨越到邊界的事件。 系統順序圖是把系統作為黑箱來設計。 順序圖将互動關系表示為一個二維圖。縱向是時間軸,時間沿豎線向下延伸。橫向軸代表了在協作中各獨立對象的類元角色。類元角色用生命線表示。當對象存在時,角色用一條虛線表示,當對象的過程處于激活狀态時,生命線是一個雙道線。 消息用從一個對象的生命線到另一個對象生命線的箭頭表示。箭頭以時間順序在圖中從上到下排列。 後面會讨論順序圖也可以說明互動軟體對象的設計問題。 1 )一個SSD 示例 下面的例子是用SSD顯示參與者與系統(作為黑箱)直接的互動,參與者所産生的事件。 2 )SSD 和用例 SSD顯示用例的一個場景中的系統事件,是以它産生自用例的考察。你可以直接把它和用例中的步驟對應起來。 3 )系統事件和系統邊界 為了識别系統事件,必須象前面用例的讨論一樣,清楚的定義系統的邊界,由于軟體開發的目的,系統邊界經常被定義為軟體本身,在這樣的語境下,系統事件是直接激活軟體的外部系統事件。 在上面處理銷售的例子中,由于顧客并沒有直接參與POS系統的互動,是以顧客不是系統事件的參與者,隻有收銀員才是。 4 )命名系統事件及操作 因為名稱強調事件的指令導向,是以事件以動詞開頭(add、enter、end、make)可以增加清晰度。 比如: enterItem(加入項目)比scan(雷射掃描器)要好。 5 )顯示用例文本 事實上,這個順序圖是為了更清晰的表達問題,特别是為了更好的和使用者交流,是以,很多情況下,希望能在順序圖中顯示場景的用例片斷,比如: 6 )SSD 和術語表 SSD中顯示的術語(操作、參數、傳回值)是簡練的,有的時候可能需要适當的解釋,就應該在術語表中表達。 不過,如果讨論是工件的建立而不是編碼,又沒有必要建立享用的術語比哦澳是個令人懷疑的事情,除非用途和決策支援标明這真正有價值,就是一個不必要的工作。 二、統一過程中的SSD SSD使用例模型中的一部分(用例中互動的可視化),但是在UP 中并不認為一定要用SSD來描述。 不過,有的時候花個幾分鐘或半個小時建立SSD也不是完全沒有用處。 一般的情況是: 初始: 在初始階段一般不會使用SSD。 細化: 在細化階段,大多數SSD可以被建立出來,用來識别系統事件的細節,以及澄清哪些是系統必須設計來處理的主要操作。 注意: 沒有必要為所有場景建立SSD,一般隻是為目前疊代所選擇的場景建立SSD。 三、分析對象之間的行為 當需要更加細膩的分析的時候,可以用更詳細的順序圖來分析。下圖為帶有異步消息的典型的順序圖,這是一個服務網點的存款服務的用例。 激活: 激活是過程的執行,包括它等待嵌套過程執行的時間。在順序圖中它用部分替換生命線的雙道線表示。 當控制流程重新進入對象中的一個操作遞歸時,遞歸調用發生,但是第二個調用是與第一個調用分離的激活。同一個對象中的遞歸或嵌套調用用激活框的疊加表示。 下圖為含有過程控制流的一個順序圖,包括一個遞歸調用和一個對象的建立。 帶有激活的順序圖 四、案例: 訂單處理子系統 互動圖很多情況下是對于活動圖的深入研究建構起來的,比如對于已經讨論的裝置購置案例,我們仔細的研究活動圖,對“顯示目前配置”的活動作更加細膩的研究。 它牽涉到三個類: ConfigurationWindow,這是一個界面類; ES類,這是ConfiguredES類或者StandardES類。 ConfigurationItem類,這是一個配置項目類。 需要表達的互動操作關系如下: 外部參與者Customer先選擇電源的配置,然後消息openNew()發送給一個界面類ConfigurationWindow,這個消息導緻建立一個執行個體aConfWin。 對象aConfWin需要“顯示它自己”以及配置資料,為了這個目的,它發送一個消息getConf()給ConfiguredES類或者StandardES類,并且執行個體化一個對象aComp。 對象aComp使用輸出參數item_rec根據ConfigurationItem對象“組合它自己”,然後批量發送配置項到aConfWin。消息displayES的參數為item_recset。 現在對象aConfWin能顯示自己了,對應的互動圖如下。 對這樣的序列圖的研究,可以為相應的類提供方法打下基礎,比如受影響的三個類可以構造相應的方法。 一般來說,可以為每個用例構造一個單獨的序列圖,這種對象之間互相關系的研究,為好的模組化提供了重要的基礎。 下面,我們再為“訂購配置了的電源裝置”這個用例,創造序列圖,這個序列圖表達了跨越幾個用例的行為。 描述: 在開始兩個消息的作用,我們在上面的序列圖已經說明過了。 消息acceptConf産生發送給:Order對象的prepareForOrder消息,這就建立了一個Order對象,它在:OrderWindow中顯示。 針對客戶對預定細節的接受情況(submitOrder),:OrderWindow觸發(storeOrede)一個永久的:Order對象的建立,然後,這個:Order對象把它自己連結到所預定的:ES和相關的:Customer和:Payment對象上,一旦這個對象被永久地連結起來,這個:Order對象就發送emailOrder消息給外部參與者:Customer。 注意,:Customer機作為外部參與者對象又作為内部類對象的雙重用法,這在模組化中是經常出現的沖突,客戶對系統來說既是外部的又是内部的,作為外部的,它與系統互動,作為内部的,客戶資訊又必須保持在系統裡面,以識别一個外部客戶是否是系統已經知道的一個合法内部實體。 參照前面的活動圖,可以畫出序列圖。這個序列圖分成兩部分,Order和OrderWindow的生命線在這兩部分中被重複使用。 這裡隻顯示消息的激活,消息的傳回是隐式的,同時也不需要指出參數。 五、用操作契約 (Contract ) 增加用例細節 操作契約可以幫助定義系統行為,它是用概念對象的狀态改變,來描述系統操作執行的結果。有的時候更詳細的系統行為描述也是有價值的。 在執行一個系統操作以後,契約根據概念模型中對象的狀态變化來描述詳細的系統行為。 契約是為系統操作(system operation)而制定的,這種操作,是作為“黑箱”的系統,再它的公共接口中提供的。 貫穿所有用例的全體系統操作,定義了公共的接口。 而系統,作為一個整體,可以用一個類來表示。 我們看下面的例子:
契約2 :enterItem | |
操作 | enterItem(iyemID:itemID,quantity:integer) |
交叉引用 | 用例:Process Sale |
前置條件 | 有一個銷售正在進行 |
後置條件 | 1 ,建立一個SalesLineItem執行個體sli(建立執行個體) 2 ,sli和目前的Sale形成關聯(關聯形成) 3 ,sli.quantity變成quantity(屬性修改) 4 ,在itemID比對的基礎上,sli和ProductSpeciyfication 形成關聯(關聯形成) |
1 、契約條目的描述
契約名:操作名 | |
操作 | 操作以及參數的名稱 |
交叉引用 | [ 可選]可能發生這個操作的用例 |
前置條件 | 在操作執行以前,概念模型中系統或者對象狀态的值得注意的假 設,它們在此操作的邏輯内不會得到測試,而被假設為真。另外, 他們并非無關緊要,而是要讓閱讀者了解有這個假設存在。 |
後置條件 | 操作完成以後,概念模型的狀态,後面就會詳細讨論。 |
2 、後置條件 注意,在前面的例子中,每個後置條件都包含一個分類,比如“執行個體建立”(instance creation)或者“關聯形成”(association formed),這是一個關鍵點。 後置條件描述概念模型中對象狀态的變化,概念模型對象狀态的變化包括:執行個體建立或删除、關聯形成或斷開、屬性改變。 後置條件不是系統操作中要執行的動作,而是系統操作完成以後,為“真”的關于概念模型的聲明。 關于關聯斷開:可以這樣描述,“標明的SaleLineItem和Sale之間的關聯就斷開了”,還有“當償還了貸款後,關聯就斷開了”等。 執行個體删除非常少見,這是人們一般不太關心強制的銷毀一個事務。 後置條件一個特點是,它是聲明性的,它描述的是狀态變化,而不是一個動作的執行過程。 1 )分析細節 契約以聲明狀态變化的方式來表達問題,使它成為一個優秀的需求分析工具,在不需要說明操作如何實作的情況下,描述系統操作如何引起系統狀态的變化。後置條件可以分析細粒度的資訊,并指明系統的狀态是什麼。 這樣就可以很好的分析我們所關心的一些細節問題。 2 )後置條件應該達到怎麼樣的詳細程度 人們往往關心後置條件要書寫到怎樣的詳細程度。 事實上,并不一定需要契約。 但假設需要一些契約,但産生完整、詳細的後置條件是不可能也是不必要的。 這就是系統架構師的能力問題,如何抓住重點。 不過,在設計工作階段,我們會發現一些細微的細節,這不見得是壞事,這些發現可以通知後面的疊代需求工作,這正是疊代開發的優點,一個近期的疊代,可以豐富後一個疊代的調研和分析工作。 經常在建立契約的時候發現,需要記錄概念模型中出現的新的概念類、屬性或者關聯,我們不要受限于先前已經定義的概念模型,在思考操作契約并且有新的發現的時候,可以進一步豐富概念模型。 3 、書寫契約的指導原則 要建立契約的時候,必須: 1) SSD識别系統操作 2)對于那些複雜的,結果微妙的以及在用例中不清晰的系統操作,可以構造一個契約。 3)要描述後置條件: l 執行個體的建立和删除 l 屬性修改 l 關聯形成和斷開 一些建議: l 後置條件的陳述應該采用過去時态的聲明語氣(was…),以強調系統狀态的變化,而不是強調這種變化是如何設計實作的,比如: (較好)A SalesLineItem was created (較差)Create a SalesLineItem l 不要忘記在新建立的對象和已經存在的對象之間保持記憶關系。這個記憶關系就是兩個對象之間的關聯關系。例如,當enterItem操作發生的時候,會建立一個新的SalesLineItem執行個體,這還不夠,當操作完成之後,在新建立的執行個體和Sale之間,還應該建立一個關聯關系,即: SalesLineItem和目前的Sales建立關聯(關聯形成) 注意: 最常見的錯誤,就是遺漏了關聯的形式,特别是在建立了新的執行個體以後,往往需要和多個對象之間建立關聯,千萬别忘了! 六、用協作圖分析複雜操作 雖然用順序圖可以很好的表達操作和行為,而且時間關系也很清楚,但是,當關系非常複雜的時候,往往圖就很複雜,這樣反而不利于看清問題,是以,某些情況下使用協作圖将會使表達更清楚。 協作圖隻對互相間具有互動作用的對象和對象間的關聯模組化,而忽略了其他對象和關聯。注意,我們并不需要對系統所有的部分繪制協作圖,而隻是對最主要最複雜的部分做這樣的讨論。 1 、消息 消息可以用依附于連結的帶标記的箭頭表示。每個消息包括一個順序号、一張可選的前任消息的表、一個可選的監護條件、一個名字和參量表、可選的傳回值表。 2 、流 通常,在完整的操作中協作圖包含對象的符号。然而,有時對象具有不同的狀态并且必須明确表達出來。 例如,一個對象可以改變位置,或者在不同的時刻它的關聯有很大差別。對象可以用它的類與它所處的狀态表示,這就是具有狀态類的對象。同一個對象可以表示多次,每次有不同的位置和狀态。 代表同一對象的不同對象符号可以用變成流聯系起來。 變成流是從一個對象狀态到另一個的轉換。它用帶有構造型《 become 》的箭頭表示,并且可以用順序号标記表示它何時出現(如下圖所示)。 協作圖和順序圖都表示出了對象間的互動作用,但是它們側重點不同。順序圖清楚地表示了互動作用中的時間順序,但沒有明确表示對象間的關系。協作圖清楚地表示了對象間的關系,但時間順序必須從順序号獲得。順序圖常常用于表示方案,而協作圖用于過程的詳細設計。 下圖為一個協作圖。 可以将對象辨別成四個組: 存在于整個互動作用中的對象; 互動作用中建立的對象(使用限制 {new} ); 在互動作用中銷毀的對象(使用限制 {destroyed} ); 在互動作用中建立并銷毀的對象(使用限制 {transient} )。 設計時可以首先表示操作開始時可得的對象和連接配接,然後決定控制如何流向圖中正确的對象去實作操作。 雖然協作直接表現了操作的實作,它們也可以表示整個類的實作。在這種使用中,它表示了用來實作類的所有操作的語境。這這使得對象在不同的操作中可以擔當多種角色。這種視圖可以通過描述對象所有操作的協作的聯合來構造。 七、狀态圖及其讨論 狀态圖可以表達一個對象的狀态變遷,事實上,在分析的時候,常常并不總是需要這種狀态變遷的讨論,但是,有時候在最重要的類上進行這種讨論,也是有意義的,因為這可以為我們下一步系統設計打下了基礎,我們來看下面的案例。 案例:訂單處理子系統 考慮Invoice對象的狀态, 有兩種支付方式,初始狀态是未付款,形成發票有兩種可能的狀态變遷,可以用下面的狀态圖表達。 另一方面,我們可以給Order對象畫出狀态圖,一個新訂單可能有兩種狀态變遷,可以看出來,這對細膩的描述訂單的狀态變遷是很有意義的。 第七節 疊代計劃和風險管理 我們現在再把注意力回到疊代開發上來,疊代計劃和項目管理是一個大問題,但為了能夠實用,我們必須把問題簡化,讨論一些關鍵問題。 所有的問題都集中在: l 在下一個疊代中該做什麼? l 如何在疊代開發中跟蹤需求? l 如何組織項目工作? 一、區分需求的等級 1 )早期疊代的驅動因素: 風險、覆寫範圍、重要性和技能發展。 在最早的疊代中,要根據風險、覆寫範圍、重要性來組織疊代。 需求風險包括技術複雜度和其它因素,如工作方向的不确定性、拙劣的規範說明,行政問題或者可用性。 覆寫範圍: 早期疊代至少要涉及系統的所有主要部分,可能還要充分或粗略的實作許多元件。 重要性: 具有很高業務價值的的功能,即使沒有技術風險,在早期疊代中至少部分實作中要場景所需的主要功能。 有些工程的另一個驅動因素是技能教育訓練,即幫組開發人員掌握新技術,在這些工程中,技能教育訓練是高優先級的驅動因素。 2 )如何進行等級劃分 UP是用例驅動的,是以具體實施是對用例進行等級劃分。 另外,有些需求被描述為和特定用例無關的高優先級特性,它可能會跨越幾個用例。這時需要描述在用例的補充規範中。 是以,優先級清單要包括用例和高層特征兩個部分。
優先級清單 | ||
需求 | 類型 | 優先級 |
Process | 用例 | 1 |
Logging | 特征 | 2 |
…… | …… | …… |
3 )優先級劃分的小組定位法 優先級可以是定性的,可以采取小組定位法。 可以在小組會上投票,事實上每次做疊代計劃的時候都可以進行這種投票活動。 4 )優先級劃分的定量法 需求和風險優先等級的劃分,可能小組計點投票就已經足夠了,不過這是模糊的定性方法,如果需要進行更定量的思考,需要進行以權重為基礎的分類。
架構權重分析表 | |||||
需求 | 類型 | AS | 風險 | 重要性 | 權重和 |
Process Sale | UC | 3 | 2 | 3 | 15 |
Logging | Feat | 3 | 1 | 7 | |
Handle Returns | UC | 1 | 2 | ||
…… | …… | …… | …… | ||
說明 | 名稱 權值 範圍 AS:架構上的重要性 2 0 - 3 風險:技術、複雜、創新 3 0 - 3 重要性:早期較高的業務價值 1 0 - 3 |
二、劃分項目風險等級 劃分全部項目風險等級的一個有效的方法,就是從成本、時間或者工時上估計它的發生頻率和影響力。這種評估可以是定量的(通常需要深入的思考),也可以是簡化定性的(小組讨論、投票,簡單的分成:高、中、低三級)。 最糟糕的風險,是那些很可能發生又影響很大的風險,例如:
風險 | 可能性 | 影響程度 | 緩解方法 |
缺乏熟練的面向對象開發人員 | 高 | 高 | l 閱讀書籍 l 雇用臨時的咨詢顧問 l 課堂教學或者教育訓練輔導 l 兩人一組程式設計 |
示範程式不滿足即将産生的Hamburg的POS規範 | 中 | 高 | l 雇傭擁有POS系統開發經驗的臨時顧問。 l 識别示範程式中已經實作的最嚴重的需求,并安排較高的優先級。 l 最大限度的利用以完成的元件。 |
三、在疊代之間跟蹤需求 我們已經很清楚,疊代開發中并非所有的場景都在第一次疊代中實作,一個複雜的場景,往往要花6個月采用多次為期兩周的疊代來完成。每次疊代都處理新的場景或者場景的某些部分。在這樣的情況下,必然出現了一個需求跟蹤的問題,人們如何記錄用例的哪些部分已經完成,哪些部分正在進行中,哪些部分還沒有涉及呢? 這就需要用到需求工具。 Rational的RequisitePro是一個需求跟蹤工具,值得我們花時間掌握它來跟蹤在疊代之間已部分完成的用例。 我們可以把RequisitePro和Microsoft word整合到一起,用word編輯需求,在RequisitePro中選擇短語,并把它定義成被跟蹤的需求。每個需求都有多種屬性,如狀态、風險等,RequisitePro工具可以使我們可以在疊代之間跟蹤用例的部分完成情況。這個工具的使用很簡單也很有效。 第八節 領域模組化的執行個體分析 一、如何通過領域模型來發現出類及其關系 模組化 執行個體一:我們使用一個猜數遊戲來說明如何建立領域模型問題:輸入一個數,如果猜中了顯示“你猜中了啊”然後程式結束,如果猜的不對,系統則告訴你的數是太大還是太小,然後要求你重新輸入新的數,直到猜中為止。 (1 )開始歸納問題-----其實是描述出用例的事件流 +-----------------------------------------------------------------+ | 系統應該準備一個正确答案 | | 玩家可以輸入一個答案 | | 系統應該比較玩家輸入的答案和正确答案 | | 系統應該顯示玩家每次輸入的結果 | +-----------------------------------------------------------------+ 在歸納問題時,要注意把握下面的幾個 基本要點 l 第一是不要涉及内部的流程,别出現“如果輸入不正确,就怎麼怎麼樣”的句子,這些并不是正确的問題,正确的問題必須是明确的,清晰的,如果可能的話全部按照“什麼可以幹什麼”的格式來寫。 l 第二是不要一開始就進入細節,包涵太多細節的問題将會是一個長長的清單,這種清單根本沒什麼用。盡量從最高一層分析,但也不要簡單到“使用者可以玩遊戲”這種籠統的問題。 l 總之一個原則是全面、清晰、明确。要做好問題域分析完全取決于設計師的水準與能力,這就不是可以簡單的看看書能達到的了。 (2 )獲得名詞清單-----為發現出類提供資訊 把問題清單中的名詞都提出來,得到一個名詞清單,這就是類的來源(不過不忙,這隻是初步過程) +-----------------------+ | 系統 | | 玩家 | | 正确答案 | | 答案 | | 遊戲結果 | +-----------------------+ (3 )篩選名詞-----除掉無關的名詞 但要注意的是,不是名詞清單中的所有的名詞都能作為類的,接下來需要進行篩選。 l 玩家是參與者,應該放到用例圖上去 l 系統太籠統,不能成為一個對象的名稱 l 答案和正确答案容易混淆,但稱為輸入答案又容易被誤解成一個動作,幹脆叫做玩家答案 l 結果不明确,察看前面的需求,應該分解成錯誤資訊和完成資訊 (4 )根據名詞清單發現出其中的類 最後,對前面的名詞清單進行篩選完畢後,得到一個下面的名詞清單 +---------------------+ | 正确答案 | | 玩家答案 | | 錯誤資訊 | | 完成資訊 | +-----------------------+ 在這個清單中缺少了系統,顯得太單薄,回過頭再仔細察看需求,應該引入一個遊戲引擎,由它來充當排程者(控制類)。同時,我們再引入一些Helper類以實作遊戲的互動(邊界類 ) +-----------------------+ | 遊戲引擎 | | 正确答案 | | 玩家答案 | | 錯誤資訊 | | 完成資訊 | | 遊戲 的互動 | +-----------------------+ 進而發現出問題域中所隐藏的分析類。但要注意的是,在這個階段中所發現出的類,并不是最終要實作的類,而是一個分析類。利用分析類的主要目的是幫助設計師理清系統的關系,将需求文稿中錯綜複雜的關系整理成一個脈絡清晰的完整系統。根據規則,應該包含有三種分析類:邊界類、實體類和控制類。在本問題中,它們分别是: 邊界類: 遊戲的互動 實體類: 正确答案、玩家答案、錯誤資訊和完成資訊 控制類: 遊戲引擎 (5 )進一步修改前面的問題域,以獲得更清晰的需求描述 同時修改前面的問題域,現在系統已經明确是一個遊戲引擎。這種替換當然是一種理想情況,通常都會發生分解和關聯,那時候需要擴充問題域,有時候還需要建立新的問題域。 +-----------------------------------------------------------+ | 遊戲引擎應該準備一個正确答案 | | 玩家可以輸入一個答案 | | 遊戲引擎應該比較玩家答案和正确答案 | | 遊戲引擎應該顯示玩家每次輸入的結果 | +-----------------------------------------------------------+ (6 )分析類的層次(縱向關聯) 在前面,我們已經初步對問題域進行了分析,獲得了一個類名的名詞清單,接下來的工作則是要繪制這些分析類的層次 。現在我們要用我們的專業知識來歸納類了。很明顯,錯誤資訊和成功資訊需要一個基類,玩家答案和正确答案也是一樣。 (7)分析類之間的關聯(橫向關聯) 通過對項目中的類層次進行分析和描述以後,接下來則是要分析類之間的關聯,同樣我們也應該從需求文檔和問題域中尋找線索。在本問題中,“遊戲引擎應該準備一個正确答案”,即“遊戲引擎”與“正确答案”之間有關聯。 (8 )最後,設計出本問題例的類的分析圖(關系說明---- 靜态分析) (9 )設計出遊戲互動的順序圖---- 動态分析 (10 )設計出類中的屬性和方法--- 進一步細化分析類以最終産生出設計的類 類的關聯在類圖已經完整地設計出後,應該為類配置設定方法和屬性了,這将是以後的設計階段的工作。 二、建立領域模型總結 ( 1 )可以從用例的事件流開始,看看事件流中的名詞與名詞短語,找出大量重要的域對象以獲得所要用到的類(抽取對應于業務實體或事件的名詞),然後再分析這些類的屬性、操作和它們之間的關系。 (2 )将名詞進行分類、抽取出合适的類;同時将名詞與名詞短語成為對象與屬性,而動詞與動詞短語成為操作與關聯。 (3 )審查類及屬性 l 是否在系統責任之内 l 是否描述類對象的特征 l 是否存在備援 l 是否有複雜結構的屬性 l 根據對需求的了解進行細化 (4 )所要注意的幾點 l 素描類的特性 需要強調的是,在這一階段對特定領域類的描述具有一定的素描性質。也就是說特定領域類的操作和屬性不一定與最終實作時的定義一緻。 因為此時還沒有涉及到系統功能的具體實作,不可能準确、完整地定義它們。有一些操作需要在設計階段細化時才能确定。 l 動态行為的描述 此外,為了描述領域類的動态行為,可以使用UML中的任何一種動态圖(如順序圖、活動圖、合作圖、狀态圖)來描述。 三、模組化執行個體二: 某一網站領域模型的建立例 (1 )使用者所羅列出的一些需求 l 我需要做一個網站 l 我的文章、我最近的活動(新聞)、下載下傳和留言 l 我希望把我平時的文章釋出出來給使用者看 l 我希望把我最近做的講座放到我的活動欄目中來進行宣傳 l 我還會把我的一些源代碼和講座錄像打包發出去 l 我希望使用者給我留言 (2 )需求分析 l 功能性需求 ü 網站可以提供我平時寫的文章的連結 ü 網站可以将我最近的活動情況釋出出來 ü 網站能夠将我平時的源代碼和講座錄像打包發出去 ü 網站能夠接受使用者給我的留言 l 非功能性需求 網站要簡單、美觀和大方;浏覽的速度盡可能快。 (3 )找出名詞短語------ 領域模型
網站 平時文章 最近活動新聞 平時源代碼 講座錄像 使用者留言 管理者 文章 講座 活動 新聞欄目 源代碼 講座的錄像包 浏覽者 留言 |
(4 )發現類及類之間的關系 l 建立“使用者留言”功能子產品的包 l 在該包中分别添加各個分析類 l 設定“使用者留言”功能子產品中的相關的各個分析類的關系 l 給某個類設定其屬性和方法 l 再設定其屬性的資料類型和通路限制 l 給該類添加方法 l 設定“使用者留言”功能子產品中的互動的順序圖---- 動态分析 名稱為“使用者留言子產品的順序圖” 分别從用例圖中拖動參與者“使用者”和從“留言功能包”中拖動“留言表單”、“使用者留言”和“留言”、“留言成功”等類到視圖中。 然後再分别設計其消息的發送和傳回的次序。 注意:在上面的順序圖中所出現的各個消息沒有映射成對應類的操作方法,如“填寫表單”消息沒有映射成“留言表單”類的操作方法。是以在後面進行 用Rose生成代碼中進行“檢查模型”時會出現錯誤。 l 根據順序圖建立出協作圖 四、模組化執行個體三 下面給出“鐵路呼叫中心”項目的功能性和非功能性的需求,進而獲得“問題域”中的相關的類; (1)呼叫中心項目的功能性需求 旅客應該能夠通過系統進行車次資訊的相關查詢 旅客應該可以通過系統進行相關車次餘票的查詢 旅客應該能夠通過系統進行訂票 旅客應該能夠通過系統提供投訴意見 旅客應該可以通過系統進行行包的辦理 系統應該可以取消訂票 系統應該可以記錄旅客的操作步驟 系統語音提示應該盡量的簡單清楚 系統應該可以記錄對方使用者的電話号碼等資訊 系統應該具有少量的人工坐席和大量的自動坐席 系統應該能夠及時的響應客戶訂票,并通知訂票結果 系統應該可以自動地給旅客配置設定一個訂票号和相應的訂票密碼 系統應該可以按照車次查詢時刻表 系統應該可以按車次查詢到站時刻 系統應該可以根據始發站和到達站或途徑站的車次資訊 系統應該可以為團體客戶提供團隊訂票業務 系統應該可以為旅客提供原有訂單的查詢 ( 2 ) 呼叫中心項目的非功能性的需求 訂票流程應該盡量的簡單 訂票流程的操作時間應該盡量的短 系統應該能夠控制訂票操作的時間 系統應該能夠取消故意騷擾系統的電話 系統應該有預留接口可以友善的連接配接到其他的客服服務電話号碼中去
旅客 呼叫系統 車次資訊 車次餘票 火車票 投訴意見 行包 操作步驟 語音提示 使用者資訊 人工坐席 自動坐席 訂票結果 訂票号 訂票密碼 時刻表 到站時刻 始發站 到達站 途徑站 團體客戶 訂票業務 訂單 |
(3) 找出名詞短語------ 領域模型
( 4 )發現出類及類之間的關系 五、模組化執行個體四 下面給出“網上訂票”需求項目的功能性和非功能性的需求,進而獲得“問題域”中的相關的類; (1)網上訂票項目的功能性需求 系統應該可以允許使用者進行注冊 系統應該可以允許進行登陸 系統應該可以允許使用者修改自己的個人資訊 系統應該可以允許進行網絡線上訂票 系統應該可以允許可以根據車次查詢列車時刻表 系統應該可以根據始發站和到達站或途徑站的車次資訊 系統應該可以查詢票價 系統應該可以查詢既有訂票資訊 系統應該可以取消訂票 系統應該可以查詢晚點資訊 系統應該可以提供團體訂票業務 系統應該可以允許線上支付票款 系統應該可以查詢餘票資訊 (2)網上訂票項目的非功能性需求 網絡響應速度應該盡量快(訂票流程的操作時間應該盡量的短) 使用者填寫的資訊應該盡量的少,采用菜單選擇和勾選方式(訂票流程應該盡量的簡單) 系統應該有預留接口可以友善地連接配接到其他的客服服務電話号碼中去 (3) 找出名詞短語------ 領領域模型
系統 使用者 個人資訊 火車票 車次 時刻表 始發站 到達站 途徑站 票價 既有訂票資訊 晚點資訊 團體訂票業務 票款 餘票資訊 |
(4 )發現出類及類之間的關系 六、模組化執行個體五 下面給出“ATM系統自動售票系統”需求項目的功能性和非功能性的需求,進而獲得“問題域”中的相關的類; ( 1 ) ATM 系統自動售票系統 的功能性需求 ATM系統應該可以接受紙币 ATM系統可以接受信用卡 ATM系統可以檢驗紙币的金額 ATM應該可以驗證信用卡的密碼 ATM系統應該可以進行僞鈔的識别 ATM系統必須可以賣票 ATM系統可以驗證購票的金額與信用卡的金額的比較 ATM系統可以找零錢 ATM系統應該可以訂票? ATM可以列印交易的收據憑票 ATM系統可以吐票 ATM系統可以查閱車次資訊 ATM系統可以查詢車票的席位餘額 ATM系統應該可以對帳 ATM系統應該可以查詢錢箱中的餘額 ATM系統應該可以取消購票 ATM系統應該可以記錄操作步驟 ATM系統應該用觸摸屏 ( 2 ) ATM 系統自動售票系統 的非功能性需求 ATM系統應該可以語音提示 ATM系統應該可以對于什麼什麼進行報警? ATM系統購票過程應該操作步驟簡單 ATM系統必須有監視功能 ATM系統應該适合不通身高的人購票 (3) 找出名詞短語------ 領域模型
ATM系統 紙币 信用卡 紙币的金額 信用卡的密碼 僞鈔 票 購票的金額 零錢 列印憑條 車次 帳 錢箱的餘額 操作步驟 觸摸屏 |
(4 )發現類及類之間的關系 ATM系統的取錢使用案例的Class類圖 張三取款的順序圖 張三取100元錢的協作圖 張三取款的狀态圖