• <menu id="w2i4a"></menu>
  • logo Enterprise Architect教程

    文檔首頁(yè)>>Enterprise Architect教程>>UML軟件開(kāi)發(fā)與建模工具Enterprise Architect教程:創(chuàng)建項(xiàng)目特定的代碼生成器(下)

    UML軟件開(kāi)發(fā)與建模工具Enterprise Architect教程:創(chuàng)建項(xiàng)目特定的代碼生成器(下)


    Enterprise Architect是一個(gè)對(duì)于軟件系統(tǒng)開(kāi)發(fā)有著極好支持的CASE軟件(Computer Aided Software Engineering)。EA不同于普通的UML畫(huà)圖工具(如VISIO),它將支撐系統(tǒng)開(kāi)發(fā)的全過(guò)程。在需求分析階段,系統(tǒng)分析與設(shè)計(jì)階段,系統(tǒng)開(kāi)發(fā) 及部署等方面有著強(qiáng)大的支持,同時(shí)加上對(duì)10種編程語(yǔ)言的正反向工程,項(xiàng)目管理,文檔生成,數(shù)據(jù)建模等方面??梢宰屜到y(tǒng)開(kāi)發(fā)中各個(gè)角色都獲得最好的開(kāi)發(fā)效率。

    點(diǎn)擊下載Enterprise Architect最新試用版

    每個(gè)模型元素生成一個(gè)以上的Artefact

    讓我們通過(guò)使用兩種不同的持久性方法來(lái)實(shí)現(xiàn)一個(gè)產(chǎn)品線,使示例更加令人興奮:一種使用JPA將數(shù)據(jù)存儲(chǔ)在關(guān)系數(shù)據(jù)庫(kù)中,另一種使用HBase作為大數(shù)據(jù)存儲(chǔ)。

    我建議實(shí)現(xiàn)一個(gè)可用于加載和保存實(shí)例的持久性管理器。只有基于JPA的產(chǎn)品才允許啟動(dòng)和完成交易。此外,我想將JPA特定的注釋放在Java類(lèi)中。圖3顯示了持久性管理器提供的方法。

    UML軟件開(kāi)發(fā)與建模工具Enterprise Architect教程:創(chuàng)建項(xiàng)目特定的代碼生成器(下)

    圖3:處理圖1中的域類(lèi)的PersistenceManager類(lèi)的概述

    現(xiàn)在的結(jié)果是,這兩種產(chǎn)品的所有六個(gè)類(lèi)的實(shí)現(xiàn)都略有不同。在Java代碼清單5,  6,  7  和  8示出了代碼的摘錄來(lái)實(shí)現(xiàn)。

    package com.example.orderingsoftware;
    
    public class Article extends AbstractIDObject {
    
       private String name; 
    
       public String getName() {
          return name;
       }
       
       public void setName(String name) {
          this.name = name;
       }
    }
    清單5:使用HBase作為持久性方法的Article類(lèi)的Java代碼
    package com.example.orderingsoftware;
    
    import javax.persistence.Entity;
    import javax.persistence.Table;
    
    @Entity
    @Table(name = "ArticleTable")
    public class Article extends AbstractIDObject {
    
       private String name; 
    
       public String getName() {
          return name;
       }
       
       public void setName(String name) {
          this.name = name;
       }
    }
    清單6:使用JPA作為持久性方法的Article類(lèi)的Java代碼
    public class PersistenceManager implements AutoCloseable {
    
       private final Table articleTable;
    
       public static final byte[] MODEL_FAMILY = "Model".getBytes();
    
       public static final TableName ARTICLE_TABLE_NAME = TableName.valueOf("ArticleTable");
    
       public Article getArticle(UUID id) {
          try {
             if (id != null) {
                Get get = new Get(id.toString().getBytes());
                if (articleTable.exists(get)) {
                   Result r = articleTable.get(get);
                   Article result = new Article();
                   result.setId(id);
                   result.setName(Bytes.toString(r.getValue(MODEL_FAMILY, ARTICLE_NAME_QUALIFIER)));
                   return result;
                }
             }
             return null;
          } catch (Exception e) {
             throw new RuntimeException(e.getMessage(), e);
          }
       }
    
       // ...
    }
    清單7:PersistenceManager類(lèi)的Java代碼的一部分,其中使用HBase作為持久性方法
    public class PersistenceManager implements AutoCloseable {
    
       private EntityManager entityManager; 
    
       public Article getArticle(UUID id) {
          if (id != null) {
             return entityManager.find(Article.class, id);
          } else {
             return null;
          }
       }
    
       // ...
    }
    清單8:PersistenceManager類(lèi)的Java代碼的摘錄,其中JPA作為持久性方法

    實(shí)現(xiàn)該產(chǎn)品線的可行解決方案是:

    • 使用繼承。這將需要使用每個(gè)類(lèi)的公共API進(jìn)行接口定義,并為JPA和HBase實(shí)現(xiàn)它。結(jié)果是必須將應(yīng)用程序的其余部分調(diào)整為僅在接口上運(yùn)行,而不能在具體類(lèi)上運(yùn)行。
    • 復(fù)制,粘貼和修改這兩種產(chǎn)品的實(shí)現(xiàn)將避免修改應(yīng)用程序的其余部分。維護(hù)兩個(gè)變體聽(tīng)起來(lái)很合理。但是隨著變體數(shù)量的增加,情況依然如此嗎?您應(yīng)該仔細(xì)考慮復(fù)制和粘貼的利弊。
    • 使用代碼生成器生成產(chǎn)品特定的代碼。實(shí)現(xiàn)代碼生成模板的類(lèi)可以基于通用實(shí)現(xiàn),并且每個(gè)子類(lèi)可以調(diào)整產(chǎn)品特定的部分。

    我更喜歡最后一種解決方案。圖4中的概述顯示了清單1的重構(gòu)的類(lèi)模板。每個(gè)引入的方法都會(huì)生成Java類(lèi)的特定成員。這使我可以在產(chǎn)品特定的模板中覆蓋這些方法。例如,在清單9中,可以看到JPA特定的注釋位于類(lèi)定義之前。

    圖4:重構(gòu)類(lèi)ClassTemplate的概述

    class JPAClassTemplate extends ClassTemplate {
       @EACodegenFile
       def IFile path(Class element, IFile ^default) {
          val path = "com/example/orderingsoftware/" + ^default.name
          return getTargetFilePath("jpa", path)
       }
       
       @EACodegen("java")
       override generate(Class element) {
          return super.generate(element)
       }
       
       override printClassDeclaration(Class element) '''
          ?IF element.isAbstract?
             @MappedSuperclass
          ?ELSE?
             @Entity
             @Table(name = "?element.name?Table")
          ?ENDIF?
          ?super.printClassDeclaration(element)?'''
    
       // ...
    }
    清單9:用Xtend編寫(xiě)的JPA的代碼生成模板的摘錄

    path(Class, IFile)帶有注釋的模板子類(lèi)中的方法@EACodegenFile用于定義應(yīng)保存生成的代碼的目標(biāo)位置。它有兩個(gè)參數(shù)。第一個(gè)是應(yīng)為其生成代碼的UML元素。第二個(gè)是應(yīng)將生成的代碼存儲(chǔ)在默認(rèn)位置。帶注釋的方法的返回值是調(diào)整后的位置,應(yīng)在該位置存儲(chǔ)生成的代碼。

    圖5中的屏幕快照顯示了所有模板。箭頭指向它們各自生成的文件。除了生產(chǎn)代碼外,還會(huì)生成測(cè)試代碼。



    圖5:JPA和HBase的代碼生成模板以及生成的源文件

    結(jié)論

    現(xiàn)代通用編程語(yǔ)言(例如Xtend)非常適合實(shí)現(xiàn)復(fù)雜的代碼生成器。輸入可能是UML模型,可能是在Enterprise Architect中建模的。YAKINDU EA-Bridge可以將Enterprise Architect模型背后的關(guān)系數(shù)據(jù)庫(kù)即時(shí)轉(zhuǎn)換為UML元模型的實(shí)例,并且將其完全隱藏。無(wú)需學(xué)習(xí)Enterprise Architect提供的專(zhuān)有代碼生成語(yǔ)言或?qū)nterprise Architect的數(shù)據(jù)庫(kù)架構(gòu)進(jìn)行反向工程。

    YAKINDU EA-Bridge的Eclipse IDE集成使人們可以在短時(shí)間內(nèi)以低成本實(shí)現(xiàn)特定于項(xiàng)目的代碼生成器。這樣,您可以節(jié)省許多繁瑣,容易出錯(cuò)和無(wú)意識(shí)的實(shí)施工作。

    如果您想親自查看并運(yùn)行完整的示例,請(qǐng)嘗試使用YAKINDU EA-Bridge。所提供的示例是YAKINDU EA-Bridge附帶的示例之一。

    =====================================================

    想要了解或購(gòu)買(mǎi)Enterprise Architect正版版權(quán),請(qǐng)咨詢慧都官方客服

    關(guān)注下方微信公眾號(hào),及時(shí)獲取產(chǎn)品最新消息和最新資訊

    掃碼咨詢


    添加微信 立即咨詢

    電話咨詢

    客服熱線
    023-68661681

    TOP
    三级成人熟女影院,欧美午夜成人精品视频,亚洲国产成人乱色在线观看,色中色成人论坛 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();