Profile,Stereotype,TaggedValue與OCL漫談
起因
事情的起因是由于我需要在一篇文章中使用一個UML Profile for Design Pattern,就是在上一篇blog中提到的那個Profile。但是當我使用OCL來描述一些約束時,突然發(fā)現(xiàn)我不知道如何去取得PatternClass這個Stereotype中的TaggedValue的一個名字為role的值。并非我對OCL不熟悉,而是由于我對Stereotype和TaggedValue的精確關(guān)系不甚了解。于是我在qq群中求助,從而和阿飛展開了長達兩個多小時的討論,最后在他的幫助下總算略有所得,遂記之。
問題的描述
為了文章的完整性,我還是再簡要描述一下那個UML Profile for Design Pattern[1],如下所示:
這個Profile中引入了三個Stereotype和三個標簽值,其具體含義列表如下:
Stereotype |
Applies To |
Definition |
<<PatternClass>> |
Class |
指出這個Class是設(shè)計模式中的一部分 |
<<PatternAttribute>> |
Attribute |
指出這個Attribute是設(shè)計模式中的一部分 |
<<PatternOperation>> |
Operation |
指出這個Operation是設(shè)計模式中的一部分 |
TaggedValue表如下:
Tagged Value |
Applies to |
|
Name |
Value |
pattern |
<name[instance],role> |
<<PatternClass>> |
指出了被附著的class在名為name的設(shè)計模式實例instance中扮演了role這個角色。 |
pattern |
<name[instance],role> |
<<PatternAttribute>> |
指出了被附著的Attribute在名為name的設(shè)計模式實例instance中扮演了role這個角色。 |
pattern |
<name[instance],role> |
<<PatternOperation>> |
指出了被附著的Operation在名為name的設(shè)計模式實例instance中扮演了role這個角色。 |
具體的含義我已經(jīng)在上篇blog中介紹過。
對于這樣一個Profile,我希望在使用OCL描述約束時,能夠?qū)τ?/SPAN>TaggedValue中的name、instance和role的具體值有所規(guī)定。例如一個具體的類MyDAO,它的Stereotype和標簽值如下:<}>>。如果我希望有一個約束,表明MyDAO類的TaggedValue的role必須是DataAccessObject。則OCL如下:
context MyDAO inv:
??????
問題就在于如何使用OCL來描述這個與Stereotype和TaggedValue相關(guān)的約束。因為對于Class、Stereotype和TaggedValue的關(guān)系不甚明了。
問題的討論
問題的討論是非常煩雜的,我偷個懶,把聊天記錄整理上來:
wxb_nudt 19:48:35
有這么一個OCL的問題。
wxb_nudt 19:49:38
一個Class,它有一個Stereotype(PatternClass),并且這個Stereotype有一個TaggedValue,如何在OCL表達式中引用這個標簽值的值?
wxb_nudt 19:49:48
是不是
Class inv:
self.stereotype.taggedvalue.value?
wxb_nudt 19:51:53
老阿飛,出來跟俺討論一下吧,只有你通讀過UML2.0規(guī)范吧?
阿飛外傳 21:42:29
上面的是UML1.x的元模型吧
wxb_nudt 22:06:15
能說說我那個OCL應(yīng)該怎么寫么?
阿飛外傳 22:11:45
wxb_nudt 22:13:09
讓我看看啊
wxb_nudt 22:14:09
modelElement可以直接引用stereotype
wxb_nudt 22:14:48
但是steretype可以直接引用taggedvalue么?stereotype是modelElement的一種么?
wxb_nudt 22:14:53
好像是的。
wxb_nudt 22:15:11
那么應(yīng)該是class.stereotype.taggedvalue.value!
wxb_nudt 22:15:27
是不是啊?阿飛?這個圖哪兒來的?
阿飛外傳 22:19:04
modelElement可以直接引用stereotype --- right
但是steretype可以直接引用taggedvalue么?--- sure, but will go through TagDefinition
stereotype是modelElement的一種么? --- right
阿飛外傳 22:21:04
是不是啊?阿飛?這個圖哪兒來的? --- UML1.4 semantic01-09-73
阿飛外傳 22:22:21
The data value of a tagged value must conform to the data type specified by the “tagType”
attribute of the tag definition.
-- cannot be specified with OCL (requires an OCL function that
converts a string name into a corresponding metatype)
阿飛外傳 22:29:26
一個Class,它有一個Stereotype(PatternClass),并且這個Stereotype有一個TaggedValue,如何在OCL表達式中引用這個標簽值的值?
inv:
self.taggedValue->forAll(v | v.dataValue = "theStringRepresentationOftheValue" imples v.type.tagType ="the
TypeName")
wxb_nudt 22:45:14
wait
wxb_nudt 22:47:23
<>:
self.taggedValue.value.name -> notEmpty
這是一篇文章中的。
wxb_nudt 22:49:25
對于一個class,不需要引用Stereotype,直接使用self.taggedValue可以么?這個TagValue是附加在這個Stereotype上面的。
wxb_nudt 22:51:55
對于String類型的值,應(yīng)該可以直接這樣得到
self.taggedValue.theStringRepresentationOftheValue
wxb_nudt 22:52:20
錯了,應(yīng)該是self.taggedValue.theValuename
阿飛外傳 22:53:55

阿飛外傳 22:55:16
http://www.erp5.cn/forum/dispbbs.asp?boardID=3&ID=329&page=1
wxb_nudt 22:55:22
看看
阿飛外傳 22:57:29
<>:
self.taggedValue.value.name -> notEmpty
這是一篇文章中的。 --- 很可能是不正確的。
wxb_nudt 22:58:11
嗯,難道現(xiàn)在的UML2.0規(guī)范中沒有很明確的指出這些關(guān)系么?就像上面這張圖一樣的?
wxb_nudt 22:59:28
還有一個問題
wxb_nudt 23:00:18
taggedValue可以附加于每一個模型元素。如果一個Class,有一個Stereotype擴展了它,這個Stereotype有一個標簽值,那么這個標簽值是否同時屬于這個class?
阿飛外傳 23:00:53
對于一個class,不需要引用Stereotype,直接使用self.taggedValue可以么? --- 可以,也是profile的語用之一。
這個TagValue是附加在這個Stereotype上面的。----- TagValue與Stereotype沒有什么包含關(guān)系, 一個TagValue的定義(TagDefinition)只是從值(TagValue)到型的一種聲明,是一種由值到類型的自底向上的宣告式分類方法。
wxb_nudt 23:02:27
有點明白了,Stereotype和TagDefinition都是用來定義類型的,通俗的說。
而Class和TaggedValue就是這些類型的實例,是不是這樣的?
wxb_nudt 23:02:55
因此,從Class直接引用TaggedValue是很自然的。
阿飛外傳 23:05:40
taggedValue可以附加于每一個模型元素。如果一個Class,有一個Stereotype擴展了它,這個Stereotype有(只是偶然關(guān)聯(lián)而不是"有")一個標簽值,
那么這個標簽值是否同時屬于這個class?--- 標記值屬于某個class,并不是Stereotype or TagDefinition使然,完全是用戶不小心加到某個class上的亂帖的小標簽,至于這個標簽,有什么有分類完全是另一回事。
阿飛外傳 23:06:34
至于這個標簽,有沒有分類,是什么分類完全是另一回事。
阿飛外傳 23:06:53
這是動態(tài)類型(分類)面向的。
阿飛外傳 23:07:19
或者說是:值面向的
阿飛外傳 23:08:37
或者說:值就是存在,并不需要類型的存在而存在。
wxb_nudt 23:10:00
似乎有點明白了。
阿飛外傳 23:10:26
因此基于profile機制的UML元對象(M2級物理實例)的(虛)slot可以動態(tài)擴張的
阿飛外傳 23:11:39
這是由(ModelElement, taggedValue)關(guān)聯(lián)建立起來的
wxb_nudt 23:12:16
意思就是說,在模型元素上面,可以附加任意的值,這些值就用tag value來表示就可以了。
阿飛外傳 23:13:51
對UML::ModelElement而言相當于這樣:
class UML::ModelElement { List tagValue; //(虛)slot擴展點 }
阿飛外傳 23:14:04
對。
wxb_nudt 23:14:10
嗯,現(xiàn)在明白了。
wxb_nudt 23:14:19
thank you。
阿飛外傳 23:15:17
class UML::ModelElement {
List stereotypes ; //(虛)子類型擴展點
List tagValue; //(虛)slot擴展點
}
阿飛外傳 23:16:23
class UML::ModelElement {
List stereotypes ; //(虛)子類型擴展點
List tagValue; //(虛)slot擴展點
}
wxb_nudt 23:16:25
每個Class只能有一個Stereotype的,所以不應(yīng)該用 List stereotypes ;
wxb_nudt 23:16:49
因為后來的Stereotype會替換前面的。
阿飛外傳 23:17:09
每個Class只能有一個Stereotype的 --- 每個類不可能有多個子類?
wxb_nudt 23:17:10
UML2.0是這樣的,我不知道前面的規(guī)范如何。
wxb_nudt 23:17:19
我剛剛讀過。
wxb_nudt 23:19:43
找不到了,不過我記得是這樣的。
阿飛外傳 23:20:16

wxb_nudt 23:21:59
可能我的方向搞反了,對于Remote和Home,它們都擴展了Interface,而對于Interface,它可以擴展為多個Stereotype。
wxb_nudt 23:22:22
我的意思是,一個具體的Class,只能擁有一個Stereotype。
wxb_nudt 23:22:36
你的意思是,一個模型元素可以擴展為多個Stereotype
wxb_nudt 23:24:29
在一個系統(tǒng)中,這么寫:
class UML::ModelElement {
List stereotypes ; //(虛)子類型擴展點
List tagValue; //(虛)slot擴展點
}
是正確的。因為它代表這個系統(tǒng)中的某個模型元素擴展了哪些內(nèi)容。
阿飛外傳 23:25:02
一個具體的Class,只能擁有一個Stereotype。 --- 因為OO的用戶級(M1)一個用戶設(shè)計對象只能歸屬到一個分類。
一個模型元素可以擴展為多個Stereotype --- 因為M2的類型系統(tǒng)中,一個類可以有多個子類。
wxb_nudt 23:25:17
我的意思和你一樣。
wxb_nudt 23:26:38
TagDefinition中的TagType:Name
Name是一個數(shù)據(jù)類型么?
阿飛外傳 23:27:03
TagDefinition中的TagType:Name
Name是一個數(shù)據(jù)類型的名字
wxb_nudt 23:28:51
Tagged Value Applies to
Name Value
pattern <> 指出了被附著的class在名為name的設(shè)計模式實例instance中扮演了role這個角色。
wxb_nudt 23:29:14
這樣一個TagValue,它的TagType的值是什么?
wxb_nudt 23:30:45
我對TaggedValue和TagDefinition的關(guān)系感到很迷惑。
阿飛外傳 23:31:11
Tagged Value Applies to
Name Value
pattern <> 指出了被附著的class在名為name的設(shè)計模式實例instance中扮演了role這個角色。--- 這是一張表么,看不太清楚,能帖一圖么。
wxb_nudt 23:31:20
wait
wxb_nudt 23:31:36

阿飛外傳 23:35:09
相當于:
struct PatternAtt { String name; String role }
class PatternClass
{
PatternAtt pa;
}
wxb_nudt 23:36:04
其實我就想知道如何在OCL中表達role的取值。
阿飛外傳 23:38:13
它能給出具體的例子么
wxb_nudt 23:38:53
這么一個類 <}>>ConnectionPool
wxb_nudt 23:40:02
顯然它的TaggedValue的兩個值是name=Abstract Factory,role=AbstractFactory
stereotype=PatternClass
阿飛外傳 23:42:31
[instance]是什么
wxb_nudt 23:42:56
它可以不出現(xiàn),你忽視它好了。
阿飛外傳 23:43:34
(前面我說的有誤,確實可以從作為導(dǎo)航入口點,導(dǎo)航到TaggedValue)
wxb_nudt 23:44:39
怎么導(dǎo)航呢?
wxb_nudt 23:45:57
Class、Stereotype、TagDefinition、TaggedValue?
阿飛外傳 23:47:00
因為Stereotype 繼承自GeneralizedElement,后者繼承自ModelElement,而ModelElement有到TaggedValue的包括關(guān)聯(lián)。
wxb_nudt 23:47:44
那就是可以直接從Class到Stereotype然后到TaggedValue
wxb_nudt 23:48:14
這個問題解決了,但是如何表達那個role的取值呢?
wxb_nudt 23:50:06
it's a big problem.
wxb_nudt 23:55:16
主要問題是如何從dataValue中取得role的值?
阿飛外傳 23:55:14
context PatternClass inv:
self.stereotype.definedTag->forAll(td : TagDefinition |
td.tagType = "AbstractFactory" imples td.typedValue.dataValue ="Abstract Factory[instance],AbstractFactory") and
self.stereotype.definedTag->forAll(td : TagDefinition |
td.tagType = "Iterator" imples td.typedValue.dataValue ="Iterator [instance],Iterator") and
...
阿飛外傳 23:55:47
需要串的操作設(shè)施。
wxb_nudt 23:57:22
我認為td.tagType = "Pattern"
wxb_nudt 23:59:39
主要問題是如何從dataValue中取得role的值?
role這個名字不是白定義了的。
阿飛外傳 00:05:18
因為這個paper把這些信息用串記錄在TaggedValue的dataValue字段中,所以需要串處理。你可以用其它方式(actually, i am not sure,maybe more detailed stereotype or taggedvalue)
wxb_nudt 00:10:57
好吧,謝謝你了,我明天再仔細研究吧,晚安阿飛!
結(jié)論整理
結(jié)論一,UML的擴展機制
首先,對于Stereotype和標簽值的擴展機制,顯然下面這個式子是成立的:
class UML::ModelElement {
List stereotypes ; //(虛)子類型擴展點
List tagValue; //(虛)slot擴展點
}
它表明,對于某個UML的模型元素,可以擴展為不同的Stereotype,也可以附加很多的標簽值。有兩點需要注意的是:第一,對于某個具體的模型元素,它只能屬于一個Stereotype;第二,對于某個模型元素的標簽值,標簽值的名字是唯一的。也就是說,如果某個模型元素有多個標簽值,并且它們的名字相同,那么它們是同一個標簽值。
結(jié)論二,模型元素、Stereotype和TaggedValue的導(dǎo)航關(guān)系
通過觀察上面的圖可以得知:Class和Stereotype都屬于模型元素,它們都可以直接通過taggedValue導(dǎo)航到自己擁有的標簽值。另外,Class可以通過stereotype導(dǎo)航到自己所屬的構(gòu)造型。
結(jié)論三,TaggedValue和TagDefinition的關(guān)系
TaggedValue只有一個屬性,就是dataValue,它是一個String[*],可以包含字符串數(shù)組。所有的標簽值的值都存儲在這個dataValue中。
而TagDefinition是標簽值的數(shù)據(jù)結(jié)構(gòu)的描述,它有兩個屬性,tagType:Name,和mutiplicity:Mutiplicity。Name和Mutiplicity都是數(shù)據(jù)類型,它們聯(lián)合起來定義了TaggedValue的數(shù)據(jù)結(jié)構(gòu)。
TaggedValue和TagDefinition之間可以通過type和typedValue來互相導(dǎo)航。
結(jié)論四,如何表達tuple形式的TaggedValue
這是昨晚沒有解決的問題,但是今天在一篇文章[2]中看見了相應(yīng)的例子。
<>:
self.baseClass = Class and self.taggedValue -> exists
(tv:taggedValue | tv.name = "pattern" and tv.dataValue =
"tuple")
對于一個tuple來說,可以直接取值他的一個部分,就使用這個部分的名字即可。
因此可以這樣得到role的值:
class.stereotype.taggedValue.dataValue.role
那篇文章中的一個表達式證實了這一點:
<>:
self.taggedValue.dataValue.role -> notEmpty
問題的解決
一個具體的類MyDAO,它的Stereotype和標簽值如下:<}>>。我希望有一個約束,表明MyDAO類的TaggedValue的role必須包含DataAccessObject角色。則OCL如下:
context MyDAO inv:
self.stereotype.taggedValue.dataValue.role->exists(“DataAccessObject”)
Reference
[1]. Extending UML To Visualize Design Patterns In Class Diagrams
[2]. Visualizing Design Patterns With A UML Profile