MDA之路

          MDA,UML,XML,Eclipse及Java相關(guān)的Blog
          posts - 53, comments - 494, trackbacks - 0, articles - 2
            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          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è)最簡單的模型:

          image001.gif

          一個(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年左右,UMLXML幾乎同時(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ǔ),例如EMFMagicDrawRationalRose我沒有看,估計(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.0XMI2.0EMF的模型存儲(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[0-1] ordered : EString

                     reference customer[1-*] ordered : Customer;

          }

           

          class Customer {

                     attribute name[0-1] ordered : EString

                     attribute age[0-1] ordered : EInt

                     attribute sex[0-1] ordered : EBoolean

                     reference bank[0-1] ordered : 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í)例。

          例如我們要將上面的EMFXML存儲(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">

          &lt;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">&gt;</xsl:text>

                     <xsl:apply-templates select="eClassifiers"/>

                     <xsl:text disable-output-escaping="yes">

                              &lt;/ecore:EPackage&gt;

                     </xsl:text>

          </xsl:template>

          <xsl:template match="eClassifiers">

                     <xsl:choose>

                              <xsl:when test="@name[. = 'Bank']">

                                       <eClassifiers xsi:type="ecore:EClass" name="Bank">

                                                 <xsl:for-each select="eStructuralFeatures ">

                                                          <xsl:choose>

                                                                   <xsl:when test="@name[. = '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中的顯示如下:
          image003.gifimage004.jpg

          左邊的是源模型,右邊則是目標(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)模型。

          (撰寫中。。。)


          評(píng)論

          # re: MDA中模型的存儲(chǔ)、表現(xiàn)與轉(zhuǎn)換  回復(fù)  更多評(píng)論   

          2006-02-14 09:49 by Christine
          謝謝指點(diǎn),
          關(guān)注 ing "模型的轉(zhuǎn)換"

          # re: MDA中模型的存儲(chǔ)、表現(xiàn)與轉(zhuǎn)換  回復(fù)  更多評(píng)論   

          2006-11-15 22:17 by jesse[匿名]
          View是不是還可以這樣理解,我覺得QVT中的view和SQL中的view非常相似。例如我們?cè)跀?shù)據(jù)庫中創(chuàng)建了一個(gè)非常復(fù)雜的table,而我們的操作又只關(guān)注這個(gè)table的某幾條數(shù)據(jù),這樣我們就可以對(duì)我們關(guān)心的數(shù)據(jù)創(chuàng)建一個(gè)view。這樣我們對(duì)table的操作就可以通過view來實(shí)現(xiàn)。
          同樣,對(duì)于一些復(fù)雜的模型集合,我們也許只關(guān)注其中某些模型或者一些模型的某些方面,這時(shí)我們就可以建立一個(gè)這樣的"view",使我們的關(guān)注點(diǎn)放在這個(gè)view上

          # re: MDA中模型的存儲(chǔ)、表現(xiàn)與轉(zhuǎn)換  回復(fù)  更多評(píng)論   

          2007-11-11 19:03 by 劉玉龍
          找到專家了,請(qǐng)多指導(dǎo).

          # re: MDA中模型的存儲(chǔ)、表現(xiàn)與轉(zhuǎn)換  回復(fù)  更多評(píng)論   

          2009-04-24 15:09 by bengle
          這個(gè)東東到底好不好用啊
          聽起來不錯(cuò)
          但是JAVA WEB中用的時(shí)候只能轉(zhuǎn)成JSF的...
          期待該技術(shù)的發(fā)展
          主站蜘蛛池模板: 忻州市| 稷山县| 本溪市| 商洛市| 长丰县| 拜泉县| 广水市| 沙坪坝区| 九龙城区| 荃湾区| 松原市| 宁河县| 灵丘县| 永康市| 巴彦县| 额尔古纳市| 德格县| 南部县| 民权县| 南宫市| 洛南县| 云安县| 乌审旗| 云南省| 漳州市| 宝兴县| 开封县| 叶城县| 明水县| 鹿邑县| 巴南区| SHOW| 阜南县| 封开县| 林芝县| 镇原县| 保亭| 新和县| 丰镇市| 凤山市| 永昌县|