程序員眼中的UML(4)
--類圖釋疑之一,Attribute和Property之區(qū)別
上一篇中提出了很多問題,其中最令人費(fèi)解的可能就是Attribute和Property之區(qū)別了吧。我在網(wǎng)絡(luò)上尋找良久也沒有發(fā)現(xiàn)好的解釋,反而發(fā)現(xiàn)了很多混亂的解釋和用法。因此,依靠OMG網(wǎng)站上的UML規(guī)范以及自己的理解,整理出了這篇文章。
UML中的Attribute和Property之區(qū)別
在很多人的腦海中,Attribute就是類的屬性,Property呢?好像也是類的屬性?因此有很多人不加區(qū)別的統(tǒng)一稱為類的屬性,尤其是在寫中文文章的時(shí)候。這種心理是典型的鴕鳥心態(tài),眼不見為凈。其實(shí)稍微用腳想一下就知道,事實(shí)肯定不是這樣的,UML中既然發(fā)明了這兩個(gè)術(shù)語,顯然不是用來冗余的。它們之間肯定有著千絲萬縷的聯(lián)系與區(qū)別。
各種各樣的面向?qū)ο笳Z言、各種組件技術(shù)、模板技術(shù)、Web Service技術(shù),其中大部分涉及到了“屬性”這個(gè)概念,而其英文術(shù)語則常常是Attribute、Property或者Field。很多人一概稱之為“屬性”,有的地方確實(shí)可以不加區(qū)分,但有的地方卻是差之毫厘、謬以千里。我對(duì)于這些紛紛擾擾的技術(shù)和術(shù)語也很苦惱,但是我們至少可以通過UML中的這兩個(gè)術(shù)語的解釋找到一個(gè)可以參考的標(biāo)準(zhǔn)。無論如何,UML是面向?qū)ο蠹夹g(shù)的集大成者和事實(shí)上的標(biāo)準(zhǔn)。
UML1.4中的Attribute和Property
造成Attribute和Property理解混亂的罪魁禍?zhǔn)子幸话胧?/SPAN>OMG自己,因?yàn)樵?/SPAN>UML1.4以前的規(guī)范中,Property并沒有當(dāng)作一個(gè)標(biāo)準(zhǔn)的術(shù)語出場(chǎng),而是叫做Element Properties。其定義如下[1]:
Many kinds of elements have detailed properties that do not have a visual notation. In addition, users can define new element properties using the tagged value mechanism. A string may be used to display properties attached to a model element. This includes properties represented by attributes in the metamodel as well as both predefined and user-defined tagged values.
許多模型元素含有詳細(xì)的特性(properties),它們并沒有可視化的符號(hào)。另外,用戶可以使用標(biāo)記值(tagged value)機(jī)制定義新的模型元素特性。一個(gè)字符串可以被用來顯示附著在模型元素上面的特性。它包括在元模型中用來表示特性(properties)的屬性(attribute)以及預(yù)定義和用戶自定義的標(biāo)記值。
從上面的定義可以看出,OMG的本意是將Property作為表示模型元素特性的統(tǒng)一術(shù)語。模型元素是UML所有建模元素的頂層父類和原子成分,Class也是一種模型元素。因此Property是用來修飾一部分模型元素的,而不僅僅是用來修飾Class的。另外一層含義是,Property包含了Attribure和tagged value,它的概念范圍應(yīng)該比Attribute要大。
再來看看Attribute在UML1.4規(guī)范中的定義[2]:
An attribute is a named slot within a classifier that describes a range of values that instances of the classifier may hold. In the metamodel, an Attribute is a named piece of the declared state of a Classifier, particularly the range of values that Instances of the Classifier may hold.
一個(gè)屬性(attribute)是類元(classifier)中的一個(gè)命名的槽(named slot),它用來描述此類元的實(shí)例可能擁有的取值范圍。在元模型中,一個(gè)屬性是一個(gè)類元的可命名的聲明狀態(tài),尤其表示了這個(gè)類元的實(shí)例可能擁有的取值范圍。
由此可知,Attribute是與Classifier相關(guān)聯(lián)的術(shù)語,它比Property的影響范圍要小。Class是Classifier的子類,因此Attribute也可以表示Class的屬性。從上面的定義還可以看出,Attribute可以是Classifier的實(shí)例的命名的槽。對(duì)于Class來說,其實(shí)例就是Object,Object的槽就是對(duì)象的屬性值槽。因此,Attribute是可以作為對(duì)象的屬性的。而Property似乎沒有這一層的含義。按MOF(元對(duì)象設(shè)施,OMG的另一個(gè)規(guī)范,后面會(huì)有詳細(xì)解釋)的模型層次劃分,Attribute涉及的模型層從M2到M0,而Property似乎只是M2層的概念。
很客觀的說,UML1.4中對(duì)于這兩個(gè)術(shù)語并沒有很清晰的定義,但是其區(qū)別還是顯而易見的。Attribute應(yīng)該是UML1.4中的寵兒,而Property連一個(gè)單獨(dú)的術(shù)語都沒有撈到。誰也沒想到在UML2.0中風(fēng)云突變,Attribute從類圖中消失了,而Property堂而皇之入主中原。
UML2.0拋棄Attribute了么?
當(dāng)我看到UML2.0的類圖元模型的那一剎那,第一個(gè)感覺就是“Attribute哪兒去了?”下面是UML2.0中的Core::Basic包中的類圖元模型[3]:

從圖中可以清晰的看到,Class僅僅聚合了兩個(gè)元素:Property和Operation。而Attribute卻從類圖元模型中消失了。
先看看此元模型中Property的定義[4]:
A property is a typed element that represents an attribute of a class.
一個(gè)特性(property)是一個(gè)有類型的元素(typed element),它代表了一個(gè)類中的一個(gè)屬性(Attribute)。
哇,這個(gè)定義是不是在搞笑?各位別急,別忘記了UML2.0中的類圖元模型可不止一個(gè),它的類圖元模型是由三個(gè)分散的部分組成的。除了上面提到的Core::Basic::Class Diagram之外,還有Core::Constructs::Class Diagram和Class Diagram from Kernel Package。下面再來看看Core::Constructs::Class Diagram[5]:

可以看出這個(gè)圖與上面的不同之處是加入了Classifier和Association,Class、Property和Operation三巨頭還在。這個(gè)圖對(duì)于Property的定義幾乎可以解開我心中的疑惑了:
A property is a structural feature of a classifier that characterizes instances of the classifier. Constructs::Property merges the definition of Basic::Property with Constructs::StructuralFeature.
When a property is owned by a class it represents an attribute. In this case it relates an instance of the class to a value or set of values of the type of the attribute.
When a property is owned by an association it represents a non-navigable end of the association. In this case the type of the property is the type of the end of the association.
Property represents a declared state of one or more instances in terms of a named relationship to a value or values. When a property is an attribute of a classifier, the value or values are related to the instance of the classifier by being held in slots of the instance. When a property is an association end, the value or values are related to the instance or instances at the other end(s) of the association (see semantics of Association).
一個(gè)property是一個(gè)類元(classifier)的結(jié)構(gòu)化特征,它用來刻畫這個(gè)類元的實(shí)例。Constructs包中的Property(Constructs::Property)結(jié)合了Basic::Property和Constructs::StructuralFeature的定義。
當(dāng)一個(gè)property被一個(gè)class擁有時(shí)它代表一個(gè)attribute。在這種情況下,它將一個(gè)class的實(shí)例聯(lián)系到一個(gè)具體值或者一組值,這些值的類型符合attribute的類型。
當(dāng)一個(gè)property被一個(gè)連接(association)擁有時(shí)它代表一個(gè)非導(dǎo)向的連接端。在這種情況下這個(gè)property的類型就是這個(gè)association的連接端的類型。
Property表達(dá)了一個(gè)或者一些實(shí)例的聲明狀態(tài),它使用了一個(gè)命名的關(guān)系將實(shí)例連接到一個(gè)值或者一組值。當(dāng)一個(gè)property是一個(gè)classifier中的attribute的時(shí)候,它通過將值儲(chǔ)存在這個(gè)classifier的實(shí)例的槽(slot)中來給一個(gè)實(shí)例賦值。當(dāng)一個(gè)property是一個(gè)關(guān)聯(lián)端(association end)的時(shí)候,它的值被關(guān)聯(lián)到association另一個(gè)關(guān)聯(lián)端的實(shí)例。
從上面的定義中可以看出,Property同時(shí)代表了Attribute和Association end,如果它的owningAssociation不為空,則表明它屬于一個(gè)Association,這時(shí)它代表了一個(gè)關(guān)聯(lián)端;如果它的owningAssociation為空,則表明它不屬于一個(gè)Association,這時(shí)它代表了類的一個(gè)Attribute。同時(shí),Property繼承了UML1.4中的定義,它可以用來表示標(biāo)記值(Tagged Value)。
那么Attribute呢?UML2.0徹底拋棄它了么?不是的,它的定義依然存在[6]:
A structural feature of a classifier that characterizes instances of the classifier. An attribute relates an instance of a classifier to a value or values through a named relationship.
一個(gè)類元的結(jié)構(gòu)特征,它能夠刻畫這個(gè)類元的實(shí)例。一個(gè)Attribute通過一個(gè)命名的關(guān)系將一個(gè)類元的實(shí)例聯(lián)系到一個(gè)或者一組具體值。
比起UML1.4中的定義,這個(gè)定義要簡(jiǎn)潔多了,Attribute這里僅僅指一個(gè)類元的結(jié)構(gòu)特征,可以將類元的實(shí)例聯(lián)系到一個(gè)或者一組具體值。而沒有提到實(shí)例的槽(slot)等等。我猜想,這是因?yàn)?/SPAN>UML2.0中已經(jīng)把Attribute作為Property的一個(gè)子集了,所以關(guān)于實(shí)例的槽(slot)等等的具體賦值方法,都?xì)w結(jié)到Property的定義中解釋了。
另外一點(diǎn)值得注意的是,Attribute的定義來自于術(shù)語表,而沒有在元模型圖中出現(xiàn)。而Property出現(xiàn)在元模型圖中,并且都做了詳細(xì)而具體的解釋。這一點(diǎn)可以看出,UML強(qiáng)化Property,弱化Attribute的決心。
Attribute和Property的總結(jié)
這一節(jié)對(duì)Attribute和Property作一個(gè)小結(jié),基于目前最新的UML2.0規(guī)范:
l 總體上來說,Attribute是Property的子集,Property會(huì)在適當(dāng)?shù)臅r(shí)機(jī)表現(xiàn)為Attribute;
l Property出現(xiàn)在類圖的元模型中,代表了Class的所有結(jié)構(gòu)化特征;Attribute沒有出現(xiàn)在元模型中,它僅僅在Class的概念中存在,沒有相應(yīng)的語法了;
l Property有詳細(xì)的定義和約束,而Attribute沒有詳細(xì)的定義,因此也不能用OCL寫出其約束。
l Property和Attribute都是M2層的概念。在M1層,它們的實(shí)例是具體類的屬性;在M0層,它們的實(shí)例的實(shí)例是具體對(duì)象的槽中存儲(chǔ)的值。
上面多次提到了MOF的四層模型,這應(yīng)該是屬于MDA范疇中的概念,下面這一小節(jié)給出一個(gè)例子,希望能夠說明Attribute和Property及其實(shí)例在不同的模型層中扮演的角色。
元模型圖、模型圖、對(duì)象圖
MOF的四層模型分別是:元元模型層(M3)、元模型層(M2)、模型層(M1)、運(yùn)行時(shí)(M0)。其中元元模型層包含了定義建模語言所需的元素;元模型層定義了一種建模語言的結(jié)構(gòu)和語法;模型層定義了一個(gè)具體的系統(tǒng)的模型;運(yùn)行時(shí)包含了一個(gè)模型的對(duì)象在運(yùn)行時(shí)的狀態(tài)等。
本文涉及到的有M2、M1和M0層,下面給出一個(gè)例子,首先是M2層,它可以定義一個(gè)建模語言的結(jié)構(gòu)和語法,例如:

這是一個(gè)簡(jiǎn)要的元模型圖,它表示Class由Property和Operation組成,這張圖符合UML2.0的概念,但是我們也可以這樣畫:

這樣一來,Class包含三種元素:Attribute、AssociationEnd和Operation,這樣我們就創(chuàng)建了一個(gè)新的元模型,也可以說創(chuàng)建了一個(gè)小的新建模語言。雖然它不符合UML2.0規(guī)范。
M1層模型就是我們通常簡(jiǎn)稱的“模型”,它是系統(tǒng)的標(biāo)準(zhǔn)化表示,一般用建模語言來表示一個(gè)軟件系統(tǒng),例如下面的汽車和人的系統(tǒng):

其中Car類表示汽車的模型,它有兩個(gè)屬性price和type,另外還有一個(gè)關(guān)聯(lián)端owner(表示車主),這些都是Property的實(shí)例。Person類也有兩個(gè)屬性age和name,還有一個(gè)關(guān)聯(lián)端car。可以看出,M1層模型中的元素都是M2層模型元素的實(shí)例,例如:
Car和Person是Class的實(shí)例;price、type、age、name以及car、owner都是Property的實(shí)例;run()和drive()都是Operation的實(shí)例。
所謂“建模”實(shí)際上就是利用M2層定義的元模型作為建模語言來定義M1層的模型。
再來看看M0層,汽車和人系統(tǒng)的運(yùn)行時(shí)對(duì)象圖如下:

因?yàn)椴粦B(tài)熟悉對(duì)象圖,所以其中可能有疏漏,不過其意義是一目了然的。其中具體的對(duì)象屬性就是Property的實(shí)例的實(shí)例了。例如type=medium,medium是M1層模型中type的實(shí)例值,type是M2層中Property的實(shí)例值。
后記
總算將這一篇寫完了,在群里面和阿飛仔細(xì)討論了好久,真的是非常辛苦,但是我覺得弄清楚了Attribute和Property的區(qū)別是非常有意義的。它們所涉及的范圍很廣,可謂知十而聞一。這篇似乎不能夠叫“程序員眼中的UML了”,因?yàn)樯婕傲撕枚?/SPAN>MDA的知識(shí),而且離代碼很遠(yuǎn)。不過我盡量寫得清楚通俗一點(diǎn),文中出現(xiàn)的術(shù)語都作了解釋,希望能夠讓大家看懂。
文中的術(shù)語翻譯來自于《UML參考手冊(cè)》[7],因?yàn)?/SPAN>UML很多術(shù)語的翻譯不統(tǒng)一,因此我用了這本很著名的UML書的譯法。同時(shí)注明了英文原文。
參考文獻(xiàn)
1. UML1.4-01-09-67文檔 289頁
2. UML1.4-01-09-67文檔 80頁
3. UML 2.0 Infrastructure Final Adopted Specifcation03-09-15文檔109頁
4. UML 2.0 Infrastructure Final Adopted Specifcation03-09-15文檔111頁
5. UML 2.0 Infrastructure Final Adopted Specifcation03-09-15文檔123頁
6. UML 2.0 Infrastructure Final Adopted Specifcation03-09-15文檔17頁
7. UML參考手冊(cè)