面向?qū)ο笤O(shè)計課件_第1頁
面向?qū)ο笤O(shè)計課件_第2頁
面向?qū)ο笤O(shè)計課件_第3頁
面向?qū)ο笤O(shè)計課件_第4頁
面向?qū)ο笤O(shè)計課件_第5頁
已閱讀5頁,還剩203頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

面向?qū)ο笤O(shè)計

10.1面向?qū)ο蟮南到y(tǒng)設(shè)計

系統(tǒng)設(shè)計是將分析模型變換到系統(tǒng)設(shè)計模型。在系統(tǒng)設(shè)計的過程中,開發(fā)者定義了項目的設(shè)計目標,將系統(tǒng)分解為粒度更小的子系統(tǒng)。開發(fā)者還要選擇構(gòu)造系統(tǒng)的策略,比如硬件/軟件策略、持久性數(shù)據(jù)管理策略、全局控制流策略、訪問控制策略、邊界條件處理策略等。系統(tǒng)設(shè)計后得到的是一個包括子系統(tǒng)分解和每個策略的清晰描述模型。

系統(tǒng)設(shè)計由一些活動組成,每一活動都專注于整個問題中某一個部分的系統(tǒng)分解,這些活動是:

標識系統(tǒng)目標。開發(fā)者標識并區(qū)分應(yīng)進行優(yōu)化的各種系統(tǒng)屬性的優(yōu)先次序。設(shè)計初始子系統(tǒng)分解。根據(jù)用例和分析模型,開發(fā)者將系統(tǒng)分解成一些小部分。求精子系統(tǒng)分解以對應(yīng)設(shè)計目標。系統(tǒng)的構(gòu)建主要包括系統(tǒng)設(shè)計、對象設(shè)計和實現(xiàn)三個活動。在系統(tǒng)設(shè)計過程中,我們將注意力放在實現(xiàn)系統(tǒng)所必需考慮的過程、數(shù)據(jù)結(jié)構(gòu)和軟硬件構(gòu)件上面。許多彼此有沖突的準則和約束,在分解系統(tǒng)的時候必須得到折衷。

10.1.1系統(tǒng)設(shè)計概述

分析所得到的結(jié)果是需求模型,需求模型包括如下內(nèi)容:一個描述非功能需求和約束的集合,其內(nèi)容涉及:最大響應(yīng)時間、最小吞吐量、可靠性、操作系統(tǒng)平臺等等;一個用例模型,從參與者的視角描述了系統(tǒng)功能一個對象模型,描述了系統(tǒng)所操縱的多個實體;每一個用例對應(yīng)一個順序圖,展示了參與用例的對象之間的交互順序。

分析模型從參與者的視角描述了整個系統(tǒng),但是,不包含系統(tǒng)內(nèi)部的結(jié)構(gòu)信息和硬件配置信息。系統(tǒng)設(shè)計包括如下內(nèi)容:

設(shè)計目標,描述了開發(fā)者應(yīng)該進行優(yōu)化的系統(tǒng)性質(zhì);軟件體系結(jié)構(gòu),描述了根據(jù)子系統(tǒng)任務(wù)進行的子系統(tǒng)分解、子系統(tǒng)之間的依賴關(guān)系、子系統(tǒng)到硬件的映射和諸如對控制流、訪問控制和數(shù)據(jù)存儲的決策;邊界用例,描述了系統(tǒng)的配置、起始點、關(guān)閉點和異常處理問題。設(shè)計目標通過非功能需求獲取。當需要在多個設(shè)計問題之間做權(quán)衡時,設(shè)計目標可以指導開發(fā)者做出正確的決策。分解子系統(tǒng)構(gòu)成了系統(tǒng)設(shè)計的主要內(nèi)容。開發(fā)者將系統(tǒng)分解為多個容易管理的部分,每個子系統(tǒng)分配給一個團隊,由該團隊獨立實現(xiàn)該子系統(tǒng)。圖10.1從面向?qū)ο蠼嵌让枥L了系統(tǒng)設(shè)計與軟件工程中其他活動之間的關(guān)系。

10.1.2系統(tǒng)設(shè)計概念

系統(tǒng)設(shè)計的主要活動是進行子系統(tǒng)分解,并在此基礎(chǔ)上定義子系統(tǒng)/構(gòu)件之間的接口。1.子系統(tǒng)與類

為降低解域的復(fù)雜性,我們將一個系統(tǒng)分解成多個子系統(tǒng),這些子系統(tǒng)由若干個表示解域的類構(gòu)成。子系統(tǒng)與一定數(shù)量的任務(wù)相對應(yīng),這些任務(wù)由單個程序員或單個開發(fā)團隊來處理。通過將系統(tǒng)分解成多個相對獨立的子系統(tǒng),可以使多個團隊在各個子系統(tǒng)上并發(fā)工作,也減少了彼此交流所產(chǎn)生的管理上的開銷。對在前面已經(jīng)描述過的火災(zāi)報警與調(diào)度系統(tǒng)中,經(jīng)過分解可以得到:

(1)調(diào)度者接口子系統(tǒng),以實現(xiàn)調(diào)度者的用戶接口;(2)現(xiàn)場工作人員接口子系統(tǒng),以實現(xiàn)現(xiàn)場工作人員的用戶接口;(3)事件管理子系統(tǒng)負責實現(xiàn)事件的創(chuàng)建、修改和存儲;(4)資源管理子系統(tǒng)負責跟蹤可用資源(如救火車和救護車);(5)地圖管理子系統(tǒng)負責描繪地圖和位置;(6)通告子系統(tǒng)用于實現(xiàn)現(xiàn)場工作人員的終端與調(diào)度者群體之間的通信。

意外事故響應(yīng)的信息系統(tǒng)的子系統(tǒng)分解

2.服務(wù)與子系統(tǒng)接口

子系統(tǒng)的特征是由該子系統(tǒng)提供給其他子系統(tǒng)的服務(wù)來刻畫。一個服務(wù)是一組有著公共目的相關(guān)操作。例如,負責提供通知服務(wù)的子系統(tǒng)往往定義了發(fā)送通知的操作。供其他子系統(tǒng)調(diào)用的某個子系統(tǒng)的操作集合就是子系統(tǒng)接口。子系統(tǒng)接口包括操作名、操作參數(shù)、類型及其返回值。系統(tǒng)設(shè)計關(guān)注于每個子系統(tǒng)提供服務(wù)的定義,即枚舉出所有操作、這些操作涉及的參數(shù)和操作的高層行為。當編寫子系統(tǒng)接口的文檔時,應(yīng)該注意盡量減少有關(guān)子系統(tǒng)實現(xiàn)的細節(jié)信息。

3.分層與劃分

某個系統(tǒng)的層次分解將產(chǎn)生層次的有序集合。層是指一組提供相關(guān)服務(wù)的子系統(tǒng),它多半是通過使用另一層的服務(wù)來實現(xiàn)本層的功能。層一定是有序組織的,每一層僅依賴于它的下一層,而且對其上層情況是一無所知的。層次分解中每一層至少包含一個稱為垂直切片子系統(tǒng)的某個系統(tǒng)分解子集。在一個封閉體系結(jié)構(gòu)中,每一層只能訪問與其相鄰的下一層。在開放體系結(jié)構(gòu)中,每一層還可以訪問比與其相鄰下一層更低的層次。封閉體系結(jié)構(gòu)的一個例子是開放系統(tǒng)互聯(lián)參考模型(簡寫為OSI模型),它是由七層構(gòu)成。每一層負責執(zhí)行一個已預(yù)先定義好的協(xié)議功能。另外,每一層都提供自己的服務(wù),使用比其低的層次服務(wù)(圖10.5)。

直到最近,OSI模型中也只有底部的四層被很好地標準化了。CORBA和JavaRMI允許我們通過向遠程對象發(fā)送消息,以透明地訪問應(yīng)用層的構(gòu)件,這一過程就跟向本地對象發(fā)送消息一樣,CORBA高效地實現(xiàn)了表示層和會話層(參照圖10.6)。

開放體系結(jié)構(gòu)的一個例子是Java的Swing用戶接口工具包。一般來說,體系結(jié)構(gòu)的開放允許開發(fā)者繞過高層直接訪問低層接口以克服性能瓶頸。

封閉分層體系結(jié)構(gòu)具有如下期望的特性:子系統(tǒng)之間具有低耦合的特征、子系統(tǒng)可以被增量地集成和測試。但是,每一層引入了一個速度和存儲管理費用問題,這就會導致一些非功能屬性難以滿足。此外,在隨后的新修改版本中向原有系統(tǒng)加入新的功能已被證實有困難,特別是加入一些事先沒有預(yù)料到的功能。實踐當中,一個系統(tǒng)很少被分解超過五層的情況。

處理復(fù)雜性的一種方法是劃分,將系統(tǒng)分解成對等的子系統(tǒng),每個子系統(tǒng)負責一類不同的服務(wù)。我們利用分層與劃分來進行一個子系統(tǒng)分解。首先使用劃分方法,將一個系統(tǒng)分成頂層的幾個子系統(tǒng)。這樣得到的每個子系統(tǒng),如果還存在比較復(fù)雜的子系統(tǒng),則對它進一步進行分層的處理,將其分解為層次更低的多個小子系統(tǒng),直到小子系統(tǒng)簡單到可以由單個的開發(fā)者實現(xiàn)為止。10.1.3系統(tǒng)設(shè)計活動:從對象到子系統(tǒng)

系統(tǒng)設(shè)計需要考慮在需求分析文檔中描述的非功能屬性。我們通過車輛路程規(guī)劃系統(tǒng)來展示系統(tǒng)設(shè)計活動。1.出發(fā)點:車輛線路規(guī)劃系統(tǒng)的分析模型

司機采用車輛路程規(guī)劃系統(tǒng)可以讓家里的計算機通過網(wǎng)絡(luò)上的旅程規(guī)劃服務(wù)來規(guī)劃自己的旅程。旅程規(guī)劃在服務(wù)器上保存起來,并為以后的檢索服務(wù)。旅行規(guī)劃服務(wù)必須支持多個司機。車輛路程規(guī)劃系統(tǒng)中的規(guī)劃行程用例

用例名稱規(guī)劃行程用例事件流1.司機激活其計算機并登錄到旅程規(guī)劃網(wǎng)絡(luò)服務(wù)系統(tǒng)。2.司機輸入對旅程的約束,應(yīng)是一個含多個目的地的序列。3.基于地圖數(shù)據(jù)庫,規(guī)劃服務(wù)計算出按照規(guī)定順序訪問的目的地的最短路程。計算結(jié)果是一個帶有一系列路口和方向列表的行程段序列。4.司機能夠通過添加或刪除目的地來重新設(shè)計旅程。5.司機以名稱形式在規(guī)劃服務(wù)的數(shù)據(jù)庫中存儲規(guī)劃好的旅程,以便日后檢索。司機發(fā)動轎車開始其旅程,此時車載計算機將給出具體方向,這是基于規(guī)劃服務(wù)中的旅程信息和車載的全球定位系統(tǒng)對當前位置的提示完成的(在圖10.9中)。

車輛路程規(guī)劃系統(tǒng)中的執(zhí)行行程用例

用例名稱執(zhí)行行程用例事件流1.司機啟動其轎車,登錄到車載的路線助手系統(tǒng)上。2.成功登錄后,司機規(guī)定使用規(guī)劃服務(wù)系統(tǒng)規(guī)劃行程。3.車載的路線助手系統(tǒng)從旅程規(guī)劃服務(wù)系統(tǒng)獲得目的地、方向、行程段和路口的信息列表。4.給定當前位置,線路助手系統(tǒng)為司機提供下一個方向集合。5.司機到達目的地,關(guān)閉路線助手系統(tǒng)。車輛路程規(guī)劃系統(tǒng)和執(zhí)行的分析模型

路口路口是指若干地理上行程段的交匯點。目的地目的地表示了司機想去的位置。方向給定路口和鄰接的行程段,方向是用自然語言描述的如何駕駛車輛到達指定的行程段。位置位置是由車載全球定位系統(tǒng)或通過計算車輪轉(zhuǎn)過的數(shù)目得出的轎車所處的位置。規(guī)劃服務(wù)規(guī)劃服務(wù)是一個網(wǎng)絡(luò)服務(wù)器,能支持旅程,以路口和行程段序列的形式連接多個目的地。線路助手線路助手根據(jù)轎車當前位置和下一站路口信息,為司機指出方向。行程段行程段展示了兩個路口之間的路程。旅程旅程是兩個目的地之間的方向序列。此外,在需求獲取中,客戶對車輛路程規(guī)劃系統(tǒng)標識了如下的非功能需求:

(1)系統(tǒng)與計劃服務(wù)是通過無線調(diào)制解調(diào)器來連接的。假設(shè)無線調(diào)制解調(diào)器在初始目的地也能正確地工作。(2)

一旦旅程開始,即使調(diào)制解調(diào)器與計劃服務(wù)的連接失敗,系統(tǒng)也應(yīng)該給出正確的方向。(3)系統(tǒng)應(yīng)該盡量減少連接時間以便降低操作開銷。(4)只有在與計劃服務(wù)能夠聯(lián)系的情況下才可以重新規(guī)劃線路。(5)計劃服務(wù)要能夠至少支持50個不同的司機和1000個旅程。2.明確設(shè)計目標

明確系統(tǒng)設(shè)計目標的含義,是進行系統(tǒng)設(shè)計的第一步。定義明確了系統(tǒng)必須關(guān)注的質(zhì)量屬性。許多設(shè)計目標可以從非功能需求或應(yīng)用領(lǐng)域中抽取出來。另一些設(shè)計目標則應(yīng)從用戶那里得到。下面我們總結(jié)了相關(guān)的設(shè)計目標。

系統(tǒng)的設(shè)計目標

可靠性:系統(tǒng)應(yīng)該是可靠的[非功能需求2的泛化]。容錯性:系統(tǒng)應(yīng)該在失去與線路服務(wù)時能夠容錯[非功能需求2的另一種說法]。安全性:系統(tǒng)應(yīng)該是安全的,即不允許其他的司機或是沒有授權(quán)的用戶訪問某個司機的旅程規(guī)劃[由應(yīng)用領(lǐng)域推導出來]。可修改性:為使用不同的線路服務(wù),系統(tǒng)應(yīng)該是可以修改的[對由開發(fā)人員所做更改的預(yù)測]。

我們通??蓮囊婚L串期望的屬性列表中選擇出設(shè)計目標。表6-2到表6-6列出了一些可能的設(shè)計準則。這些設(shè)計準則分成五組:性能、可靠性、成本、維護和最終用戶準則。性能、可靠性和最終用戶準則往往從需求中明確獲取,或者可以從應(yīng)用領(lǐng)域中獲取。成本和維護準則由客戶和供應(yīng)商提出。

性能準則(表10.1)包括了對系統(tǒng)速度和空間的需求。

可靠性準則(表10.2)決定對減少系統(tǒng)崩潰及隨后造成的危害所做的努力程度。

成本準則(表10.3)包括開發(fā)、配置和管理系統(tǒng)的成本。注意,成本準則不僅包括設(shè)計上的考慮,還包括管理上的考慮。當新系統(tǒng)取代舊系統(tǒng)時,我們應(yīng)該確保向后兼容性,或減少移植到新系統(tǒng)的開銷。在各種成本中(如開發(fā)成本、最終用戶培訓成本、移植成本和維護成本),我們必須做出權(quán)衡。維護準則(表10.4)決定完成部署后再改變系統(tǒng)的困難程度。這些內(nèi)容具體涉及:增加新的功能有多困難?對現(xiàn)存功能進行修改有多困難?系統(tǒng)能夠適用不同的應(yīng)用領(lǐng)域嗎?如果需要將系統(tǒng)移植到另一個平臺上,需要花費多大努力?這些準則很難進行優(yōu)化和事先規(guī)劃,因為很少能清晰地給出項目成功的程度和系統(tǒng)可操作的時間周期。最終用戶準則(表10.5)包括從用戶視點出發(fā)所涉及的屬性,這些屬性與性能準則和可靠性準則并不重復(fù)。這些內(nèi)容具體涉及:軟件使用和學習的困難程度?用戶是否能夠在系統(tǒng)上完成所需任務(wù)?在與系統(tǒng)簽約的客戶并非系統(tǒng)用戶時,這些準則通常不會得到關(guān)注。

當定義設(shè)計目標時,這些準則通常只有一個很小的子集被考慮到了。例如,希望開發(fā)一個安全、可靠并且廉價的系統(tǒng)是不現(xiàn)實的。典型情況下,開發(fā)者應(yīng)該優(yōu)先考慮一些設(shè)計目標,將這些目標與其他設(shè)計目標進行權(quán)衡(參表10.6)。此外,還要權(quán)衡管理目標與技術(shù)目標??傊?,一旦有了清晰的設(shè)計目標,我們就可以對子系統(tǒng)進行初始分解了。

表10.6設(shè)計目標權(quán)衡的例子

權(quán)衡基本原理空間與速度如果軟件的響應(yīng)時間或吞吐量不滿足需求,則可以使用更多的存儲空間(例如,高速緩沖,更大的冗余)來加快軟件的執(zhí)行速度。如果軟件太大,則可以犧牲一定的速度對數(shù)據(jù)進行壓縮處理。交付時間與功能如果開發(fā)進度滯后于時間表,項目經(jīng)理可以按時交付功能比已經(jīng)明確的功能要少,或只能夠推遲交付全部功能。契約軟件通常更強調(diào)功能,而商業(yè)外購軟件項目則更強調(diào)交付日期。交付時間與質(zhì)量如果測試滯后于時間表,項目經(jīng)理可以按時交付帶有已知錯誤的軟件,或推遲交付帶有少量錯誤的軟件。交付時間與人員安置如果開發(fā)進度滯后于時間表,項目經(jīng)理能夠向項目中增加資源以提高生產(chǎn)率。在多數(shù)情況下,這種選擇只適用于早期項目:新的人員要經(jīng)過培訓方可使用,這樣增加資源通常會降低生產(chǎn)率。注意,增加資源還會增加軟件的開發(fā)成本。3.明確子系統(tǒng)

在面向?qū)ο蠓治鲋形覀兘榻B了一些像Abbotts啟發(fā)式方法之類的對象鑒別技術(shù),這一思想也同樣適用于子系統(tǒng)的鑒別。當新問題被進一步提出時,將對子系統(tǒng)分解進行如下一些修改:將一些子系統(tǒng)歸并為一個子系統(tǒng),將一個復(fù)雜的子系統(tǒng)分成更多的部分,在一些子系統(tǒng)中添加新功能。設(shè)計者最好通過集體討論來解決分解問題。初始子系統(tǒng)分解應(yīng)該從需求的功能模型中導出。例如,在車輛路程規(guī)劃系統(tǒng)中,我們主要標識了兩組對象:一組與規(guī)劃行程用例相關(guān),另一組與執(zhí)行行程用例相關(guān)。行程類、方向類、路口類、旅程類、規(guī)范服務(wù)類和目的地類被用于所有的用例上。該類集合由于整體用于行程類,所以設(shè)計是緊密耦合的。我們決定將這些類分給規(guī)劃子系統(tǒng)中的規(guī)劃服務(wù),其余的類則分到行程安排子系統(tǒng)中(圖10.11)。這樣跨越子系統(tǒng)邊界的關(guān)聯(lián)只有一個。子系統(tǒng)確認規(guī)則要求保持功能相關(guān)對象的整體性。將對象分組歸入子系統(tǒng)的規(guī)則是:將在同一用例中明確的對象歸入同一個子系統(tǒng);為對象創(chuàng)建一個專門的子系統(tǒng),用來在子系統(tǒng)間移動數(shù)據(jù);盡量減少跨越子系統(tǒng)邊界的關(guān)聯(lián)數(shù)目;同一個子系統(tǒng)中的所有對象應(yīng)該是功能相關(guān)的。

子系統(tǒng)分解應(yīng)該通過減少這些子系統(tǒng)之間的耦合程度,以降低解答域的復(fù)雜性。層面設(shè)計模式通過簡單的、統(tǒng)一的接口來封裝子系統(tǒng),以求達到進一步減少類之間的依賴性。例如,層面僅提供對子系統(tǒng)公共服務(wù)的訪問權(quán),隱藏其他的所有細節(jié),有效地減少了子系統(tǒng)之間地耦合度。

在初始的子系統(tǒng)分解中,我們往往將功能相關(guān)的類加以分組,接著標識出子系統(tǒng)。當這些子系統(tǒng)可以作為層面設(shè)計模式候選時,我們用一個類加以封裝。

圖10.12層面設(shè)計模式的一個示例

10.2面向?qū)ο竽繕素瀼?/p>

10.2.1面向?qū)ο笤O(shè)計的目標貫徹

我們將介紹一些確保設(shè)計目標得以貫徹的系統(tǒng)設(shè)計活動。描述與子系統(tǒng)設(shè)計有關(guān)的管理問題,例如編寫文檔、責任分派和交流。我們將特別關(guān)注:對商業(yè)外購構(gòu)件和遺留構(gòu)件的選擇;將子系統(tǒng)映射到硬件;

持久性數(shù)據(jù)管理基礎(chǔ)設(shè)施的設(shè)計;訪問控制策略的規(guī)格說明;全局控制流的設(shè)計;邊界條件的處理。

對上述這些特別關(guān)注的內(nèi)容,現(xiàn)說明如下:商業(yè)外購構(gòu)件或遺留構(gòu)件可更經(jīng)濟地實現(xiàn)特定子系統(tǒng)。我們應(yīng)該在初始子系統(tǒng)分解時,仔細考慮這些內(nèi)容;當系統(tǒng)被部署到一些結(jié)點上時,需要關(guān)注附加子系統(tǒng)的可靠性及性能問題;管理那些生命周期比系統(tǒng)執(zhí)行一次的時間還要長的狀態(tài),會對整個系統(tǒng)的性能造成影響,這一需求導致需要標識一個或更多的存儲子系統(tǒng);保護共享對象以便用戶對這些對象的訪問是受控的。訪問控制將影響對象在子系統(tǒng)中的分布方式;決定操作順序,該順序會影響子系統(tǒng)的接口;一旦所有的子系統(tǒng)被確定下來,開發(fā)者就可以決定單個構(gòu)件的啟動和關(guān)閉順序。10.2.2系統(tǒng)設(shè)計活動概述

開發(fā)者在分解系統(tǒng)時需要把握好一些系統(tǒng)級的問題。特別是要把握好以下幾個問題:

l

硬件/軟件映射問題;l

數(shù)據(jù)管理問題;l

訪問控制問題;l

控制流問題;l

邊界條件問題等。在硬件/軟件映射方面,我們要考慮:系統(tǒng)的硬件配置是什么?哪個結(jié)點負責哪個功能?結(jié)點之間的通信是如何實現(xiàn)的?哪些服務(wù)是否是用現(xiàn)存的軟件構(gòu)件實現(xiàn)的?這些構(gòu)件是如何被封裝的?考慮硬件/軟件映射問題會導致附加系統(tǒng)的定義。這些附加系統(tǒng)的功能之一,就是負責將數(shù)據(jù)從一個結(jié)點移動到另一個結(jié)點,以處理并發(fā)和可靠性問題。商業(yè)外購構(gòu)件允許開發(fā)者更經(jīng)濟地實現(xiàn)復(fù)雜的服務(wù)。用戶接口包和數(shù)據(jù)庫管理系統(tǒng)是商業(yè)外購構(gòu)件的主要例子。在數(shù)據(jù)管理方面,我們要考慮:哪些數(shù)據(jù)應(yīng)該是持久性數(shù)據(jù)?持久性數(shù)據(jù)應(yīng)該被存儲在哪里?如何訪問它們?在許多不同的情況下持久性數(shù)據(jù)都有系統(tǒng)瓶頸:系統(tǒng)中的大部分功能都與創(chuàng)建或操縱持久性數(shù)據(jù)有關(guān)。正是由于這個原因,對數(shù)據(jù)的訪問應(yīng)該是快速的、可靠的。檢索數(shù)據(jù)的速度問題,以及數(shù)據(jù)之間的一致性問題等,都必須在系統(tǒng)層上得到一致地通盤考慮。在訪問控制方面,我們要考慮:誰能夠訪問什么數(shù)據(jù)?訪問控制能夠動態(tài)改變嗎?訪問控制是如何標識并實現(xiàn)的?訪問控制和安全是系統(tǒng)層面上的問題。訪問控制的一致性是跨越整個系統(tǒng)的。在控制流方面,我們要考慮:系統(tǒng)的操作序列是怎么樣的?系統(tǒng)是由消息驅(qū)動的嗎?系統(tǒng)每次能夠處理多于一個用戶的交互嗎?控制流的選擇對子系統(tǒng)的接口是有影響的。如果選擇的是消息驅(qū)動控制流,子系統(tǒng)將提供消息句柄。如果選擇的是線程,子系統(tǒng)必須保證臨界區(qū)的互斥。

在邊界條件方面,我們要考慮:系統(tǒng)是如何初始化的?系統(tǒng)又是如何關(guān)閉的?異常案例是如何被偵測并處理的?系統(tǒng)初始化和關(guān)閉往往能夠展示出一個系統(tǒng)含有的絕大部分復(fù)雜性,分布式環(huán)境更是如此。初始化、關(guān)閉和異常處理對所有子系統(tǒng)的接口都有影響。圖10.13描繪了系統(tǒng)設(shè)計的活動。每個活動涉及我們前面描述的問題。下圖所示的每個活動,所表示的系統(tǒng)設(shè)計是高度迭代的活動,這將導致新的子系統(tǒng)的確定、現(xiàn)存子系統(tǒng)的修改以及對所有子系統(tǒng)產(chǎn)生影響的系統(tǒng)層面上的改動。

圖10.13系統(tǒng)設(shè)計活動

10.2.3UML部署圖

UML部署圖用來展示系統(tǒng)運行期間構(gòu)件和硬件結(jié)點之間的關(guān)系。構(gòu)件是自含的實體,可為其他構(gòu)件或參與者提供服務(wù)。在UML部署圖中,結(jié)點用含有構(gòu)件圖標的盒子來表示。構(gòu)件之間的依賴用帶箭頭的虛線來表示。圖10.14描繪了一個用兩個網(wǎng)絡(luò)瀏覽器訪問一臺網(wǎng)絡(luò)服務(wù)器部署圖的例子。圖10.14UML部署圖展示了構(gòu)件分配到不同結(jié)點的情況和構(gòu)件之間的依賴關(guān)系

圖10.14中部署圖的關(guān)注點,主要集中在將構(gòu)件分配到不同的結(jié)點上,提供每個構(gòu)件的高層視圖。構(gòu)件能夠被求精,包括它們所提供的有關(guān)接口信息和它們所包含的類信息。圖10.15WebServer提供了兩個接口:一個瀏覽器既可以通過讀接口訪問通過統(tǒng)一資源定位器(URL)所標識的文件中的內(nèi)容,又可以通過寫接口發(fā)送表單。

圖10.15WebServer的求精視圖

10.2.4系統(tǒng)設(shè)計活動中的設(shè)計目標貫徹

為了確保子系統(tǒng)分解,我們需要知道所有的非功能需求和解決實現(xiàn)階段的任何限制條件。首先,我們標識出一些設(shè)計目標,接著,我們將通過以下活動對子系統(tǒng)分解進行求精:

(1)將子系統(tǒng)映射到處理器和構(gòu)件上;(2)標識并存儲持久性數(shù)據(jù);(3)提供訪問控制;(4)設(shè)計全局控制流;(5)標識邊界條件;(6)評審系統(tǒng)設(shè)計。1.將子系統(tǒng)映射到處理器和構(gòu)件

第一步,選擇硬件配置與平臺。許多系統(tǒng)運行在不止一臺計算機上,而且系統(tǒng)的運行依賴于對企業(yè)內(nèi)部網(wǎng)絡(luò)和因特網(wǎng)的訪問。因此我們需要確保將子系統(tǒng)分配到多臺計算機上,以設(shè)計其基礎(chǔ)設(shè)施來支持子系統(tǒng)之間的通信。這些計算機在UML部署圖中,用一些結(jié)點來進行建模。因為將構(gòu)件映射到硬件活動上,對系統(tǒng)性能和復(fù)雜性有著重要的意義,我們將在系統(tǒng)設(shè)計中盡早地進行這一活動。選擇一個硬件配置也包括選擇虛擬機,要構(gòu)建的系統(tǒng)將在其上面運行。虛擬機包括操作系統(tǒng)和任意所需的軟件構(gòu)件。然而,對虛擬機的選擇將會受到來自客戶的約束,還會受到成本因素的限制。在車輛路程規(guī)劃系統(tǒng)中,我們從需求得知:規(guī)劃子系統(tǒng)和路由子系統(tǒng)運行在兩個不同的結(jié)點上。前者運行在基于網(wǎng)絡(luò)服務(wù)器的因特網(wǎng)主機上,后者運行在隨車攜帶的計算機上。圖10.16給出了車輛路程規(guī)劃系統(tǒng)所帶有的兩個結(jié)點的硬件分配,分別稱為隨車攜帶計算機和基于Web的網(wǎng)絡(luò)服務(wù)器。圖10.16將車輛路程規(guī)劃系統(tǒng)子系統(tǒng)分配到硬件上。將路由子系統(tǒng)分配到隨車攜帶計算機上;規(guī)劃子系統(tǒng)分配到基于Web的網(wǎng)絡(luò)服務(wù)器上

第二步,將對象和子系統(tǒng)分配到結(jié)點上。在車輛路程規(guī)劃系統(tǒng)的子系統(tǒng)中,路由子系統(tǒng)和規(guī)劃子系統(tǒng)共享了行程對象、目的地對象、交叉口對象、路段對象和方向?qū)ο?。這些類的實例需采用一些通信協(xié)議,并通過無線調(diào)制解調(diào)器來進行彼此間的通信。我們創(chuàng)建一個通信子系統(tǒng)來支持該通信。存儲在路由子系統(tǒng)中的信息僅構(gòu)成了旅途規(guī)劃的部分內(nèi)容。旅途規(guī)劃的另一部分內(nèi)容則存在于規(guī)劃子系統(tǒng)中。考慮到這些問題,我們需要路由子系統(tǒng)中的對象為規(guī)劃子系統(tǒng)中的路段和行程提供代理服務(wù)。一個能夠代表另一個對象的對象被稱為“代理”。因此,我們創(chuàng)建了兩個新類,路段代理和行程代理,并將這些對象作為路由子系統(tǒng)的一部分。一旦司機需要重新規(guī)劃行程路線,這個類將會向通信子系統(tǒng)發(fā)出透明請求,以檢索規(guī)劃子系統(tǒng)中與路段有關(guān)的信息。最后,通信子系統(tǒng)將一個完整的旅程線路從規(guī)劃子系統(tǒng)轉(zhuǎn)移到路由子系統(tǒng)上。一般來說,將某一子系統(tǒng)分配到硬件結(jié)點上,這意味著我們能夠?qū)⒐δ芎吞幚砟芰Ψ峙涞阶钚枰@些子系統(tǒng)的地方。但隨之而來的問題是,這一決策也引入了子系統(tǒng)中的數(shù)據(jù)存儲、數(shù)據(jù)轉(zhuǎn)移、數(shù)據(jù)復(fù)制和同步數(shù)據(jù)有關(guān)的一系列問題。

圖10.17修改后的車輛路程規(guī)劃系統(tǒng)設(shè)計模型

通信子系統(tǒng)

負責傳輸規(guī)劃子系統(tǒng)信息到路由子系統(tǒng)中的對象。連接

連接展示了規(guī)劃子系統(tǒng)與路由子系統(tǒng)間的活動關(guān)聯(lián)。連接對象需要處理網(wǎng)絡(luò)服務(wù)中異常的用例。消息

消息展示了旅程和與它相關(guān)的目的地、行程段、路口和方向等方面的信息,可為傳輸提供編碼。2.標識并存儲持久性數(shù)據(jù)

持久性數(shù)據(jù)的生命周期要長于系統(tǒng)的一次執(zhí)行周期。數(shù)據(jù)在系統(tǒng)中的存儲位置和存儲方式將會影響到系統(tǒng)分解。在一些情況下,例如,在倉庫體系結(jié)構(gòu)風格中,一個子系統(tǒng)能夠被完全地劃分出來進行數(shù)據(jù)存儲。對特定數(shù)據(jù)庫管理系統(tǒng)的選擇也會對全局控制策略和并發(fā)管理產(chǎn)生影響。例如,在車輛路程規(guī)劃系統(tǒng)中,我們決定將當前的行程存儲到一個可拆卸的磁盤文件中,以便在司機在到達最終目的地之前,如果汽車發(fā)生拋錨等故障時,能夠隨時對行程進行恢復(fù)。在這種情況下,使用文件進行記錄的方式是最簡單、最有效的解決方案,假定路由子系統(tǒng)在汽車拋錨前,在文件上存儲有完整的行程,在系統(tǒng)啟動時就會加載該文件。然而,在規(guī)劃子系統(tǒng)中,行程將被存儲在數(shù)據(jù)庫中。這個子系統(tǒng)能夠被用于管理多個司機的所有行程和產(chǎn)生行程所需的地圖。在這個子系統(tǒng)中采用數(shù)據(jù)庫,允許我們在這些數(shù)據(jù)上執(zhí)行復(fù)雜的查詢。我們添加行程文件存儲子系統(tǒng)和映射數(shù)據(jù)庫存儲子系統(tǒng)到車輛路程規(guī)劃系統(tǒng)中,以反映這些決策。

圖10.18數(shù)據(jù)存儲問題做出決策后,車輛路程規(guī)劃系統(tǒng)的子系統(tǒng)分解

行程文件存儲子系統(tǒng)

行程文件存儲子系統(tǒng)負責將旅程數(shù)據(jù)存儲到車載計算機的文件中。因為這個存儲旅程的功能只是在車輛拋錨時使用,所以該子系統(tǒng)只支持整個旅程的快速存儲和載入。映射數(shù)據(jù)庫存儲子系統(tǒng)

映射數(shù)據(jù)庫存儲子系統(tǒng)負責將地圖和旅程數(shù)據(jù)存儲到規(guī)劃子系統(tǒng)的數(shù)據(jù)庫中。該子系統(tǒng)支持多個并發(fā)的司機和規(guī)劃代理。第一步,標識持久性對象。首先,我們要標識出哪些數(shù)據(jù)是持久性數(shù)據(jù)。在車輛路程規(guī)劃系統(tǒng)中,行程及其相關(guān)類(如交叉口類、目的類、規(guī)劃服務(wù)類和路段類等)必須存儲。注意,并非所有的實體對象均要存儲,例如,在汽車移動時不停地在重復(fù)計算位置和方向等數(shù)據(jù)就不必進行存儲。然而,持久性對象并不局限于實體對象,也可以是邊界對象,如在一個多用戶系統(tǒng)中,與用戶相關(guān)的信息是持久性的,一些邊界對象的屬性也是持久性的(例如,窗口位置、用戶界面喜好、長期運行的控制對象的狀態(tài))。通常地,我們可以在系統(tǒng)關(guān)閉后,通過檢查所有必須保存的類,以標識出持久性對象。第二步,選擇存儲管理策略。存儲管理的決策十分復(fù)雜,常常受到如下非功能屬性的制約:對象能被迅速地檢索出來嗎?系統(tǒng)一定要執(zhí)行復(fù)雜的查詢來檢索這些對象嗎?這些對象需要大量的內(nèi)存和磁盤空間嗎?目前有三種選擇方案來進行存儲管理:1)文件;2)關(guān)系數(shù)據(jù)庫;3)面向?qū)ο髷?shù)據(jù)庫。文件是一種由操作系統(tǒng)提供的存儲抽象。應(yīng)用程序以字符序列形式存儲其數(shù)據(jù),應(yīng)用程序可定義用什么方式、在什么時間檢索數(shù)據(jù)。文件抽象相對層次較低但是文件的使用中需要應(yīng)用程序考慮許多問題。關(guān)系數(shù)據(jù)庫提供了比文件層次更高的數(shù)據(jù)抽象。數(shù)據(jù)是遵照預(yù)先定義好的模式類型進行存儲。關(guān)系數(shù)據(jù)庫提供了并發(fā)管理、訪問控制和故障恢復(fù)服務(wù)。關(guān)系數(shù)據(jù)庫已成為一項成熟的技術(shù),但對非結(jié)構(gòu)化數(shù)據(jù)(例如,圖像、自然語言文本),速度就顯得太慢了。面向?qū)ο髷?shù)據(jù)庫提供的服務(wù)與關(guān)系數(shù)據(jù)庫類似。與關(guān)系數(shù)據(jù)庫不同的是,面向?qū)ο髷?shù)據(jù)庫以對象和關(guān)聯(lián)的方式來存儲數(shù)據(jù);它提供一個上層的抽象并為開發(fā)者提供了繼承和抽象數(shù)據(jù)類型??傊嫦?qū)ο髷?shù)據(jù)庫可以極大地減少存儲子系統(tǒng)的開發(fā)時間。但是面向?qū)ο髷?shù)據(jù)庫的查詢速度比關(guān)系數(shù)據(jù)庫慢,且更不容易調(diào)試。圖10.19在文件和數(shù)據(jù)庫之間所做的存儲管理的權(quán)衡

1.選擇文件的規(guī)則:1)存在大量的數(shù)據(jù)(例如,圖像);2)存在臨時數(shù)據(jù)(例如,磁心存儲文件);3)存在低密度信息(例如,檔案文件、歷史日志)。2.選擇關(guān)系數(shù)據(jù)庫或面向?qū)ο髷?shù)據(jù)庫的規(guī)則:1)存在并發(fā)訪問;2)訪問比較合適的細節(jié)層;3)對相同數(shù)據(jù)的多重平臺或應(yīng)用。3.選擇關(guān)系數(shù)據(jù)庫的規(guī)則:1)屬性上的復(fù)雜查詢;2)存在大數(shù)據(jù)集。4.選擇面向?qū)ο髷?shù)據(jù)庫的規(guī)則:1)為檢索數(shù)據(jù)擴展關(guān)聯(lián)的使用;2)中等尺寸的數(shù)據(jù)集;3)對象之間的不規(guī)則關(guān)聯(lián)。3.提供訪問控制

在多用戶系統(tǒng)中,不同的參與者對不同功能和數(shù)據(jù)具有不同的訪問權(quán)限。例如,在車輛路程規(guī)劃系統(tǒng)中,在同一個數(shù)據(jù)庫中存儲地圖信息和行程信息會引發(fā)安全問題。我們必須確保行程僅被發(fā)送給創(chuàng)建這些行程的司機。為此我們使用司機類來對司機建模,將該類與行程類關(guān)聯(lián)起來。規(guī)劃子系統(tǒng)負責在發(fā)送行程之前對司機進行標識。最后,我們需要對路由子系統(tǒng)和規(guī)劃子系統(tǒng)之間的通信信息是否加密進行決策。表10.7依據(jù)決策信息修改設(shè)計模型

通信子系統(tǒng)

通信子系統(tǒng)負責傳送來自規(guī)劃子系統(tǒng)和路由子系統(tǒng)的行程。通信子系統(tǒng)將司機與行程關(guān)聯(lián)起來,選擇一個密鑰對要通信的行程信息進行加密,再將行程傳送出去。規(guī)劃子系統(tǒng)

規(guī)劃子系統(tǒng)負責創(chuàng)建行程與目的地連接的一個序列。規(guī)劃子系統(tǒng)還負責對來自路由子系統(tǒng)的重新規(guī)劃請求做出反應(yīng)。在處理任何請求之前,規(guī)劃子系統(tǒng)要鑒別來自路由子系統(tǒng)的司機信息。通過鑒別的司機信息以確定哪個行程能夠被發(fā)送給對應(yīng)的路由子系統(tǒng)。

司機

一個司機信息表示需通過鑒別的用戶信息。該信息由通信子系統(tǒng)調(diào)用來記住與用戶關(guān)聯(lián)的密碼,由規(guī)劃子系統(tǒng)將行程關(guān)聯(lián)到用戶。我們需要為多用戶系統(tǒng)中的每個參與者定義一個共享對象,說明該對象的哪些操作可以供這些參與者訪問。例如,一個銀行出納員可以發(fā)布貸款,借出一定數(shù)量的金額。如果交易超出了預(yù)先定義的數(shù)目,交易必須由經(jīng)理批準才能通過。經(jīng)理可以訪問該分支的統(tǒng)計數(shù)據(jù),但是不能訪問其他分支的統(tǒng)計數(shù)據(jù)。分析員可以訪問跨越公司的所有分支信息,但是不能操作個人的帳戶交易信息。我們用訪問矩陣來對類的訪問控制進行建模。矩陣行表示系統(tǒng)中的參與者。矩陣列表示我們要進行控制訪問的類。訪問矩陣的一個條目元組(類,參與者)稱為訪問權(quán),它列出了參與者能夠在類實例上執(zhí)行的操作。對象參與者公司分支信息帳戶出納員postSmallDebit()postSmallCredit()examineBalance()經(jīng)理examineBranchState()postSmallDebit()postSmallCredit()postLargeDebit()postLargeCredit()examineBalance()examineHistory()分析師examineGlobalStats()examineBranchStats()表10.8一個銀行系統(tǒng)的訪問矩陣

訪問矩陣僅定義了靜態(tài)訪問控制。這就意味著訪問權(quán)限可以用系統(tǒng)對象的屬性來建模。在銀行信息系統(tǒng)的例子中,我們考察經(jīng)紀人參與者,該參與者被分配到證券集合中。由于存在規(guī)則,一個經(jīng)紀人不能訪問由其他經(jīng)紀人管理的證券。在這個例子中,我們需要對系統(tǒng)的訪問權(quán)限進行動態(tài)建模,這種類型的訪問稱為動態(tài)訪問控制。例如,圖10.20定義了這種訪問類型是如何采用代理設(shè)計模式實現(xiàn)的。對每一個部長職務(wù),我們都會創(chuàng)建一個部長職務(wù)代理來確保檢查訪問權(quán)限。為了訪問一個部長職務(wù),經(jīng)紀人向相應(yīng)的部長職務(wù)代理發(fā)出消息。如果發(fā)出調(diào)用請求的經(jīng)紀人存在與部長職務(wù)代理的正確訪問權(quán)限,部長職務(wù)代理將執(zhí)行相關(guān)檢查。如果訪問被同意,部長職務(wù)代理將為部長職務(wù)代理消息。否則,操作失敗。圖10.20一種采用了動態(tài)訪問控制代理模式的實例

4.全局控制流設(shè)計

控制流是指某個系統(tǒng)中的動作序列。在面向?qū)ο笙到y(tǒng)中,動作序列包括了應(yīng)該執(zhí)行哪些操作、以什么順序執(zhí)行這些操作。注意的控制流機制有三種:過程驅(qū)動控制;事件驅(qū)動控制;線程機制。一旦選擇了控制流機制,我們就能采用一個或多個控制對象集來實現(xiàn)它??刂茖ο蟮淖饔檬怯涗浲獠渴录?,存儲其有關(guān)狀態(tài),給出邊界上的操作調(diào)用和與外部事件相關(guān)聯(lián)的實體對象操作調(diào)用的正確順序。

5.標識邊界條件

我們需要對系統(tǒng)的邊界條件進行檢查,即決定系統(tǒng)如何啟動、如何初始化及如何關(guān)閉,此外我們還需要定義在數(shù)據(jù)發(fā)生故障和網(wǎng)絡(luò)斷開等情況下,如何處理失敗等。我們將負責處理這些條件的用例稱為邊界用例。例如,現(xiàn)在假設(shè)我們對如何讓車輛路程規(guī)劃系統(tǒng)工作在穩(wěn)定的狀態(tài)下,有了一個好主意。但是我們還沒有搞清楚車輛路程規(guī)劃系統(tǒng)是怎么被初始化的,具體而言,我們的問題有地圖是如何被加載到規(guī)劃服務(wù)中去的?車輛路程規(guī)劃系統(tǒng)又是如何被安裝到汽車上的?車輛路程規(guī)劃系統(tǒng)是怎么知道應(yīng)該連接到哪個規(guī)劃服務(wù)上呢?司機是怎么添加規(guī)劃服務(wù)的呢?在分析過程中,尚未標識出邊界用例,這一點是正常的。例如,一些系統(tǒng)管理功能可以從日常用戶的需求(如注冊、刪除用戶,管理訪問權(quán)限)中推知出來;而另一些功能則是從設(shè)計決策的結(jié)果(如高速緩存容量、數(shù)據(jù)庫服務(wù)器的位置和備份服務(wù)器的位置)。一般來說,我們是通過配置、啟動與關(guān)閉、異常處理等檢測每個子系統(tǒng)和每個持續(xù)性對象,以標識出邊界用例的。具體如下:

配置。對每一個持久性對象,我們檢查該持久性對象在哪個用例中被創(chuàng)建、銷毀(或存檔)。對那些不在任何一個一般用例中創(chuàng)建或銷毀的對象而言,我們需要增加一個由系統(tǒng)管理員調(diào)用的一個用例。由此可以根據(jù)配置信息得到邊界對象。啟動與關(guān)閉。對每一個構(gòu)件而言,我們增加三個用例來啟動、關(guān)閉和配置構(gòu)件。注意,單一用例可以管理多個彼此之間存在緊密耦合關(guān)系的構(gòu)件。異常處理。對于每一種類型的構(gòu)件失?。ɡ?,網(wǎng)絡(luò)中斷),系統(tǒng)的后續(xù)動作或如何進行反應(yīng)是由我們決定的。我們使用異常用例對這些決策進行文檔編寫,這些異常用例是對在需求獲取的過程中標識的一般用例進行擴展而得到的。需注意的是,當要容忍一次失敗的后果時,異常條件處理可能會導致系統(tǒng)設(shè)計的改變,而非僅僅是添加一個異常用例。一般來說,異常是發(fā)生在系統(tǒng)執(zhí)行過程中的一個事件或錯誤。導致不同異常的原因主要有三個:

硬件失敗。硬件老化和失敗。操作環(huán)境的改變。環(huán)境也影響了系統(tǒng)的工作方式。軟件失敗。可靠系統(tǒng)的開發(fā)是一個困難的話題。往往要對一些功能做出權(quán)衡,這樣才能夠使系統(tǒng)設(shè)計變得更簡單。在車輛路程規(guī)劃系統(tǒng)中,所做的假設(shè)是,源端、目的端的連接一直是可能的,并且在旅行中的通信問題是會影響旅程重新規(guī)劃的。例如在圖10.21中,我們更改了車輛路程規(guī)劃系統(tǒng)中包括邊界用例在內(nèi)的分析模型。特別地,我們增加了三個用例:第一,司機管理用例,用來增加、刪除和編輯司機信息;第二,地圖管理用例,用來增加、刪除和更新地圖以用來產(chǎn)生旅程信息;第三,服務(wù)管理用例,用來執(zhí)行例行的配置程序,啟動和關(guān)閉服務(wù)器。圖10.21管理車輛路程規(guī)劃系統(tǒng)

圖10.22車輛路程規(guī)劃系統(tǒng)中啟動服務(wù)用例

用例名稱

啟動服務(wù)

進入條件

1.規(guī)劃服務(wù)器管理員登錄到服務(wù)器。事件流

2.成功登錄后,規(guī)劃服務(wù)器管理員執(zhí)行啟動規(guī)劃服務(wù)命令。3.如果前一次規(guī)劃服務(wù)是正常關(guān)閉,服務(wù)器將讀取合法的司機列表、活動的旅程和地圖索引。如果規(guī)劃服務(wù)已經(jīng)崩潰,它將通知規(guī)劃服務(wù)器管理員,并對地圖數(shù)據(jù)庫存儲做一致性檢查。退出條件

4.規(guī)劃服務(wù)是可用的,并且等待來自路由助理的連接。6.評審系統(tǒng)設(shè)計

項目經(jīng)理和開發(fā)者需要組織一個評審過程來替代質(zhì)量改善活動。除了滿足系統(tǒng)設(shè)計時確定的設(shè)計目標外,我們還需要確保系統(tǒng)設(shè)計的正確性、完備性、一致性、可實現(xiàn)性和可讀性。具體如下:如果分析模型能夠被映射到系統(tǒng)設(shè)計模型上,則系統(tǒng)是正確的。以下問題可以確定系統(tǒng)設(shè)計是否正確:l

每一個子系統(tǒng)是否能夠被追溯到一個用例或一個非功能需求上?l

每一個用例是否能夠被映射到一個子系統(tǒng)的集合上?l

每一個設(shè)計目標是否能夠被追溯到一個非功能需求上?l

每一個非功能需求是否在系統(tǒng)設(shè)計模型中被很好的把握了?l

每一個參與者是否擁有其訪問策略?l

每一個訪問策略是否與非功能安全需求相一致?

如果每個需求和系統(tǒng)設(shè)計問題都被考慮到了,則系統(tǒng)模型是完備的。以下問題可以確定系統(tǒng)設(shè)計是否完備:

l

邊界條件是否已經(jīng)被處理?l

是否在系統(tǒng)設(shè)計中忽視了某個功能,存在由于對用例的考慮不夠而需再次標識用例的情況?l

是否所有的用例都被檢查過了,并且分配給了相應(yīng)的控制對象?l

是否把握住了系統(tǒng)設(shè)計的所有方面(即硬件分配、持久性存儲、訪問控制、遺留代碼和邊界條件)?l

是否所有的系統(tǒng)都有定義?

如果不含有任何的沖突,則系統(tǒng)模型是一致的。以下問題可以確定系統(tǒng)設(shè)計是否一致:

l

是否所有沖突的設(shè)計目標都劃分了優(yōu)先順序?l

是否有設(shè)計目標違反了非功能需求?l

是否存在多個子系統(tǒng)或類重名?l

子系統(tǒng)之間的對象集合是否以一種一致的方式進行交換?

如果對應(yīng)的系統(tǒng)能夠被實現(xiàn),則模型是可實現(xiàn)的。以下問題可以確定系統(tǒng)設(shè)計是否可實現(xiàn):

l

系統(tǒng)中是否包含新的技術(shù)或構(gòu)件?是否對這些技術(shù)或構(gòu)件的適合性或魯棒性做了評估?如何進行評估?l

在子系統(tǒng)分解的上下文中,性能需求與可靠性需求是否已經(jīng)被評審?l

并發(fā)問題(例如,競爭、死鎖)是否已被考慮?

如果沒有參與系統(tǒng)設(shè)計的開發(fā)者能夠理解模型,則系統(tǒng)模型是可讀的。以下問題可以確保系統(tǒng)設(shè)計是否可讀:

l

子系統(tǒng)名是否可理解?l

具有類似名稱的實體(例如,子系統(tǒng)、類)是否表示了類似的概念?l

是否所有的實體在同一細節(jié)層被描述?

10.2.5管理系統(tǒng)設(shè)計

1.系統(tǒng)設(shè)計文檔編寫

系統(tǒng)設(shè)計結(jié)論在系統(tǒng)設(shè)計文檔中撰寫。系統(tǒng)設(shè)計結(jié)論用項目、子系統(tǒng)分解(用UML類圖)、硬件/軟件映射(用UML部署圖)、數(shù)據(jù)管理、訪問控制、控制流機制和邊界條件描述設(shè)計目標集合等內(nèi)容來表示。系統(tǒng)設(shè)計文檔定義了開發(fā)團隊之間的接口,當體系結(jié)構(gòu)層的決策需重新考慮時,系統(tǒng)設(shè)計文檔又可以用作參考。系統(tǒng)設(shè)計文檔的讀者包括項目管理人員、系統(tǒng)體系結(jié)構(gòu)師(即參與系統(tǒng)設(shè)計的開發(fā)者)和設(shè)計并實現(xiàn)每個子系統(tǒng)的開發(fā)者。系統(tǒng)設(shè)計文檔大綱的示例

1.

介紹1.1

系統(tǒng)目標1.2

設(shè)計目標1.3

定義、首字母的縮寫詞和縮寫1.4

參考文獻1.5

概述2.當前軟件體系結(jié)構(gòu)3.建議軟件體系結(jié)構(gòu)

3.1

概述3.2

子系統(tǒng)分解3.3

硬件/軟件映射3.4

持久性數(shù)據(jù)管理3.5

訪問控制與保密性3.6

全局軟件控制3.7

邊界條件4.

子系統(tǒng)服務(wù)術(shù)語表系統(tǒng)設(shè)計文檔的第一部分是一些介紹。介紹的目的是提供一個簡要的軟件體系結(jié)構(gòu)及設(shè)計目標的概述。介紹還提供了對其他文檔的參考和追蹤的信息(例如,相關(guān)的需求分析文檔,對現(xiàn)存系統(tǒng)的參考,影響軟件體系結(jié)構(gòu)的約束等)。第二部分是當前軟件體系結(jié)構(gòu),描述了被替換系統(tǒng)的軟件體系結(jié)構(gòu)。如果不存在以前的系統(tǒng),這個部分可以用對類似系統(tǒng)的當前體系結(jié)構(gòu)來代替。這一部分內(nèi)容是為了弄清楚系統(tǒng)體系結(jié)構(gòu)師使用的背景信息、系統(tǒng)體系結(jié)構(gòu)師的假設(shè)和新系統(tǒng)將會遇到的一些通常的問題。

第三部分是建議的系統(tǒng)體系結(jié)構(gòu),對新系統(tǒng)的設(shè)計模型編寫文檔。這一部分可以分為七個子部分:

(1)概述給出軟件體系結(jié)構(gòu)的大體情況并簡明地描述了每個子系統(tǒng)上的功能分配情況。(2)子系統(tǒng)分解描繪了分解成多個子系統(tǒng)及每個子系統(tǒng)的職責。這是系統(tǒng)設(shè)計的主要產(chǎn)品。(3)硬件/軟件映射描述了子系統(tǒng)是如何分配到硬件和商業(yè)外購構(gòu)件上去的。硬件/軟件映射還列出了多個結(jié)點和軟件復(fù)用所帶來的問題。(4)持久性數(shù)據(jù)管理描述了存儲在系統(tǒng)中的持久性數(shù)據(jù)和它所需要的數(shù)據(jù)管理支撐基礎(chǔ)。這一部分主要包括數(shù)據(jù)模式的描述、數(shù)據(jù)庫選擇和數(shù)據(jù)庫封裝的描述。(5)訪問控制和安全根據(jù)訪問矩陣描述了系統(tǒng)的用戶模型。這一部分還描述了安全問題,例如標識機制的選擇、密碼術(shù)的使用和密鑰的管理等。(6)全局軟件控制描述了全局軟件控制是如何實現(xiàn)的。特別的是,這一部分應(yīng)該描述請求是如何被初始化及子系統(tǒng)是如何同步。這一部分應(yīng)該列舉并指出同步和并發(fā)問題。(7)邊界條件描述了系統(tǒng)啟動、關(guān)閉及其錯誤的行為(如果新的用例被系統(tǒng)管理員發(fā)現(xiàn),這些用例應(yīng)該被包含在需求分析文檔里面,而不應(yīng)該放在這個部分)。第四部分是子系統(tǒng)服務(wù),根據(jù)操作描述了每個子系統(tǒng)應(yīng)提供的服務(wù)。當完成了初始的系統(tǒng)分解之后,就應(yīng)該編寫系統(tǒng)設(shè)計文檔了;也就是說,系統(tǒng)體系結(jié)構(gòu)師不應(yīng)該等到系統(tǒng)設(shè)計決策做出后,再發(fā)布文檔。一旦做出了設(shè)計決策或發(fā)現(xiàn)了問題,系統(tǒng)設(shè)計文檔將在設(shè)計過程中更新。2.責任分配

復(fù)雜系統(tǒng)的系統(tǒng)設(shè)計主要由體系結(jié)構(gòu)團隊負責。這是由定義子系統(tǒng)分解的體系結(jié)構(gòu)師和將來實現(xiàn)子系統(tǒng)的開發(fā)者組成的功能交叉團隊。一旦分析模型趨于穩(wěn)定,體系結(jié)構(gòu)團隊就應(yīng)該開始工作了,并將持續(xù)發(fā)揮作用直到后期集成階段的完成。下面就是系統(tǒng)設(shè)計的主要角色:

體系結(jié)構(gòu)設(shè)計師是系統(tǒng)設(shè)計中的主要角色。體系結(jié)構(gòu)設(shè)計師確保設(shè)計決策和接口風格的一致。體系結(jié)構(gòu)設(shè)計師確保配置管理和測試團隊的設(shè)計一致,特別是配置管理策略和系統(tǒng)集成策略在形式上一致。體系結(jié)構(gòu)設(shè)計師是一個主要的集成角色,使用來自各個子系統(tǒng)團隊的信息。體系結(jié)構(gòu)設(shè)計師是功能交叉團隊的領(lǐng)導者。體系結(jié)構(gòu)聯(lián)絡(luò)員是體系結(jié)構(gòu)團隊的成員,他們代表各自的子系統(tǒng)團隊,負責為自己的團隊傳遞和反饋信息,協(xié)調(diào)接口的變化。在系統(tǒng)設(shè)計中,他們主要關(guān)注子系統(tǒng)服務(wù);在實現(xiàn)階段,他們注意關(guān)注應(yīng)用程序員接口(API)是否一致。其它成員還有文檔編輯員、配置經(jīng)理和評審者等。

3.系統(tǒng)設(shè)計交流

系統(tǒng)設(shè)計中所遇到交流方面的挑戰(zhàn),應(yīng)該比在分析中遇到的要小的多,但仍然存在,這反映在:

(1)規(guī)模。(2)更改。(3)抽象層。(4)不愿面對的問題。(5)目標和準則的沖突。我們在分析中所討論的技術(shù),可以用于系統(tǒng)設(shè)計,即:

為系統(tǒng)設(shè)計標識設(shè)計目標,并按優(yōu)先度排序,以顯式表示這些設(shè)計目標。對所有關(guān)注當前系統(tǒng)的分解版本的人來說,該分解版本應(yīng)該是可用的。維護最新的術(shù)語表。在分析過程中,顯式地定義術(shù)語可以減少誤解。面對設(shè)計問題。在提交設(shè)計決策之前,如果需要更多的信息,則延遲設(shè)計決策是有益的。迭代。在實現(xiàn)階段進行有選擇的迭代能夠改善系統(tǒng)設(shè)計。

4.系統(tǒng)設(shè)計中的迭代

由于連續(xù)的迭代和變更,系統(tǒng)設(shè)計會不斷發(fā)生。為了防止混亂,變更應(yīng)該得到控制,特別是在包含多個參與者的復(fù)雜項目中。在系統(tǒng)設(shè)計中,我們區(qū)分三種類型的迭代:第一,當系統(tǒng)設(shè)計中不同活動開始時候的迭代,第二,當創(chuàng)建了評估原型來對特定問題進行評估時候的迭代,這時的迭代會發(fā)生子系統(tǒng)接口改變。第三,在后期被發(fā)現(xiàn)的錯誤和疏漏時將會觸發(fā)子系統(tǒng)接口改變的迭代,這些迭代有時還會觸發(fā)子系統(tǒng)本身的改變。第一種迭代集最好是在集思廣益的會議上解決。第二種迭代的目的是解決困難的問題或倍受關(guān)注的問題,例如對特定供應(yīng)商或?qū)夹g(shù)進行選擇之類的問題。第三種迭代要解決這個過程的后期所發(fā)現(xiàn)的一些設(shè)計問題。10.3面向?qū)ο蟮膶ο笤O(shè)計

對象設(shè)計包括:

重用,即為了利用已有的解決問題方法,我們標識出商業(yè)外購構(gòu)件和設(shè)計模式;服務(wù)規(guī)格說明,即每一個類接口的精確描述對象模型重構(gòu),即改進對象設(shè)計模型,以提高可讀性和擴展性;對象模型優(yōu)化,即改進對象設(shè)計模型,以滿足性能標準。

與系統(tǒng)設(shè)計一樣,對象設(shè)計不涉及算法設(shè)計,而只是標識問題解決過程中起著舉足輕重作用的模式和構(gòu)件,我們將要討論這些構(gòu)造模塊以及與它們相關(guān)聯(lián)的活動。我們的重點集中在重用上,即如何來選擇構(gòu)件和設(shè)計模式應(yīng)用。10.3.1使用模式設(shè)計對象

在對象設(shè)計過程中,開發(fā)者負責填充分析過程中所定義的應(yīng)用程序?qū)ο笈c系統(tǒng)設(shè)計中標識出的軟硬件平臺之間存在的鴻溝。開發(fā)者除了標識出系統(tǒng)中正常的解對象外,還建立了一些自定義的解對象,以用來實現(xiàn)遺漏的功能。通常情況下,一個操作的調(diào)用者只會關(guān)注操作的非形式化說明、該操作對其它操作的影響,以及該操作的邊界情況等。為了準確使用一個操作,開發(fā)者需要根據(jù)約束條件構(gòu)造有關(guān)類、屬性、操作的精確規(guī)格說明。同樣地,開發(fā)者可以調(diào)整和重用那些有詳細接口說明的商業(yè)外購構(gòu)件。最后,開發(fā)者重構(gòu)和優(yōu)化對象設(shè)計模型,達到可維護性、可擴展性、效率、反應(yīng)時間、實時性等設(shè)計目標。10.3.2對象設(shè)計總論

系統(tǒng)設(shè)計通過兩個方面活動,以減少給定問題和機器實現(xiàn)之間存在的差距。一方面,系統(tǒng)設(shè)計會涉及比普通機器抽象層次更高的虛擬機器,這是通過購買活動來實現(xiàn)的,購買的內(nèi)容涉及中間件、用戶接口工具包、應(yīng)用程序框架和類庫之類的商業(yè)外購構(gòu)件。另一方面,系統(tǒng)設(shè)計標識出需要使用商業(yè)化構(gòu)件的應(yīng)用域中的對象。圖10.24對象設(shè)計填補了需求分析中標識的應(yīng)用對象和系統(tǒng)設(shè)計中所選擇的商業(yè)外購構(gòu)件之間的差異

圖10.25對象設(shè)計的四組活動

圖10.25說明了對象設(shè)計包括四組活動:(1)重用;(2)接口規(guī)格說明;(3)重構(gòu);(4)優(yōu)化。在系統(tǒng)重用設(shè)計過程中,需要標識實現(xiàn)每一個子系統(tǒng)的商業(yè)外購構(gòu)件。為了實現(xiàn)基本的數(shù)據(jù)結(jié)構(gòu)和功能服務(wù),開發(fā)者需要選擇所需的類庫和額外構(gòu)件。開發(fā)者通常選擇合適的設(shè)計模式來解決一般性問題,使得特定類在系統(tǒng)開發(fā)過程中不會發(fā)生變化??偟恼f來,構(gòu)件和設(shè)計模式需要在它們使用之前互相協(xié)調(diào)好。通過隱藏構(gòu)件和設(shè)計模式周圍的自定義對象或是通過使用繼承,以實現(xiàn)對抽象與求精的目的。在這些過程中,開發(fā)者將面臨是買構(gòu)件還是自己開發(fā)系統(tǒng)構(gòu)件這一選擇。在接口規(guī)格說明過程,在系統(tǒng)設(shè)計中標識子系統(tǒng)的功能都能在類接口中進行詳細說明,這包括操作、參數(shù)、類型規(guī)格說明和異常情況等內(nèi)容。這個過程中,我們標識了進行數(shù)據(jù)交換的子系統(tǒng)、傳遞操作以及對象。服務(wù)功能的規(guī)格說明會對每個子系統(tǒng)接口產(chǎn)生完整說明。這個子系統(tǒng)的功能說明通常被稱為子系統(tǒng)API。重構(gòu)活動通過系統(tǒng)模型利用軟件重用來增加代碼,或者是來滿足其它的設(shè)計目標。重構(gòu)活動可以看作對特殊模型子集的轉(zhuǎn)換過程。在重構(gòu)的過程中,我們主要是實現(xiàn)系統(tǒng)模型設(shè)計目標中的可維護性、可讀性以及可理解性。

優(yōu)化活動主要是實現(xiàn)系統(tǒng)模型中提出的性能要求。這個過程包括選擇更好的算法來提高系統(tǒng)執(zhí)行的速度;使用更好的存儲系統(tǒng);減少連結(jié)中的多樣性來提高查詢的速度;為了提高效率而增加額外的連結(jié)等。

對象設(shè)計過程并不是按照順序方式進行的,這些活動通常是并發(fā)進行的。通常先進行接口規(guī)格說明和重用活動,可產(chǎn)生一個對象設(shè)計模型,使用該模型檢查某個特定子系統(tǒng)的用例,即該子系統(tǒng)的功能。一旦該子系統(tǒng)的對象設(shè)計模型穩(wěn)定下來以后,接下來就可以進行重構(gòu)和優(yōu)化。不管怎樣,對象設(shè)計過程是一個迭代過程。

一旦設(shè)計模型構(gòu)造好了,就需要進行驗證和評審。通過驗證和評審之后,接下來我們就涉及如何將該模型到映射到代碼上。這時,我們要完成的主要工作是:

通過優(yōu)化活動,處理系統(tǒng)模型的性能需求。這包括減少關(guān)聯(lián),以加快查詢速度;添加冗余關(guān)聯(lián),以提高效率;添加導出屬性,以減少對象訪問時間。實現(xiàn)設(shè)計模型中的關(guān)聯(lián)。在這個活動中,我們將關(guān)聯(lián)映射到源代碼結(jié)構(gòu)上。將契約映射到異常。在這個過程中,我們描述了契約被違反時的操作行為。這包括發(fā)現(xiàn)事故時,產(chǎn)生異常和在系統(tǒng)更高層要處理的異常。將所設(shè)計的類模型映射到某一存儲模式。10.3.3重用中的概念:解對象、繼承和設(shè)計模式

1.應(yīng)用程序?qū)ο蠛徒鈱ο?/p>

類圖可以對應(yīng)用域和解域進行建模。應(yīng)用對象,也稱為域?qū)ο螅枋隽讼到y(tǒng)中的域概念。解對象描述了一組不包含應(yīng)用域概念的構(gòu)件,比如說持久數(shù)據(jù)存儲、用戶接口對象或是中間件。在對象設(shè)計中,我們對應(yīng)用對象和解對象進行求精和細化,并且標識了額外對象以填充對象設(shè)計與解對象之間存在的鴻溝。

2.定義繼承和實現(xiàn)繼承

在分析過程中,我們通過使用繼承概念對對象進行分類,這樣我們就可以得到兩種類。一種是超類或基類,用來描述一般類的共有行為;另一種是子類或?qū)С鲱?,用來描述特定對象的特有行為。在對象設(shè)計中,繼承的核心是為了減少冗余并增加擴展性。繼承機制對實現(xiàn)者而言是難以把握以的,因為使用了集成的緣故,很多新手寫出的代碼,與他們不用繼承機制相比,要更加混亂和不夠健壯。使用超類和從其繼承的特定子類可以減少類之間的耦合度,提高了效率。但是,這樣做會增加超類和子類在繼承層次上的耦合度。在圖10.26中,我們給出了UML類模型,總結(jié)了四種不同類型的繼承。圖10.26繼承元模型

3.授權(quán)當要求重用而使用繼承的時候,授權(quán)是一種可供選擇的辦法。A類授權(quán)B類是指A類為了完成一個操作需要向B類重發(fā)一個消息。使用授權(quán)可以把重用類和新類之間的依賴關(guān)系描述清楚。

4.Liskov替換準則Liskov準則能夠為接口的規(guī)格說明提供一個形式化的描述,其思想是:開發(fā)者通過增添新子類而不用對代碼做任何改變,就可以使用由某個父類提供的方法。5.設(shè)計模式中的授權(quán)和繼承

通常來說,什么時候使用授權(quán),什么時候使用繼承,并不能很清楚的判別出來,這需要開發(fā)者自己的判斷和以往開發(fā)經(jīng)驗的積累。繼承和授權(quán)如果結(jié)合起來使用,能夠解決很大范圍的問題:減少抽象接口的耦合度;把從基類中繼承的代碼封裝起來;減少說明服務(wù)類和提供服務(wù)機制類之間的耦合度。

10.4接口設(shè)計

系統(tǒng)設(shè)計的關(guān)注點在于標識可分配給單個團隊或單個開發(fā)者的大粒度構(gòu)件,而對象設(shè)計的關(guān)注點在于標識這些大粒度構(gòu)件中的各個對象及對象之間的接口。在系統(tǒng)底層細節(jié)迅速擴展的情況下,接口規(guī)格說明的關(guān)注點在于開發(fā)者是否依然能夠清楚和準確地進行交流。對象設(shè)計中接口描述活動包括:確定遺漏的屬性和操作;描述類型簽名和可見性;描述不變式;描述前置條件和后置條件。

我們將討論與接口規(guī)格說明有關(guān)的對象設(shè)計活動,具體內(nèi)容如下:提供了一個接口規(guī)格說明的綜述;定義了主要的接口規(guī)格說明概念,包括類型簽名、約束、協(xié)議,介紹了UML的對象約束語言;討論了接口規(guī)格說明的管理問題等。

10.4.1接口規(guī)格說明綜述

在系統(tǒng)開發(fā)的這一點上,我們做出了很多決策并產(chǎn)生很多的模型.但是所有的這些模型,只是反映了系統(tǒng)的部分視點。有很多問題被我們遺漏了,這些問題需要進一步求精。接口規(guī)格說明的目標是足夠清晰地描述每一個對象的接口,這樣就能通過單獨的開發(fā)者實現(xiàn)這些對象,以滿足最小集成的需要。為了達到這個目標,接口規(guī)格說明包括以下活動:標識遺漏的屬性和操作。標識可見性和簽名。定義契約。10.4.2接口規(guī)格說明概念

1.實現(xiàn)者、類擴展者和類使用者

我們需要根據(jù)開發(fā)者的觀點,區(qū)分不同的開發(fā)者:

(1)類實現(xiàn)者負責對有待實現(xiàn)的類進行實現(xiàn)。(2)類使用者在其它類的實現(xiàn)過程中,調(diào)用實現(xiàn)類所提供的操作。(3)類擴展者對實現(xiàn)類進行了特定擴展。圖10.27類實現(xiàn)者、類擴展者以及類使用者的角色

2.類型、簽名和可見性

在對象設(shè)計中,我們通過給出完整的類型和可見性信息,對分析和系統(tǒng)設(shè)計模型進行求精。屬性的類型說明了這個屬性可以取值的范圍,以及該屬性能夠進行的操作。操作參數(shù)和返回值也需要確定類型。類型約束了參數(shù)或返回值可取值范圍。一個給定操作、符合要求的參數(shù)和返回值類型的元組,稱為操作的簽名。比如說:系列賽對象的接收選手操作acceptPlayer()需要一個Player類型的參數(shù),并且該操作沒有返回值。那么操作acceptPlayer()的簽名就是acceptPlayer(Player):void。系列賽對象中的getMaxNumPlayers()操作沒有參數(shù),并返回一個整型值,那么getMaxNumPlayers()操作的簽名就是getMaxNumPlayers(void):int。

類實現(xiàn)者、類使用者和類擴展者都需要訪問類的操作和屬性。但是三者的訪問范圍各有不同。例如,一個類實現(xiàn)者能夠訪問類的內(nèi)部數(shù)據(jù)結(jié)構(gòu),而這些信息對類使用者來說通常是不可見的。類擴展者僅僅是有選擇地訪問超類中的一些內(nèi)部結(jié)構(gòu)。

3.契約:不變式、前置條件和后置條件

契約就是在一個類上定義的、確保有關(guān)該類的類實現(xiàn)者、使用者、擴展者都要遵守的假設(shè)條件。一個契約說明了類使用者在使用該類之前必須遵守的約束,這一約束也是類實現(xiàn)者和類擴展者在實現(xiàn)和使用時必須遵守的約束。

契約包括三種類型的約束,具體說明如下:(1)不變式。不變式是一個對該類的所有實例都為真的謂詞。不變式是和類或接口有關(guān)的約束。不變式通常用來說明類屬性之間的一致性約束。(2)前置條件。前置條件是在調(diào)用一個操作之前必須為真的謂詞。前置條件和某個特定操作有關(guān)。前置條件用來說明類使用者在調(diào)用一個操作之前必須滿足的約束。(3)后置條件。后置條件是在調(diào)用一個操作之后必須為真的謂詞。后置條件和某個特定操作有關(guān)。后置條件用來說明類實現(xiàn)者和類擴展者在調(diào)用一個操作之后必須滿足的約束。在系列賽類中有一個增加選手的方法acceptPlayer(),有一個取消選手的方法removePlayer()和一個取得參加選手的最大數(shù)目的方法getMaxPlayers()。

系列賽類中存在這樣一個不變式:即確保系列賽類中選手的最大數(shù)目應(yīng)該為正數(shù)。在構(gòu)造一個系列賽對象t的時候,如果所設(shè)定的最大選手數(shù)目為0的話,那么使用acceptPlayer()方法將違反該操作的契約,因為任意增加一個選手的話,都會破壞最大選手數(shù)目為0的條件,因此應(yīng)該設(shè)定最大選手數(shù)目為正數(shù)。我們可以將這個不變式表述為t.getMaxPlayers()>0。

acceptPlayer()方法適用的前置條件的例子是:如果一名選手希望參加系列賽,那么該選手在申請之前,應(yīng)確保沒有加入到該系列賽中,并且在該選手加入系列賽時,該系列賽所能容納選手的最大上限沒有達到。我們使用一個布爾表達式描述該不變式,其中t代表一個系列賽,p代表一個選手:!t.isPlayerAccepted(p)andt.getNumPlayers()<t.getMaxNumPlayer()。

acceptPlayer()方法適用的后置條件的例子是:在使用accpetPlayer()方法之后,當前選手Players的數(shù)目必須比調(diào)用該函數(shù)之前的選手數(shù)目多一個。我們把這個后置條件表述為:t.getNumPlayers_afterAccept=t.getNumPlayers_beforeAccept+1。在此,getNumPlayers_afterAccept表示在調(diào)用acceptPlayer()方法之后的選手數(shù)目,getNumPlayers_beforeAccept表示在調(diào)用acceptPlayer()方法之前的選手數(shù)目。通過使用不變式、前置條件、后置條件,我們清楚地說明規(guī)格說明的邊界條件以及所期望的情況。

4.對象約束語言

我們可以通過對象約束語言(ObjectConstraintLanguage,OCL)的形式來描述一個約束。OCL是一種允許在單個模型元素(例如,屬性、操作、類)和模型元組上(例如,關(guān)聯(lián)和參與類)對約束進行形式化說明的語言。一個約束可描述為返回值為真或為假的布爾表達式。一個約束可描述成通過依賴關(guān)系關(guān)聯(lián)到一個受約束的UML元素的說明。下圖使用UML和OCL描述了在以前章節(jié)中提到的系列賽例子的一個類圖。圖10.28OCL中不變式、前置條件和后置條件的例子

我們選擇使用文本形式描述OCL表達式。例如系列賽中的最大選手數(shù)目屬性為正數(shù)的不變式描述如下:contextTournamentinv:self.getMaxNumPlayers()>0。

context關(guān)鍵字表明該表達式所適用的實體。context關(guān)鍵字后面可以是關(guān)鍵字inv、pre和post中的一個,這與UML的<<invariants>>,<<precondition>>,<<postcondition>>是分別對應(yīng)的。然后就是實際的OCL表達式。但是,由于OCL不是一個過程型語言,因此不能用來表示控制流。對于不變式而言,表達式中的上下文表明了與該不變式相關(guān)聯(lián)的類。關(guān)鍵字self(例如,self.numElements)表示該類的所有實例。我們可以使用點號訪問屬性和操作。例如,使用self.maxNumPlayers訪問當前上下文中的maxNumPlayers屬性。在沒有歧義的情況下,self關(guān)鍵字也可以省略。對于前置條件和后置條件,OCL表達式的上下文就是一個操作。傳遞給操作的參數(shù),可以用做表達式中的變量。舉例來說,考慮到下述作用于系列賽中acceptPlayer()操作的前置條件:contextTournament::acceptPlayer(p)pre:!isPlayerAccept(p)。

在約束!isPlayerAccept(p)中用到的變量p,表示傳遞給acceptPlayer()的操作參數(shù)為p。由于該約束是一個前置表達式,因此這個約束在acceptPlayer()操作執(zhí)行之前必須為真。這個約束可以用自然語言可以表達為“acceptPlayer(p)假設(shè)p以前沒有參與過系列賽”。我們可以為同一個操作寫很多前置條件。如果一個給定操作的前置條件不止一個,那么該操作所有的前置條件在其被調(diào)用之前都必須是為真的。例如,我們可以描述系列賽在調(diào)用acceptPlayer()之前,選手數(shù)目沒有達到最大數(shù)目:contextTournament::acceptPlayer(p)pre:getNumPlayers()<getMaxNumPlayers()后置條件的寫法和前置條件是一樣的,除了所使用的關(guān)鍵字是post這一點不同之外,后置條件表示要描述的這個約束是在操作返回后為真。例如,下述作用于acceptPlayer(P)的后置條件說明選手p在acceptPlayer()調(diào)用之后對于系列賽而言是可知的:contextTournament::acceptPlayer(p)post:isPlayerAccpted(p)。對后置條件,我們通常需要知道在某個屬性的一個操作執(zhí)行前后的值。為了達到這個目的,后綴@pre表示self是某個屬性在某個操作執(zhí)行之前的值。例如,如果我們想說明在調(diào)用acceptPlayer()之后,系列賽中的選手值增加了一個,我們需要知道在調(diào)用acceptPlayer()操作前后的getNumPlayers()方法的返回值。我們可以寫如下后置條件:contextTournament::acceptPlayer(p)post:getNumPlayers()=@pre.getNumPlayers()+1@pre.getNumPlayers()表示在調(diào)用acceptPlayer()之前由getNumPlayers()得到的值,getNumPlayers()表示的是,在調(diào)用了acceptPlayer()操作之后,由該操作的返回值。和前置條件一樣,如果這里對一個操作有多于一個的后置條件,在該操作執(zhí)行完畢之后,所有的后置條件都必須滿足。因此,使用同樣的方法,我們可以將removePlayer()操作的契約寫出來:contextTournament::removePlayer(p)pre:isPlayerAccepted(p)contextTournament::removePlayer(p)post:!isPlayerAccepted(p)contextTournament::removePlayer(p)post:getNumPlayers()=@pre.getNumPlayers()-1。

10.4.3接口規(guī)格說明活動

1.標識遺漏的屬性和操作

我們檢查子系統(tǒng)提供的服務(wù)描述,并且標識遺漏的屬性和操作。2.說明類型、簽名和可見性說明類型可以從兩個方面對對象設(shè)計模型進行求精。首先,我們通過說明每一個屬性的取值范圍,以增加模型細節(jié)。其次,我們把對象模型的類和屬性映射到由開發(fā)環(huán)境提供的類型上。最后,我們標識每一個操作和屬性的可見性。3.說明前置條件和后置條件

我們?yōu)槊總€類的所有公有操作定義了契約。契約就是存在于類使用者和類實現(xiàn)者之間的一個協(xié)議。一個操作的前置條件描述了類使用者必須遵守的那部分契約,后置條件描述了類使用者在遵守相關(guān)部分契約之后,類實現(xiàn)者應(yīng)該保證相關(guān)操作能夠正確執(zhí)行,且在執(zhí)行后契約得到滿足。

4.說明不變式不變式的撰寫比前置條件和后置條件的撰寫要困難很多。標識不變式的活動與在分析中找抽象類的過程相似。僅有很少不變式是很明顯的,而且

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論