MDA中模型的存儲(chǔ)、表現(xiàn)與轉(zhuǎn)換
Posted on 2006-02-13 21:08 wxb_nudt 閱讀(3919) 評(píng)論(4) 編輯 收藏 所屬分類: 技術(shù)雜談MDA中模型的存儲(chǔ)、表現(xiàn)與轉(zhuǎn)換
最近一些朋友在我的blog上面留言或者給我寫email討論一些問題,本文希望能夠一起解答他們的一些疑問,同時(shí)也整理一下自己的思路。
MDA是以模型為中心的,模型是其基本元素,所以關(guān)于模型的存儲(chǔ)、查詢、表現(xiàn)和轉(zhuǎn)換是對(duì)于基本元素的操作。OMG已經(jīng)有一些既定規(guī)范或者正在制訂的規(guī)范是用來討論這些問題的。例如XMI規(guī)范規(guī)定了模型的存儲(chǔ)格式、QVT規(guī)范(正在制訂中,已經(jīng)有一個(gè)初步的版本)是規(guī)定模型的查詢、視圖和轉(zhuǎn)換的。最近的QVT規(guī)范對(duì)于模型的查詢尚未涉及,因此本篇中也不討論模型查詢。重點(diǎn)總結(jié)一下模型的存儲(chǔ)、表現(xiàn)(視圖)和轉(zhuǎn)換。并力所能及的舉例來說明。
模型的存儲(chǔ)
我認(rèn)為模型的存儲(chǔ)按照其發(fā)展進(jìn)程來看可以分為以下幾種:自定義格式;基于XML的自定義格式;遵守XMI的格式;可以轉(zhuǎn)換為其它格式的腳本格式;以及直接以代碼存儲(chǔ)的形式。
我對(duì)于軟件建模的了解是從UML開始的,UML統(tǒng)一之前的各種建模方法并未研究,相信在UML統(tǒng)一之前,模型是沒有一個(gè)統(tǒng)一的存儲(chǔ)格式的。其必然是按照自定義的格式來存儲(chǔ)的。不同的建模工具是按照自己定義的格式來存儲(chǔ)模型,對(duì)于以下一個(gè)最簡單的模型:
一個(gè)建模工具可以這樣存儲(chǔ):
類:Bank
屬性:name;類型:string
連接:customers;類型:Customer
類:Customer
屬性:name;類型:string
屬性:age;類型:int
屬性sex;類型:boolean
連接:bank;類型:Bank
簡而言之,只要建模工具能夠識(shí)別,模型的存儲(chǔ)格式是沒有限制的。
但是,這種自定義的方式顯然是有缺點(diǎn)的,最大的兩個(gè)確定就是不具有可交互性,不能被其它工具識(shí)別。目前的建模工具已經(jīng)不使用這樣隨意的方法了。
交互性好,能夠廣泛的被工具識(shí)別的XML技術(shù)恰好與建模技術(shù)的發(fā)展在同步進(jìn)行。大概都在2000年左右,UML和XML幾乎同時(shí)達(dá)到了最高點(diǎn),因此現(xiàn)在的建模工具使用基于XML的模型存儲(chǔ)格式也就不是一件意外的事情了。由于幾乎所有的建模工具都采用了XML作為模型的存儲(chǔ)方式,OMG特別制訂了一個(gè)XMI規(guī)范,專門規(guī)定了模型的XML存儲(chǔ)格式。XMI事實(shí)上是一個(gè)XML Schema,它規(guī)定了模型、對(duì)象等概念的存儲(chǔ)格式。
目前很多建模工具都支持XMI2.0的存儲(chǔ),例如EMF、MagicDraw(RationalRose我沒有看,估計(jì)支持,因?yàn)楹?/SPAN>EMF一樣都是IBM的一母同胞)。下面是EMF的存儲(chǔ)格式,同樣是上面的那個(gè)模型:
<?xml version="1.0" encoding="UTF-8"?>
<ecore:EPackage xmi:version="2.0"
xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="mypackage">
<eClassifiers xsi:type="ecore:EClass" name="Bank">
<eStructuralFeatures xsi:type="ecore:EAttribute" name="name" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
<eStructuralFeatures xsi:type="ecore:EReference" name="customer" lowerBound="1"
upperBound="-1" eType="#//Customer"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="Customer">
<eStructuralFeatures xsi:type="ecore:EAttribute" name="name" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="age" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="sex" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EBoolean"/>
<eStructuralFeatures xsi:type="ecore:EReference" name="bank" eType="#//Bank"/>
</eClassifiers>
</ecore:EPackage>
可以看出來,EMF使用了XML1.0和XMI2.0,EMF的模型存儲(chǔ)是比較簡化的,可以人工閱讀和修改。MaigicDraw以及Rose的模型存儲(chǔ)則非常繁瑣,包含了眾多圖信息(所謂圖信息,就是定義了可視化模型元素的位置、大小、顏色等的信息)、自定義信息等,是不支持人工閱讀的。例如上面那個(gè)模型的MagicDraw的模型存儲(chǔ)文件如果不壓縮的話有174kb。
也有一些工具使用類型于腳本的語言來定義和存儲(chǔ)模型,這種腳本一般都類似java語言或者idl等語言,可以方便的定義模型元素。也能夠被方便的轉(zhuǎn)換為不同工具支持的模型。例如ATL自帶的km3語言。當(dāng)然,這樣總是覺得有點(diǎn)怪怪的。明明使用模型就是為了避免從代碼開始,但是定義模型竟然又使用了另一種代碼。上面的模型使用km3的格式如下:
package mypackage {
class Bank {
attribute name
reference customer
}
class Customer {
attribute name
attribute age
attribute sex
reference bank
}
}
最后,用代碼也可以存儲(chǔ)模型,EMF的一種模型存儲(chǔ)方式就是帶有標(biāo)記的java代碼來存儲(chǔ)模型,所以上面的模型也可以使用如下代碼存儲(chǔ):
public class Bank {
private String name;
private Customer customers;
}
public class Customer {
private String name;
private int age;
private boolean sex;
private Bank bank;
}
Together這樣的工具根本就把模型和代碼看成同一件事物的兩種外表,因此,用代碼做為存儲(chǔ)模型的格式也是自然而精確的。不過這樣也是有缺點(diǎn)的,就是圖信息無法保存,而且要確保代碼生成是毫無疑義的。
模型的表現(xiàn)
在QVT(模型的查詢、視圖、轉(zhuǎn)換)規(guī)范中使用的是View這個(gè)術(shù)語,它的含義是模型的表現(xiàn)或者視圖。在最近的QVT規(guī)范中,還不支持視圖的創(chuàng)建和管理。但是視圖的概念類似與MVC中的視圖概念。我試著下一個(gè)定義:模型的視圖指的是對(duì)于軟件模型的某個(gè)側(cè)面在某種場景下的一種表現(xiàn)方式。例如,類圖是對(duì)于某個(gè)軟件的靜態(tài)結(jié)構(gòu)的視圖,而對(duì)象圖是軟件運(yùn)行時(shí)的某個(gè)時(shí)刻的視圖。
視圖的另外一層含義是,如何將存儲(chǔ)好的模型以可視化的方式展現(xiàn)在用戶面前。有人說,最好的建模工具是白紙和筆,這句話也是有一定道理的。用白紙和筆可以很快的畫出可以用來交流的UML圖。此時(shí),白紙上的UML圖就是模型的一個(gè)視圖。UML為模型的視圖提供了一組標(biāo)準(zhǔn)化的符號(hào)和概念,讓用戶可以使用不同的建模工具構(gòu)建具有相同含義的軟件模型,即使它們的顏色、大小、方位以及存儲(chǔ)格式不同,它們指的是同樣的內(nèi)涵。
一個(gè)模型的信息只有一個(gè),但是其表達(dá)方式是無窮的,每種表達(dá)方式都可以稱為此模型的一個(gè)視圖,它們通常是白紙上畫出的模型,或者建模工具中的圖形,或者規(guī)范的XML文件等等。
舉例說明,上面例子模型中,其類圖是一種視圖,我們也可以規(guī)定另一種視圖如下:
每個(gè)類用綠色的方塊表示,方塊中上部寫類名稱,中下部寫屬性名稱,屬性后面必須跟一個(gè)冒號(hào),冒號(hào)后面是屬性的類型……
模型的轉(zhuǎn)換
在看透了模型存儲(chǔ)和視圖的本質(zhì)以后,再來討論模型的轉(zhuǎn)換就比較容易了。模型的本質(zhì)是什么呢?是其存儲(chǔ)格式還是其表現(xiàn)形式呢?都可以!根據(jù)其存儲(chǔ)格式或者視圖都可以進(jìn)行模型轉(zhuǎn)換。
最簡單的模型轉(zhuǎn)換例子就是xslt了。以XML格式存儲(chǔ)的模型,一個(gè)XSLT的入門者就可以寫出模型轉(zhuǎn)換的實(shí)例。
例如我們要將上面的EMF的XML存儲(chǔ)文件轉(zhuǎn)換一下,將Bank類的name屬性名改為bankname,則使用下面的xsl文件可以轉(zhuǎn)換:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore">
<xsl:template match="/">
<xsl:apply-templates select="ecore:EPackage"/>
</xsl:template>
<xsl:template match="ecore:EPackage">
<xsl:text disable-output-escaping="yes">
<ecore:EPackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
</xsl:text>
name= "<xsl:value-of select="@name"/>"
<xsl:text disable-output-escaping="yes">></xsl:text>
<xsl:apply-templates select="eClassifiers"/>
<xsl:text disable-output-escaping="yes">
</ecore:EPackage>
</xsl:text>
</xsl:template>
<xsl:template match="eClassifiers">
<xsl:choose>
<xsl:when test="@name
<eClassifiers xsi:type="ecore:EClass" name="Bank">
<xsl:for-each select="eStructuralFeatures ">
<xsl:choose>
<xsl:when test="@name
<eStructuralFeatures xsi:type="ecore:EAttribute" name="bankname" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</eClassifiers>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
其中<xsl:template match="ecore:EPackage">可以寫得更簡潔一點(diǎn),直接使用源文件中的這個(gè)部分來代替,但是為了體現(xiàn)屬性的讀取功能,所以使用了xsl:value-of來讀取屬性,并填入ecore:EPackage的標(biāo)記中,同時(shí)因?yàn)闃?biāo)記不能封閉,所以使用了xsl:text來輸出。運(yùn)行這個(gè)xsl轉(zhuǎn)換源模型就可以得到目標(biāo)模型。
源模型和目標(biāo)模型在EMF中的顯示如下:
左邊的是源模型,右邊則是目標(biāo)模型。從上面簡單的例子可以看出,模型轉(zhuǎn)換可以使用XSLT對(duì)以xml方式存儲(chǔ)的模型進(jìn)行轉(zhuǎn)換。
但是,以XSLT來進(jìn)行模型轉(zhuǎn)換是不自然而且繁瑣的。我們需要更好的模型轉(zhuǎn)換方法。這時(shí)的一個(gè)思路就是能否把模型載入內(nèi)存,然后用面向?qū)ο蟮姆椒ㄒ约罢Z言來處理模型元素對(duì)象,然后生成目標(biāo)模型。