<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    J2EE之巔

     

    DSL的實現要點(1)

     

    引言

    DSL(domain-specific language)并不是什么新的概念和技術,但是目前它已成為了一個技術熱點,近期各種類型的技術交流或研討會上你都可以看到關于DSL的主題。DSL似乎也在一夜間成為了大師們關注的焦點(Martin FowlerEric Evans等等)。

    應用DSL可以有效的提高系統的可維護性(縮小了實現模型和領域模型的距離,提高了實現的可讀性)和靈活性,并且提供開發的效率。

    那么如何在我們的實踐中引入DSL呢,Martin FowlerDSL實現模式做了全面的闡釋;在實際工作中作者實踐了部分Martin Fowler的模式,下文是作者對這些實踐的經驗總結,愿與大家分享。

    根據實現方式的分類DSL可以大致分為內部DSLInternal DSL)和外部DSL(Extern DSL), 作者在實際項目中實踐了這兩大類DSL,在系列文章中將分別共享各類型DSL的實現經驗。

    示例涉及的模型

    為了便于說明問題,系列文章講圍繞一個簡單得示例展開,將以不同方式實現一個關于狀態機描述的DSL


    Figure 1狀態機


    Figure 2 領域模型

    實現DSL的本質任務


    無論是實現內部DSL或是外部DSL,要完成的本質任務就是將DSL API調用及DSL語言腳本解析為應用中的語義模型(通常為應用中領域模型的部分)。

    實現DSL

    實現內部DSL

    內部DSL實際上就是一組精心設計的API,同時這種API及其對他的調用有著某些特定領域中自然語言的特性。

    以下分享兩種內部DSL實現方法的實現經驗。

    實現要點

    不要將這種DSL API直接放置在領域模型中,這不符合關注點分離的思想,并且導致代碼難以維護,應該引入一個新的層次——Builder層,由Builder層來解析調用并創建為系統中的語義模型對象。

    幾種模式的實現要點

    方法鏈(Method Chain

    調用示例

    publicclass Client {

          publicstaticvoid main(String [] args){

                Process p=new Process();

                ProcessBuilder process=new ProcessBuilder(p);

                process.name("Auto-Door")

                .state("Open")

                      .transition()

                            .event("timeout")

                            .nextState("close")                

                .state("Close")

                      .transition()

                            .event("people-closer")

                            .nextState("open");

                System.out.println(p);

          }

    }

    實現

    ProcessBuilder.java:

    publicclass ProcessBuilder {

          protected Process process;

          public ProcessBuilder(Process process2){

                this.process=process2;

          }

          public ProcessBuilder name(String name){

                process.setName(name);

                returnthis;

          }

          public StateBuilder state(String name){              

                State newState=new State();  

                StateBuilder sb= new StateBuilder(process,newState);

                sb.name(name);

                process.getStates().add(newState);

                return sb;

          }    

    }

    StateBuilder.java:

    public class StateBuilder extends ProcessBuilder{

          protected State state=new State(); 

          public StateBuilder(Process p,State state){

                super(p);        

                this.state=state;

               

          }

          public StateBuilder name(String name){

                 state.setName(name);

                 returnthis;

          }

          public TransitionBuilder transition(){

                Transition t=new Transition();

                TransitionBuilder tb= new TransitionBuilder(process,state,t);           

                state.getTransitions().add(t);           

                return tb;

          }    

    }

    TransitionBuilder.java

    publicclass TransitionBuilder extends StateBuilder {

          private Transition transition;

          public TransitionBuilder(Process process,State state,Transition transition){

                super(process,state);

                this.transition=transition;

               

          }

          public TransitionBuilder event(String event){

                transition.setEvent(new Event(event));

                returnthis;

          }

          public TransitionBuilder nextState(String state){

                returnthis;

               

          }

         

    }

    實現要點

    1 返回值

    每個方法的返回都是Builder,這是為了可以實現這種鏈式調用。

    2 繼承

    可以發現下一層次的Builder仍需可以提供上面層次Builder中的方法,我們把方法鏈拉直你便一目了然了。

                 

    由此可見為了避免代碼重復,可以采用繼承機制,讓下層的Builder繼承自上層的Builder

    3 上下文變量(context variable

    從代碼中我們可以發現這些變量(各個Builder中的成員變量,process,state,tranistion,他們用來保證我們的Builder是在正確的上下文上工作,如把生成的transition加入到正確的state中。

    這些上文變量在不同Builder將是通過構造函數進行傳遞的。

    嵌套方法(Nested function)

    調用示例

    publicstaticvoid main(String[] args) {

                Process p=process("Auto-Door", new State []{

                      state("Open",new Transition[]{

                            transition(

                                  event("timeour"),

                                  nextState("Close")

                            )    

                           

                      }),

                      state("Close",new Transition[]{

                            transition(

                                  event("people-closer "),

                                  nextState("Open")

                            )    

                           

                      })

                     

                });  

    }

    實現

    Builder.java

    publicclass Builder { 

          publicstatic Process process(String name, State [] states){

                Process process=new Process();

                process.setName(name);

                List<State> sts=new ArrayList<State>();

                for (State s:states){

                      sts.add(s);

                }

                process.setStates(sts);

                return process;

          }

          publicstatic State state(String name,Transition [] transitions){

                State state=new State();

                state.setName(name);

                List<Transition> ts=new ArrayList<Transition>();

                for (Transition t: transitions){

                      ts.add(t);

                }

                state.setTransitions(ts);

                return state;

          }

          publicstatic Transition transition(Event event,String nextState){

                Transition t=new Transition ();

                t.setEvent(event);           

                return t;

          }

          publicstatic Event event(String event){

                returnnew Event(event);

          }

          publicstatic String nextState(String nextState){

                return nextState;

          }

    }

    實現要點

    由源碼可以看出嵌套方法的實現比方法鏈要簡單得多。

    1 方法及返回值

    由于無需維護對象狀態,所以方法均為靜態,返回值則直接是方法所要創建的模型對象。

    2 方法及方法的參數來表明語義

    通過Builder中的方法來定義語法中的詞匯,方法的參數表明層次與包含的語義關系。

    3 無需上下文變量

    由于嵌套方法實現DSL巧妙的利用了系統中的方法調用棧,所以無需采用上下文變量來進行上下文的維護。



    蔡超
    HP 軟件架構師
    軟件架構顧問
    SCEA
    IBM Certified Solution Designer for OOA&D vUML2
    Chaocai2001@yahoo.com.cn

    posted on 2009-08-24 15:45 超越巔峰 閱讀(2081) 評論(2)  編輯  收藏 所屬分類: DSL

    評論

    # re: DSL的實現要點(1) 2009-08-24 17:10 99書城

    不錯啊!  回復  更多評論   

    # re: DSL的實現要點(1) 2009-08-24 22:53 vg

    camel  回復  更多評論   


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     

    導航

    統計

    常用鏈接

    留言簿(12)

    隨筆分類(54)

    隨筆檔案(59)

    文章分類(2)

    文章檔案(1)

    相冊

    搜索

    積分與排名

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 免费一级毛片在线播放视频免费观看永久 | 亚洲不卡无码av中文字幕| 久久久久久久99精品免费| 美女免费精品高清毛片在线视| 亚洲精品综合久久中文字幕| 伊人久久综在合线亚洲91| 国产精品冒白浆免费视频| 日本XXX黄区免费看| 蜜桃成人无码区免费视频网站| 国产精品小视频免费无限app| 国产成人亚洲精品播放器下载| 亚洲毛片基地4455ww| 亚洲精品美女在线观看播放| 亚洲电影国产一区| 亚洲av日韩av高潮潮喷无码 | a级毛片视频免费观看| 四虎影视在线看免费观看| 在线观看亚洲网站| 亚洲日韩中文字幕无码一区| 91亚洲性爱在线视频| 亚洲视频一区在线观看| 亚洲欧洲第一a在线观看| 国产亚洲成av人片在线观看| 中国亚洲女人69内射少妇| 亚洲人成色7777在线观看不卡 | eeuss影院免费92242部| 国产成人亚洲综合a∨| 美女啪啪网站又黄又免费| 羞羞漫画在线成人漫画阅读免费| 亚洲av第一网站久章草| 国产精品亚洲专区无码唯爱网| 亚洲爆乳精品无码一区二区| 亚洲精华国产精华精华液网站| 国产亚洲精品成人AA片| 亚洲精品欧美综合四区 | 免费一级毛片不卡在线播放| 一本久到久久亚洲综合| 亚洲第一页综合图片自拍| 亚洲区不卡顿区在线观看| 亚洲日产无码中文字幕| 亚洲av鲁丝一区二区三区|