摘要:該文深入研究了用例模型中用例之間的關系:包含、擴展、泛化。從事件流的細節剖析了用例關系的執行過程,顯示了他們的本質特征。給出了具體的描述方式。并給出了具體的實例。
關鍵詞:UML建模;用例模型;用例間關系
中文分類號:TP309 文獻標識碼:A 文章編號:1009-3044(2009)35-9988-03
Research on Relationship among the Use Cases in UML
ZOU Ping-xiang
(Xinshao County, Hunan Province industrial vocational school,Xinshao 422900,Hunan)
Abstract: In this paper, we research the relationship of use case in model of use case: include, extension, generalization. Analyze the execution of a process from event flow. Show their character in essence. Give some description on relationship of use case, and list some concrete instance.
Key words: modeling of UML; model of the use case; relation of the use case
通常我們構建用例模型有三個主要的原因: 1) 使用例(use case)更易于理解。2) 將在許多用例內說明的公有行為分離出來。3) 使用例模型更易于維護。 基于以上的需求,我們有三種關系(包含、擴展、繼承)可以用于構建用例。可以用這些關系來分析出用例部件,這些部件可以在其他用例中復用,也可以作為該用例的特例或選項。
1)如果基本用例中有一部分功能,該基本用例的執行與否由這部分功能的結果唯一決定,而不是由產生該結果的方法來決定,則可以將這一部分功能分離出來,放到一個包含用例中。采用包含關系,可以將包含用例顯式的插入基本用例中。
2)如果基本用例的一部分是可選的,或對于理解該基本用例的主要目的來說不是必需的,那么可以將這部分功能分離出來,形成一個擴展用例,以簡化基本用例的結構。利用擴展關系,可以將擴展用例隱式的插入基本用例中。
3)如果用例在行為和結構上具有共同點而且在目的上又很相似,則可以將它們的共同部分分離出來,形成一個父用例(基本用例)。而子用例可以繼承該父用例。子用例可以在從父用例繼承的結構中插入新的行為或修改現有的行為。
1 包含關系
包含關系是從基本用例到包含用例的關系,它指定如何將為包含用例定義的行為明確地插入到為基本用例定義的行為中。
1.1 解釋
基本用例通過包含關系連接到包含用例,包含用例總是抽象的。它描述在執行基本用例的用例實例中插入的行為段。基本用例可控制與包含用例的關系,并可依賴于執行包含用例所得的結果,但基本用例和包含用例都不能訪問對方的屬性。從這種意義上講,包含用例是被封裝的,它代表可在各種不同基本用例中復用的行為。[1]我們可以將包含關系用于:
1)從基本用例中分解出這樣的行為:它對于了解基本用例的主要目的并不是必需的,只有它的結果才比較重要。
2)分解出兩個或更多用例所共有的行為。 [2]
一個基本用例可以有多個包含用例。一個包含用例可以包含在若干基本用例中。這并不表示這些基本用例之間存在任何關系。甚至同一個包含用例和同一個基本用例之間可以有多個包含關系,前提是包含用例必須在基本用例中的不同位置插入,而包含關系就定義了插入的位置。添加的所有用例都可以是嵌套的,這意味著一個包含用例可以用作另一個包含用例的基本用例。由于包含用例是抽象的,因此它不需要有與它相關的主角。只有當包含用例中的行為明確地涉及到與主角的交互時,才需要與主角的通信關聯關系。
1.2 執行包含
包含用例的行為插入到基本用例中的一個位置。當遵循基本用例說明的用例實例到達基本用例中定義了包含關系的位置,它就將改而遵循包含用例的說明。一旦執行完包含用例,用例實例就將在基本用例中它先前停止的地方重新開始。[1]包含關系是無條件的:如果用例實例到達基本用例中定義了包含關系的位置,就總會執行包含。如果要表達條件,就需要將其作為基本用例的一部分來表達。如果用例實例無論如何也不能到達定義了包含關系的位置,則不會執行包含。
包含用例是一個連續的行為段,所有這些行為都包含在基本用例的一個位置中。如果我們需要將一些行為段分別插入不同位置,就應考慮使用擴展關系或用例泛化關系。
1.3 描述包含關系
對于包含關系,我們應在基本用例的行為序列中定義要插入包含用例的位置。要定義該位置,可以引用基本用例事件流中的特定步驟或分支流。為清晰起見,還應在描述基本用例事件流文本中提及包含用例。
2 擴展關系
擴展關系是從擴展用例到基本用例的關系,它說明為擴展用例定義的行為如何插入到為基本用例定義的行為中。它是以隱含形式插入的,也就是說,擴展用例并不在基本用例中顯示。
2.1 解釋
擴展關系將擴展用例與基本用例連接了起來。通過在基本用例中引用擴展點,可以定義在基本用例的哪些位置插入擴展用例。擴展用例通常是抽象的,但并不必須如此。[2]我們可以出于以下幾個目的使用擴展用例:
1) 表明用例的某一部分是可選(或可能可選)的系統行為。這樣,我們就可以將模型中的可選行為和必選行為分開。
2) 表明只在特定條件(有時是例外條件)下才執行分支流,如觸發警報。
3) 表明可能有一組行為段,其中的一個或多個段可以在基本用例中的擴展點處插入。所插入的行為段(以及插入的順序)將取決于在執行基本用例時與主角進行的交互。
擴展是有條件的,它是否執行取決于在執行基本用例時所發生的事件。基本用例并不控制執行擴展的條件:這些條件在擴展關系中進行說明。擴展用例可以訪問和修改基本用例的屬性。但基本用例看不到擴展用例,也無法訪問它們的屬性。[1]擴展用例以隱含的方式修改基本用例。也就是說,基本用例定義了可以在其中添加擴展用例的模塊化框架,但基本用例看不見特定的擴展用例。基本用例自身應是完整的,即基本用例應該是可理解且有意義的,而不必引用任何擴展用例。但基本用例并不獨立于擴展用例,因為如果無法遵循擴展用例,就不能執行基本用例。如果基本用例和“基本加擴展”用例都必須是可以直接實例化的,或者如果我們希望通過添加來修改基本用例中的行為,則應使用用例泛化關系。
擴展用例可以包含一個或多個插入段,每個插入段都可以有內置的備選路徑。這些插入段以遞增方式修改基本用例的行為。擴展用例中的每個插入段可以插入到基本用例中的不同位置。這意味著擴展關系包括一系列對擴展點的引用,引用的數量與擴展用例中插入段的數量相等。每個擴展點都必須在基本用例中定義。
一個基本用例包含若干擴展關系,這意味著一個用例實例在其生命期內可以遵循多個擴展用例。一個擴展用例可以擴展到幾個基本用例中,但這并不意味著這些基本用例之間存在依賴關系。同一個擴展用例和同一個基本用例之間甚至可以有多個擴展關系,前提是擴展用例必須在基本用例的不同位置插入。這意味著不同的擴展關系需要引用基本用例中的不同擴展點。擴展用例自身可以是擴展、包含或泛化關系中的基本用例。例如,擴展用例能夠以嵌套方式擴展其他的擴展用例。
2.2 執行擴展
當執行基本用例的用例實例達到基本用例中定義擴展點的位置時,將對相應擴展關系的條件進行評估。如果條件成立,或者如果沒有條件,用例實例將遵循擴展用例(或者擴展用例中與擴展點相對應的插入段)。如果擴展關系的條件不成立,就不執行擴展。就像所有用例一樣,擴展用例可以有基本事件流和備選事件流。用例實例通過擴展到底會采取哪條路徑,這不僅取決于在執行之前發生的事件(用例實例的狀態),而且還取決于執行擴展時在與主角的交互中發生的事件。用例實例一旦執行了擴展,它就會在基本用例的中斷點處繼續執行基本用例。(如圖3)
一個擴展用例可以有多個插入段,每個插入段都與自己在基本用例中的擴展點相關。在這種情況下,用例實例將繼續執行基本用例,并持續到擴展關系中指定的下一個擴展點為止。在此點上,它將執行擴展用例的下一個插入段。這會重復進行,直到執行完最后一個插入段為止。請注意,只在第一個擴展點對擴展關系的條件進行檢查;如果條件成立,用例實例就必須執行所有插入段。(如圖4)
擴展關系的多重性將約束整個擴展用例可以重復發生的次數。注意,在這里所重復(并受多重性限制)的是整個擴展用例,而不僅僅是一個插入段。
2.3 記錄擴展關系
按照基本用例的屬性來說明擴展的條件。另外,我們也可以選擇省略該條件,這時將總是執行擴展。每一擴展關系都有一系列對基本用例中擴展點(一個或多個)的引用。擴展點是按名稱引用的。如果擴展用例具有多個插入段,就需要指定哪個段與哪個擴展點相對應。另外,還需要說明形成各個插入段的擴展用例步驟或分支流。
示例:在電話系統中,可以由抽象的用例“顯示呼叫方身份”來擴展用例“打電話”。這是一項可選服務,通常稱為“呼叫方 ID”,接收方可能已請求該服務,也可能還未請求。可能會如下說明從“顯示呼叫方身份”到“打電話”的擴展關系:
條件:接收方必須已經預定“呼叫方 ID”服務。
擴展點:顯示身份 - 插入整個用例。
我們可以向擴展關系賦予多重性,如果省略多重性,則假定多重性為一。
3 用例泛化關系
用例泛化關系指一種從子用例到父用例的關系,它指定了子用例如何特化父用例的所有行為和特征。
3.1 解釋
父用例可特化形成一個或多個子用例,子用例代表父用例比較特殊的形式。盡管在大多數情況下父用例是抽象的,但并不要求一定是抽象的。子用例繼承父用例的所有結構、行為和關系。同一父用例的子用例都是該父用例的特例。這就是可適用于用例的泛化關系。[2]當我們發現兩個或更多用例在行為、結構和目的方面存在共性時,就可以使用泛化關系。這時,我們可以用一個新的、抽象的用例來描述這些共有部分,該用例隨后被子用例特化。 [3]
子用例依賴于父用例的結構。子用例可以將附加行為添加到父用例中。雖然子用例可以從父用例繼承行為段,但是必須慎重修改,以便保持父用例的使用目的。父用例的結構由子用例保持。這意味著盡管所有行為段(即父用例事件流的步驟或分支流)仍然必須存在,但是這些行為段的內容可以被子用例修改。
如果父用例為抽象用例,則它可以具有不完整的行為段。但是,子用例必須補充完善這些行為段,并使得它們對于主角而言是有意義的。如果父用例是一個抽象用例,則它無需與主角發生關系。如果兩個子用例都對同一父用例(或基本用例)進行特化,則二者之間的特化是相互獨立的,這意味著它們可以在各自獨立的用例實例中執行。這與包含關系和擴展關系不同。在包含和擴展關系中,一些附加用例隱式或顯式地修改了執行相同基本用例的一個用例實例。
用例的泛化關系和包含關系都可以用來復用該模型用例間的行為。二者的區別是,在用例泛化關系中,執行子用例不受父用例的結構和行為(復用部分)的影響;而在包含關系內,執行基本用例只依賴包含用例(復用部分)執行有關功能的結果。另一個區別是,在泛化關系中,子用例有相似的目的和結構;而在包含關系中,復用相同包含用例的基本用例在目的上可以完全不同,但是它們需要執行相同的功能。
3.2 執行用例泛化關系
執行子用例的用例實例將遵循父用例事件流,同時插入附加行為或修改在子用例事件流中定義的行為。
3.3 描述用例泛化關系
通常,可以不用描述泛化關系本身。相反,在子用例事件流中,我們必須指定如何將新步驟插入到繼承行為中以及怎樣去修改繼承行為。如果子用例特化了不止一個父用例(多繼承),則必須在子用例的規約中明確說明父用例的行為序列如何在子用例中交替執行。
4 總結
運用用例的三中關系(包含、擴展、泛化)可以充分的描述用戶的需求以及需求之間的關系。但要注意應當與客戶和用戶不斷地深入討論如何合并包含、擴展和泛化關系,并確信他們對產生的用例和主角有清楚的理解和認識,并且對有關說明形成一致意見。這樣捕獲的需求才是真正用戶需要的需求。
參考文獻:
[1] Grady B.UML用戶指南[M].北京:機械工業出版社,2008.
[2] 蔣惠.UML設計核心技術[M].北京:北京希望電子出版社,2007.
[3] Meilir J.UML面向對象設計基礎[M].北京:人民郵電出版社,2007.
[4] James R.UML參考手冊[M].北京:機械工業出版社,2006.