楊卓卿
(重慶郵電大學(xué)軟件工程學(xué)院,重慶400065)
在軟件開發(fā)領(lǐng)域,統(tǒng)一建模語言(Unified Modeling Language,UML)被廣泛認為是一種標準化的、通用的面向?qū)ο蠼UZ言。盡管如此,UML對客觀世界的描述能力有限,某些常見的語義,在UML中還沒有足夠的元模型來解釋[1]。
關(guān)聯(lián)的概念是大多數(shù)建模語言的一個關(guān)鍵元素,在概念模型甚至是程序代碼中,關(guān)聯(lián)定義了類之間的關(guān)系。在對客觀世界進行建模時,最常見的是二元關(guān)聯(lián),即維系兩個類的關(guān)聯(lián),此外,一元關(guān)聯(lián)也不可忽視,顧名思義,一元關(guān)聯(lián)只涉及一個類,也叫自關(guān)聯(lián)。在現(xiàn)實生活中,普遍存在一種特殊的一元關(guān)聯(lián),其特點是關(guān)聯(lián)雙方所扮演的角色是對等的。例如,人與人之間互為鄰居的關(guān)系、一個數(shù)學(xué)函數(shù)與它的反函數(shù)存在互為反函數(shù)的關(guān)系等,這種關(guān)聯(lián)叫做對稱一元關(guān)聯(lián)[2]。然而,主流的建模語言UML缺少對稱一元關(guān)聯(lián)語義的支持。
對此,本文首先分析了對稱一元關(guān)聯(lián)的語義,根據(jù)語義抽象出了對稱一元關(guān)聯(lián)的集合、圖等數(shù)學(xué)模型,再結(jié)合數(shù)學(xué)模型和UML類圖元模型,分析了UML無法支持對稱一元關(guān)聯(lián)的原因,以及由此引發(fā)的代碼生成問題。然后討論了對稱一元關(guān)聯(lián)的數(shù)據(jù)結(jié)構(gòu),提出通過擴展UML類圖元模型使UML支持對稱一元關(guān)聯(lián)建模的方法,并針對每種數(shù)據(jù)結(jié)構(gòu)給出代碼生成算法,最后通過實際例子的應(yīng)用驗證了該方法的可用性和有效性。
模型驅(qū)動架構(gòu)(Model Driven Architecture,MDA)是對象管理組織(Object Management Group,OMG)提出的一個軟件開發(fā)方法。所謂模型驅(qū)動,就是一種用模型來指導(dǎo)軟件工程師對軟件系統(tǒng)的理解、設(shè)計、構(gòu)造、部署、操作、維護和改進的方法[3]。
為了描述元建模的機制和方法,OMG定義了MDA的四層元模型體系結(jié)構(gòu)[4],分別是M0層、M1層、M2層、M3層。M0層是信息層,也叫客觀世界;M1層是模型層,用于描述M0層的信息;M2層是元模型層,用于描述M1層的模型;M3層是元元模型層,其元素提供了定義元模型的基本結(jié)構(gòu)。從M0層到M3層是一個逐層抽象的過程。
在MDA中,不同的應(yīng)用場景建立不同的模型,不同的模型由不同的元模型來描述。類圖元模型是描述類圖的模型,其作用是為類圖的建立定義一系列建模元素,稱之為類圖元模型中的“元元素”。在類圖元模型中,用一個名為“Association”的元元素來描述類圖中的“關(guān)聯(lián)”。類圖中的“關(guān)聯(lián)”都是類圖元模型中的“Association”元元素實例化后的對象。
UML標準文檔中對關(guān)聯(lián)的定義是“一種在類型化實例之間發(fā)生的語義關(guān)系”[5]。一個關(guān)聯(lián)至少有兩個端點,稱為關(guān)聯(lián)端[1],關(guān)聯(lián)端的名稱稱為角色,每一端與該關(guān)聯(lián)涉及的一個類相連接。關(guān)聯(lián)端的多重性表示關(guān)聯(lián)的某一端所連接的類對象的數(shù)量,多重性的值可以是一個特定的值,也可以是一個整數(shù)區(qū)間。關(guān)聯(lián)端可以是可導(dǎo)航的或不可導(dǎo)航的,可導(dǎo)航端所連接的類的對象將隱式地成為另一端所連接的類的成員屬性,稱為偽屬性[6]。單向關(guān)聯(lián)的關(guān)聯(lián)端的其中一端是可導(dǎo)航的,雙向關(guān)聯(lián)的兩個關(guān)聯(lián)端都是可導(dǎo)航的[7]。
本節(jié)將討論對稱一元關(guān)聯(lián)存在的問題及其語義,然后討論實現(xiàn)對稱一元關(guān)聯(lián)的數(shù)據(jù)結(jié)構(gòu),就存在問題提出了擴展UML類圖元模型的方法和代碼生成算法。
對稱一元關(guān)聯(lián)在現(xiàn)實生活中普遍存在,文獻[2]中使用的概念建模語言(Conceptual Modelling Language,ConML[8])提供了對稱一元關(guān)聯(lián)的建模所需的元模型和圖形符號,但是,UML作為一套被軟件開發(fā)人員廣泛使用的建模語言,其元模型并不支持對稱一元關(guān)聯(lián)的建模。
在理論上,如果用UML類圖表示對稱一元關(guān)聯(lián),不僅關(guān)聯(lián)兩端連接到同一個類,而且其關(guān)聯(lián)兩端的角色名、多重性、可導(dǎo)航性完全相同。以人與人之間的鄰居關(guān)系為例,每一個人都可以有多個鄰居,且鄰居的關(guān)系是相互的、對等的,在一個鄰居關(guān)系中,每一方都是另一方的鄰居。圖1(a)是用UML類圖表示的鄰居關(guān)聯(lián)。然而這將會與UML的建模規(guī)則產(chǎn)生矛盾。
圖1(c)是UML中關(guān)聯(lián)的元模型,用其表示“鄰居”關(guān)聯(lián)得到的對象圖如圖1(b)所示。圖1(b)中的對象圖出現(xiàn)了兩個完全相同的“neighbour”對象,然而在UML的標準文檔中,NamedElement元元素定義了一個名為isDistinguishableFrom()的方法來判斷UML模型中的兩個命名元素是否可以在同一個命名空間中邏輯共存[9],當兩個命名元素是不同類型的,或者同類型不同名時,兩者可以同時存在于同一個命名空間中。
類圖中的關(guān)聯(lián)端的角色是由Property元元素實例化而來的,而Property元元素間接繼承了NamedElement元元素,因此關(guān)聯(lián)端的角色也遵循isDistinguishableFrom()方法的規(guī)則。可見,圖1(b)中的兩個相同的neighbour對象不能同時存在。
由對稱一元關(guān)聯(lián)的UML建模問題,衍生出的是其代碼生成問題。對稱一元關(guān)聯(lián)兩端的角色既是相同類型的,又有相同的名稱和可導(dǎo)航性。在生成數(shù)據(jù)訪問代碼時,會導(dǎo)致語義的缺失,從而生成錯誤的代碼。以“鄰居”關(guān)聯(lián)為例,如果按照UML現(xiàn)有的語義、約束和代碼生成規(guī)則,在將類圖生成實體類代碼時,Person實體類代碼中會出現(xiàn)兩個同是Person類型且同樣名為neighbour的成員變量,其Java代碼如下。顯然這樣的代碼無法通過編譯。
圖1 用UML中關(guān)聯(lián)的元模型表示“鄰居”關(guān)聯(lián)
為了解決對稱一元關(guān)聯(lián)無法使用UML建模的問題,下面將從對稱一元關(guān)聯(lián)的語義著手,通過數(shù)學(xué)方法分析產(chǎn)生問題的原因。
在UML中,類是由一組擁有相同特征的對象組成的集合,這些對象描述了客觀世界中的真實個體;關(guān)聯(lián)是兩個類對象之間的二元關(guān)系,描述的是客觀世界中的個體之間的聯(lián)系。從數(shù)學(xué)集合的角度看,如果將類看成集合,將類對象看成集合中的元素,那么關(guān)聯(lián)就是兩個集合的元素之間的二元組。由于這些二元組描述的是同一類的二元關(guān)系,因此它們也組成了關(guān)聯(lián)的集合。
在鄰居關(guān)聯(lián)中,將Person、neighbour都看作集合,用p表示Person集合中的元素,用pn1表示Person集合中扮演neighbour角色的元素,pn2表示Person集合中另一個扮演neighbour角色的元素,則Person集合可以表示為公式(1)。
IsNeighbour關(guān)系中只存在neighbour一個角色。neighbour集合中的元素都是Person集合中的一個元素與Person集合中的另一個元素組合成的二元組,表示為公式(2)。
公式(2)表示的 neighbour集合中,二元組<pn1,pn2>表示pn2在當前關(guān)聯(lián)中所扮演的角色是neighbour,從相反的導(dǎo)航方向來看,pn1在當前關(guān)聯(lián)中所扮演的角色也是 neighbour,因此<pn1,pn2>與<pn2,pn1>等價,也就是說二元關(guān)系neighbour與其自身的逆等價,表示為公式(3)。
如果把Person集合中的每個元素看成頂點,把元素之間的關(guān)系看成頂點與頂點之間的邊,把Person集合中的每個元素看成頂點與頂點之間的關(guān)聯(lián)函數(shù),就可以將對稱一元關(guān)聯(lián)轉(zhuǎn)化為圖,如圖2所示。根據(jù)關(guān)聯(lián)“IsNeighbour”的語義,由于對稱一元關(guān)聯(lián)具有對等性和相互性,因此該圖是一個無向圖[10]。
圖2 用圖表示“鄰居”關(guān)系
其中,pn(n=0,1,2,3,4,5,6,7,8)是Person集合中的元素,其中 p0、p1、p2、p3、p4兩兩之間互為鄰居,p4、p5、p6、p7兩兩之間互為鄰居,p7和 p8互為鄰居。如果用G表示這個圖,用V(G)表示圖G中的所有頂點的集合,用E(G)表示圖G中的頂點之間邊的集合,用φ(G)表示頂點與頂點之間的關(guān)聯(lián)函數(shù),則該圖記為:
φ(G)=E→V×V,且φ(i0)=(p0,p2),φ(i1)=(p0,p1),φ(i2)=(p0,p3)
綜上所述,對稱一元關(guān)聯(lián)的特點是關(guān)聯(lián)雙方所扮演的角色是相同的且具有相互性。正是由于這個特點,當用UML表示對稱一元關(guān)聯(lián)時,無法區(qū)分兩個相同的角色。對此,可以對UML元模型進行擴展,使之支持對稱一元關(guān)聯(lián)的建模。
對稱一元關(guān)聯(lián)語義的特殊性導(dǎo)致了在生成代碼時出現(xiàn)錯誤代碼,下面將分析實現(xiàn)對稱一元關(guān)聯(lián)的幾種數(shù)據(jù)結(jié)構(gòu),為生成實體類代碼提供基礎(chǔ)。
根據(jù)上一節(jié)所討論的語義,可以將現(xiàn)實生活中的對稱一元關(guān)聯(lián)抽象成一個無向圖。一個圖所包含的信息由兩個方面,一是圖中頂點的信息,二是頂點與頂點之間關(guān)系的信息,即邊的信息。無論采用什么數(shù)據(jù)結(jié)構(gòu)來存儲圖,都要完整、準確地反映這兩方面的信息[11]。除了文獻[2]中使用的集合類型以外,常用的存儲無向圖的數(shù)據(jù)結(jié)構(gòu)有鄰接矩陣、鄰接表、鄰接多重表。
(1)鄰接矩陣
鄰接矩陣存儲圖的方法是用一個一維數(shù)組存放圖中的頂點的信息,用一個二維數(shù)組存放圖中邊的信息,這個二維數(shù)組也稱為鄰接矩陣。如圖2的無向圖有九個頂點,則一維數(shù)組的長度為9,如公式(8)所示,其鄰接矩陣是一個9×9的方陣,由于該圖是一個無環(huán)無向圖,所以方陣中主對角線上的各個位置的值都為0,其余位置的值根據(jù)兩個頂點之間是否有邊而定,若有邊則值為1,若無邊則為0,如公式(9)所示。
從公式(9)中不難看出,在 p0、p1、p2、p3、p4五個頂點構(gòu)成的五階子式中,每兩個不同頂點之間的邊的信息都被重復(fù)存儲了一次,p4、p5、p6、p7四個頂點構(gòu)成的四階子式和p7、p8兩個頂點構(gòu)成的二階子式同理,而根據(jù)對稱一元關(guān)聯(lián)的語義,被重復(fù)存儲的兩個邊并無區(qū)別,只需存儲一次,因此會出現(xiàn)數(shù)據(jù)的冗余。
(2)鄰接表
鄰接表存儲圖的方法是將每個頂點的所有鄰接點鏈接成一個單鏈表,稱為頂點的邊表。圖2的無向圖的鄰接表存儲示意圖如圖3所示。
圖3 圖2的無向圖的鄰接表存儲示意圖
從圖3中可以看出,鄰接表與鄰接矩陣一樣,也會出現(xiàn)兩個不同頂點之間的邊的信息被重復(fù)存儲的情況。
(3)鄰接多重表
鄰接多重表主要用于存儲無向圖,其存儲圖的方法與鄰接表類似,但在鄰接表的基礎(chǔ)上針對無向圖的邊重復(fù)存儲的問題做了改進。圖2的無向圖的部分頂點的鄰接多重表存儲示意圖如圖4所示。
圖4 圖2的無向圖的鄰接多重表存儲示意圖
從圖4中可以看出,兩個不同頂點之間的邊的信息只存儲了一次,便于邊的查找和刪除。
鄰接矩陣便于確定兩個頂點之間是否有邊,但時間代價較高,在存儲無向邊時存在邊信息的冗余,在處理稠密圖時,空間效率較高。鄰接表的時間代價較低,但在存儲無向邊時同樣存在邊信息的冗余,在處理稀疏圖時,空間效率較高。鄰接多重表的時間代價較低,便于邊的查找和刪除,在存儲無向邊時不存在邊信息的冗余,但是其結(jié)構(gòu)比前兩種復(fù)雜,適用于查找和刪除操作較頻繁的無向圖。表1對比了這三種圖的數(shù)據(jù)結(jié)構(gòu)的優(yōu)缺點。
表1 鄰接矩陣、鄰接表、鄰接多重表的對比
無向圖的鄰接矩陣、鄰接表、鄰接多重表的存儲各有利弊,在具體實現(xiàn)時,不但要根據(jù)圖的稀疏和稠密程度選擇合適的存儲方式,而且要考慮待解決問題的特殊需求。
通過前文的討論可知,UML元模型不支持對稱一元關(guān)聯(lián)的語義表示,需要對UML元模型進行擴展。本節(jié)將討論通過擴展類圖元模型的元屬性和約束使UML支持對稱一元關(guān)聯(lián)建模的方法。
對象約束語言(Object Constraint Language,OCL)是一種用于描述UML模型約束的形式化語言[12],與傳統(tǒng)形式化語言相比,對象約束語言具有良好的易讀性、易寫性和易理解性。本文通過為Association元元素添加元屬性和為Property添加對象約束的方法[13],對類圖元模型進行擴展,使之支持對稱一元關(guān)聯(lián)的語義。首先,為了標識模型中關(guān)聯(lián)是否是對稱一元關(guān)聯(lián),在UML標準的基礎(chǔ)上,擴展UML類圖元模型中的Association元元素,在Association元元素中添加一個元屬性,該元屬性的信息如表2。
表2 擴展的isSymmetricUnary屬性的信息
由于對稱一元關(guān)聯(lián)的建模問題源于關(guān)聯(lián)兩端的角色,而關(guān)聯(lián)端的角色是Property元元素的實例對象,因此須在Property元元素中對Association元元素的is-SymmetricUnary元屬性添加約束,用OCL描述該約束如下。
上述約束是對Property元元素的對象的約束,首先判斷當前Property對象所在的關(guān)聯(lián)是否有兩個關(guān)聯(lián)端,如果是,則定義一個名為otherEnd的變量,用來表示關(guān)聯(lián)的另一端,然后給關(guān)聯(lián)的isSymmetricUnary屬性賦值。如果兩個關(guān)聯(lián)端的名稱、數(shù)據(jù)類型(即關(guān)聯(lián)兩端所連接的類)、可導(dǎo)航性、多重性的上界和下屆之中有一項不同,則isSymmetricUnary屬性的值為false,否則isSymmetricUnary屬性的值為true。在建模時,計算機根據(jù)該約束自動判斷關(guān)聯(lián)的類型并給isSymmetricU-nary屬性賦值。
此外,在UML中,Property元元素間接繼承了NamedElement元元素,子類可以根據(jù)需要重寫父類的方法,因此可以在Property元元素中重寫NamedElement元元素的isDistinguishableFrom()方法,用于約束對稱一元關(guān)聯(lián)中的角色共存。當Association元元素的is-SymmetricUnary元屬性值為true時,關(guān)聯(lián)兩端相同的角色可以在當前命名空間中邏輯共存。用OCL描述重寫的isDistinguishableFrom()方法如下。
上述方法同樣是對Property元元素的對象的約束,在NamedElement元元素的isDistinguishableFrom()方法的基礎(chǔ)上,添加了處理對稱一元關(guān)聯(lián)的兩個相同關(guān)聯(lián)端的共存問題的分支,當Property對象所在的關(guān)聯(lián)的isSymmetricUnary屬性值為true時,關(guān)聯(lián)兩端相同的角色可以在當前命名空間中邏輯共存。對于非對稱一元關(guān)聯(lián)的情況,若兩個關(guān)聯(lián)端具有相同的類型,則二者是否可以共存取決于二者的名稱是否相同:如果名稱相同,則二者不可以共存,否則可以共存;若兩個關(guān)聯(lián)端具有不同的類型,則二者可以共存。
為了方便建模人員在建模時根據(jù)需求為對稱一元關(guān)聯(lián)選定合適的實現(xiàn)方式,可以在類圖元模型的Association元元素中標記對稱一元關(guān)聯(lián)的實現(xiàn)方式,在生成代碼時,根據(jù)不同的標記值生成不同的代碼。首先定義要擴展的元屬性的枚舉值,在UML標準的基礎(chǔ)上,在類圖元模型中添加一個名為“SUAImplementation”的枚舉型數(shù)據(jù)類型,這個數(shù)據(jù)類型的值有“CollectionType”、“AdjacencyMatrix”、“AdjacencyList”、“AdjacencyMultiList”,分別表示集合類型、鄰接矩陣、鄰接表、鄰接多重表;然后在類圖元模型的Association元元素中添加一個元屬性,該元屬性的信息如表3。
表3 擴展的implementation屬性的信息
需要注意的是,只有當isSymmetricUnary元屬性的值是true時,implementation元屬性才會啟用,否則其值為空。
圖5展示了擴展后的UML類圖元模型。
圖5 擴展UML類圖元模型
通過擴展Association元元素的元屬性以及Property元元素的約束,從元模型層面使UML支持對稱一元關(guān)聯(lián)的語義,為建模工具實現(xiàn)對稱一元關(guān)聯(lián)的建模提供了理論基礎(chǔ)。
從模型生成代碼是MDA思想中模型驅(qū)動開發(fā)的重要過程。在應(yīng)用程序的三層架構(gòu)中,領(lǐng)域?qū)ο笞鳛閿?shù)據(jù)的載體,扮演著關(guān)鍵的角色,領(lǐng)域?qū)ο笫菍嶓w類的實例,因此實體類的代碼生成尤為重要。常用的代碼生成方法是基于模板的代碼生成方法。使用模板的好處是模板與數(shù)據(jù)分離,當需要改動代碼時,只需修改模板,易于復(fù)用[14]。模板中可變的部分需要用模型的信息進行替換,不可變的部分則是代碼中固定不變的語法格式。
除了文獻[2]中給出的代碼生成方法,本文的2.3節(jié)還討論了三種實現(xiàn)對稱一元關(guān)聯(lián)的數(shù)據(jù)結(jié)構(gòu),下面將給出這些實現(xiàn)方式的代碼生成算法,其中被“%”包裹的部分為需替換成元模型的元元素中的元屬性的值。
對稱一元關(guān)聯(lián)實體類代碼生成算法
輸入:UML類圖的模型信息
輸出:對稱一元關(guān)聯(lián)實體類代碼
上述代碼首先獲取當前類圖的模型信息,循環(huán)判斷模型中的每個關(guān)聯(lián),如果關(guān)聯(lián)滿足對稱一元關(guān)聯(lián)的條件,則按照實體類代碼的模板框架生成類的定義代碼,先在類中循環(huán)生成該類的成員屬性,然后判斷implementation屬性的值,生成該值所標識的數(shù)據(jù)結(jié)構(gòu)的代碼。
鄰里社交平臺是一個專門為促進小區(qū)內(nèi)鄰居之間的交流而開發(fā)的平臺,居民在該平臺上可以隨時查看生活圈,關(guān)注鄰居的最新動態(tài),還可以向鄰居發(fā)出幫助請求,同時也可以幫助鄰居解決生活上遇到的難題,滿足了鄰里之間的交流與溝通的需求。
本節(jié)將以鄰里社交平臺的開發(fā)為例,采用本文提出的方法,使用PowerDesigner實現(xiàn)對稱一元關(guān)聯(lián)的建模和代碼生成,驗證本文研究的方法在實際軟件開發(fā)過程中的可用性和有效性。
本節(jié)討論對稱一元關(guān)聯(lián)的應(yīng)用,以“鄰居”關(guān)系為示例,建立了對稱一元關(guān)聯(lián)的UML類圖,然后在PowerDesigner中實現(xiàn)對稱一元關(guān)聯(lián)數(shù)據(jù)結(jié)構(gòu)的選擇,然后根據(jù)上一節(jié)提出的算法生成代碼。其次,還將同樣的方法應(yīng)用到一般的關(guān)聯(lián)中,說明方法的通用性。
(1)建立對稱一元關(guān)聯(lián)的領(lǐng)域模型
鄰里社交平臺的主要業(yè)務(wù)是實現(xiàn)鄰居之間的信息共享和交流。其中的特殊點在于,“鄰居”關(guān)系屬于對稱一元關(guān)聯(lián),在使用類圖建立領(lǐng)域模型時,需用到本文提出的對稱一元關(guān)聯(lián)的建模方法。其領(lǐng)域模型如圖6所示。
圖6 鄰里社交平臺核心業(yè)務(wù)的領(lǐng)域模型
領(lǐng)域模型中Person類表示使用系統(tǒng)的用戶,用戶與用戶之間的鄰居關(guān)系通過名為“IsNeighbour”的關(guān)聯(lián)來表示,該關(guān)聯(lián)雙方的鄰居角色用名為neighbour的角色表示,且多重性的值為0...*,兩端都是可導(dǎo)航端。根據(jù)前文中提出的UML元模型的擴展約束,該領(lǐng)域模型中IsNeighbour關(guān)聯(lián)滿足對稱一元關(guān)聯(lián)的條件,因此該關(guān)聯(lián)的isSymmetricUnary屬性值為true,進而關(guān)聯(lián)兩端相同的neighbour角色可以在當前命名空間中邏輯共存。
(2)數(shù)據(jù)結(jié)構(gòu)的選擇和代碼生成
為了方便建模人員在生成代碼時選擇合適的數(shù)據(jù)結(jié)構(gòu),使用PowerDesigner提供的Profile擴展功能,在資源編輯器中將一個用于標識對稱一元關(guān)聯(lián)實現(xiàn)方式的擴展屬性添加到類圖的Association元元素下,并給定這個擴展屬性的四個可選值,分別表示使用集合類型、鄰接矩陣、鄰接表、鄰接多重表,然后將四種實現(xiàn)方式的代碼生成算法應(yīng)用到這個擴展屬性中,最后提供建模人員的操作界面,如圖7所示。
圖7 在PowerDesigner中選擇代碼生成的方式
通過擴展PowerDesigner的操作界面,建模人員在建模時可以在類圖的Association元素的Properties窗口下選擇合適的數(shù)據(jù)結(jié)構(gòu)以標記使用哪種方式來生成對稱一元關(guān)聯(lián)的代碼。當然,這四個選項可用的前提是當前的關(guān)聯(lián)滿足對稱一元關(guān)聯(lián)的條件。如圖7所示,此處選擇鄰接多重表來實現(xiàn)“鄰居”對稱一元關(guān)聯(lián),生成的Java代碼如下。
在圖6所示的領(lǐng)域模型中,Reply關(guān)聯(lián)描述了用戶與消息之間的“回復(fù)”關(guān)系,一個用戶可以回復(fù)多條消息,一條消息可以被多個用戶回復(fù)。用戶的角色用名為Replier的角色表示,消息的角色用名為ReplyMessage的角色表示,關(guān)聯(lián)兩端的多重性的值都為0...*且都為不可導(dǎo)航端。
雖然Reply關(guān)聯(lián)兩端的角色的多重性、可導(dǎo)航性相同,但類型、角色名都不相同,不滿足對稱一元關(guān)聯(lián)的條件,因此該關(guān)聯(lián)的isSymmetricUnary屬性值為假,關(guān)聯(lián)兩端的角色可以在當前命名空間中邏輯共存。在本文的討論范圍內(nèi),對于非對稱一元關(guān)聯(lián),無法選擇對稱一元關(guān)聯(lián)的實現(xiàn)方式,SUAImplementation屬性被禁用,如圖8所示。
圖8 “Reply”關(guān)聯(lián)的SUAImplementation屬性被禁用
因為Reply關(guān)聯(lián)不屬于對稱一元關(guān)聯(lián),所以在生成代碼時使用的是傳統(tǒng)的代碼生成的算法,將Replier角色作為成員屬性生成到Message類中,將ReplyMessage角色作為成員屬性生成到Person類中,由于兩端的多重性值都為0...*,所以數(shù)據(jù)類型為數(shù)組,生成的Java代碼如下。
文獻[15]針對UML存在組合關(guān)聯(lián)語義定義模糊,導(dǎo)致從領(lǐng)域模型自動轉(zhuǎn)換為數(shù)據(jù)訪問層代碼的精確度不足的問題,提出了描述邏輯CATSbqr語言,并準確地描述了UML組合關(guān)聯(lián)的語義以及動態(tài)操作復(fù)雜對象數(shù)據(jù)的語義,并通過實例說明了該方法的實用性,為實現(xiàn)領(lǐng)域模型到數(shù)據(jù)訪問層的代碼自動化提供了理論基礎(chǔ)。
文獻[2]針對UML無法表示對稱一元關(guān)聯(lián)的問題,提出使用ConML元模型中的半關(guān)聯(lián)(SemiAssociation)元元素,將對稱一元關(guān)聯(lián)分解成一個主半關(guān)聯(lián)(Primary)和一個次半關(guān)聯(lián)(Secondary),且允許關(guān)聯(lián)兩端的角色相同,并使用Microsoft Visual Studio Enterprise 2015、Visual Paradigm 14.0、ArgoUML 0.34和 XCode 8.0這四種代碼生成工具生成對稱一元關(guān)聯(lián)模型的代碼,通過表達語義的精確與否、是否有冗余、是否能編譯、是否無需開發(fā)者編輯等指標對比四種工具生成代碼的質(zhì)量,得出的結(jié)論是為了能生成滿足對稱一元關(guān)聯(lián)語義的代碼,最優(yōu)的解決方案是修改底層元模型和代碼生成規(guī)則,將這些規(guī)則運用到代碼生成工具中,從而實現(xiàn)對稱一元關(guān)聯(lián)。
與上述關(guān)于UML關(guān)聯(lián)的研究工作相比,本文針對客觀世界普遍存在但UML無法支持的對稱一元關(guān)聯(lián)進行了重點討論,用集合、圖等數(shù)學(xué)方法分析了對稱一元關(guān)聯(lián)的語義,通過擴展UML類圖元模型實現(xiàn)語義的支持,并討論了對稱一元關(guān)聯(lián)的數(shù)據(jù)結(jié)構(gòu)和代碼生成算法,提高了UML的建模能力,并且實現(xiàn)根據(jù)需求生成更高效、更少錯誤的數(shù)據(jù)訪問代碼。
UML元模型定義了模型元素在同一個命名空間中共存的約束,使UML類圖元模型無法表示對稱一元關(guān)聯(lián)的語義。由于對稱一元關(guān)聯(lián)的特殊語義,在從類圖生成代碼時,會導(dǎo)致語義的缺失,從而生成錯誤的代碼。本文針對以上兩個問題,使用集合、圖等數(shù)學(xué)方法分析了對稱一元關(guān)聯(lián)的語義,討論了集合、鄰接矩陣、鄰接表、鄰接多重表四種可用于對稱一元關(guān)聯(lián)的數(shù)據(jù)結(jié)構(gòu),提出了通過擴展UML類圖元模型使UML支持對稱一元關(guān)聯(lián)建模的方法和代碼生成算法,最后通過實際例子的應(yīng)用驗證了該方法的可用性和有效性,為實現(xiàn)對稱一元關(guān)聯(lián)的建模及數(shù)據(jù)訪問代碼的自動化提供了理論基礎(chǔ)。