Applying UML and Patterners(Third Edition)學習筆記(十一)
Posted on 2010-08-30 00:39 啥都寫點 閱讀(446) 評論(0) 編輯 收藏 所屬分類: 軟件工程-
目標:1》定義系統操作2》為系統操作創建契約
簡介 在UP中,用例和系統特性是用來描述系統行為的主要方式,并且足以滿足要求。有時需要對系統行為進行更為詳細和精確的描述。操作契約使用前置和后置條件的形式,描述領域模型里對象的詳細變化,并作為系統操作的結果。領域模型是最常用的OOA模型,但是操作契約和狀態模型也能夠作為有用的與OOA相關的制品。 操作契約可以視為UP用例模型的一部分,因為它對用例指出的系統操作的效用提供了更詳細的分析。圖11-1所示的UP制品的相互影響強調了操作契約。該契約的主要輸入時SSD中確定的系統操作、領域模型和領域專家的見解。該契約也可以作為對象設計的輸入,因為他們描述的變化很可能是軟件對象或數據庫所需要的。
示例 下面給出的是系統操作enterItem的操作契約。其中的關鍵元素是后置條件,其他部分雖然有用但重要性稍低。
契約CO2:enterItem
操作:enterItem(itemID:ItemID,quantity:integer)
交叉引用:用例 : 處理銷售
前置條件:正在進行的銷售
后置條件:1》創建了SalesLineItem的實例sli(創建實例)。2》sli與當前Sale關聯(形成關聯)3》sli.quantity賦值為quantity(修改屬性)4》基于itemID的匹配,將sli關聯到ProductDescription(形成關聯)
“(創建實例)”這樣的分類是為了幫助學習,并不是契約的有效部分。
定義:契約有哪些部分 下面對契約中的每個部分進行了描述:
操作:操作的名稱和參數
交叉引用:會發生此操作的用例
前置條件:執行操作之前,對系統或領域模型對象狀態的重要假設。這些假設比較重要,應該告訴讀者。
后者條件:最重要的部分。完成操作后,領域模型對象的狀態。后續章節將詳細描述這個問題。
定義:什么是系統操作 可以為系統操作定義操作契約,系統操作時作為黑盒構件的系統在其公共接口中提供的操作。系統操作可以在繪制SSD草圖時確定,如圖11-2。更精確地講,SSD展示了系統事件,即涉及系統的事件或I/O消息。輸入的系統事件意味著系統具有用來處理事件的系統操作,正如OO消息(一種事件或信號)要由OO方法(一種操作)來處理那樣。 涉及所有用例的系統操作的完整集合將系統視為一個構件或類,定義了公共的系統接口。在UML中,作為整體的系統可以表示成名稱為(例如)System的類的一個對象。
定義:后置條件 后置條件(postcondition)描述了領域模型內對象狀態的變化。領域模型狀態變化包括創建實例、形成或消除關聯以及改變屬性。 后置條件不是在操作過程中執行的活動,相反,它們是對領域模型對象的觀察結果,當操作完成后,這些結果為真,就像濃煙散去后所能夠清晰看到的事物。 概括說來,后置條件可以分為以下三種類型:(1》創建或刪除實例 2》屬性值的變化 3》形成或消除關聯(精確地講,是UML鏈接))。消除關聯比較少見。刪除實例的后置條件也十分少見,因為人們通常不會關心明確強制銷毀現實世界中的事物。
后置條件如何與領域模型相關 這些后置條件主要是在領域模型對象的語境中表示的。可以創建什么實例?(來自于領域模型)可以形成什么關聯?(來自于領域模型),等等。
動機:為什么需要后置條件 首先,后置條件并不總是必要的。在大多數情況下,系統操作的效果對開發者而言是相對清晰的,他們可以通過閱讀用例、與專家交流或根據自己的知識對此進行理解。但有時需要更詳細和精確的描述。契約正提供了此類描述。注意,后置條件支持細粒度的細節和精確性,以聲明操作必須具備的結果。在用例中也可以表示為這種詳細級別,但并不適宜,因為過于冗長和詳細。契約是優秀的需求分析或OOA工具,能夠詳細描述系統操作(就領域模型對象而言)所需的變化,而不需描述這些操作是如何完成的。換言之,設計可以被延遲,我們可以重點分析必須發生的事物,而不是如何實現這些事物。
準則:如何編寫后置條件 用過去時態表達后置條件,以強調它們是由操作引起的狀態變化的觀察結果,而不是發生的活動。這也是后置條件名稱的由來!例如 (較好)創建了SalesLineItem 而不是 (較差)創建SalesLineItem或SalesLineItem被創建。
準則:后置條件因該完善到何種程度?敏捷與重量級分析 契約有可能是無用的。這一問題將在后續章節中討論。但是假設契約有用,則為所有系統操作生成完整詳細的后置條件集合是不可能的,或是沒有必要的。就敏捷建模的本質而言,只是將其視為初始最佳的猜測,在這種理解下,詳盡的后置條件是無法完成的,而所謂“完善”的規格說明也是幾乎不可能的或不可信的。但是要理解,進行輕量的分析是現實和有效的,這并不是意味著要在編程前放棄任何調查,這又是另一種極端的誤解。
示例:enterItem的后置條件 以下內容剖析了enterItem系統操作后置條件的動機。
創建和刪除實例 輸入itemID和商品項目的quantity后,會創建哪些新對象?SalesLineItem。因此:
- 創建了SalesLineItem的實例sli(創建實例)。
注意對實例的命名。該名字簡化了在其他后置條件語句中對該新實例的引用。
屬性修改 在收銀員輸入商品項目標識和對應的商品數量后,應該修改了哪些新對象或現有對象的屬性?SalesLineItem的quantity應該變為等于quantity參數。因此
- sli.quantity賦值為quantity(修改屬性)
準則:是否應該更新領域模型 通常在創建契約的過程中會發現,需要在領域模型中記錄新的概念類、屬性或關聯。不要局限于先前定義的領域模型,當你在思考操作契約過程中有新發現時,要對領域模型進行改進。在迭代和進化式方法中(并且反映了軟件項目的真是情況),所有分析和設計制品都不是完善的,要根據新發現對其改進。
準則:契約在何時有效 在UP中,用例是項目需求的主要知識庫。用例可以為設計提供大部分或全部所需細節。這種情況下,契約就沒有什么作用。但有時對于用例而言,所需狀態變化的細節和復雜性難以處理或過于細節化。如果開發者在沒有操作契約的情況下,能夠準確地理解所需要完成的工作,則可以不編寫契約。
準則:如何創建和編寫契約 創建契約時可以應用以下指導:1》從SSD中確定系統操作。2》如果系統操作復雜,其結果可能不明顯,或者在用例中不清楚,則可以為其構造契約。3》使用以下幾種類別來描述后置條件:1》創建和刪除實例。 2》修改屬性 3》形成清除關聯。
編寫契約
- 如上所述,以說明性的、被動式的過去時態編寫后置條件,以便強調變化的觀察結果,而非其如何實現的設計。例如:(較好)創建了SalesLineItem。 (較差)創建SalesLineItem。
- 記住,要在已有或新創建的對象之間建立關聯。例如,當enterItem操作發生時,僅創建SalesLineItem的實例是不夠的。操作完成后,還應該將此信創建的實例與Sale關聯。因此: 將SalesLineItem與Sale關聯(形成關聯)。
最常見的錯誤 最常見的問題是遺漏了關聯的形成。特別是當創建了新實例時,通常需要建立與若干對象的關聯。不要遺忘這一點!
應用UML:操作、契約和OCL UML正式地定義了操作(operation)。引證如下:操作是可以調用對象執行的轉換或查詢的規格說明。例如,在UML中,接口元素就是操作。操作是抽象而非實現。相比之下,方法是操作的實現。引證如下:操作的實現。它規定了與操作關聯的算法或過程。在UML元模型中,操作具有特征標記,在這種語境中最為重要的是,與一組UML約束對象關聯,這些對象被分類為指定操作語義的前置條件和后置條件。概括一下,UML通過約束定義操作的語義,這些約束可以用前置或后置的形式指定。要注意,本章強調UML操作的規格說明不能表示算法或解決方案,而只能是狀態的變化或操作的效果。契約除了用于指定整個System(也就是說,系統操作)的公共操作外,還能夠用于任何粒度的操作:子系統的公共操作(或接口)、構件、抽象類等。例如,可以為Stack這樣的單個軟件類定義操作。本章討論的粗粒度操作屬于將整個系統作為黑盒構件的System類,但是UML操作可以屬于任何類或接口,它們都具有前置和后置條件。
用OCL表示的操作契約 本章中的前置后后置條件的格式是非正式的自然語言格式,完全可以被UML接受,并易于理解。但UML還具有正式、嚴謹的語言,成為對象約束語言(OCL),OCL可以用來表示UML操作的約束。準則:除非有不可避免的實際原因要求人們學習和使用OCL,否則要保持簡單并使用自然語言。盡管我確信存在真實(且有效)的應用,但我從未見過使用OCL的項目,即便我調查了大量客戶和項目。
過程:UP的操作契約 前置和后置條件契約式UML指定操作的常用風格。在UML中,操作在許多級別中存在,從System到細粒度的類。系統級別的操作契約式用例模型的一部分,盡管原始的RUP或UP文檔中并沒有正式地強調這一點。RUP作者證實了用例模型中包括操作契約。
階段 初始--初始階段不會引入契約,因為過于詳細。 細化--如果使用契約的話,大部分契約將在細化階段進行編寫,這時已經編寫了大部分用例。只對最復雜和微妙的系統操作編寫契約。
-- 學海無涯