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