J2EE之巔

           

          DSL的實(shí)現(xiàn)要點(diǎn)(1)

           

          引言

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

          應(yīng)用DSL可以有效的提高系統(tǒng)的可維護(hù)性(縮小了實(shí)現(xiàn)模型和領(lǐng)域模型的距離,提高了實(shí)現(xiàn)的可讀性)和靈活性,并且提供開發(fā)的效率。

          那么如何在我們的實(shí)踐中引入DSL呢,Martin FowlerDSL實(shí)現(xiàn)模式做了全面的闡釋;在實(shí)際工作中作者實(shí)踐了部分Martin Fowler的模式,下文是作者對這些實(shí)踐的經(jīng)驗(yàn)總結(jié),愿與大家分享。

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

          示例涉及的模型

          為了便于說明問題,系列文章講圍繞一個(gè)簡單得示例展開,將以不同方式實(shí)現(xiàn)一個(gè)關(guān)于狀態(tài)機(jī)描述的DSL


          Figure 1狀態(tài)機(jī)


          Figure 2 領(lǐng)域模型

          實(shí)現(xiàn)DSL的本質(zhì)任務(wù)


          無論是實(shí)現(xiàn)內(nèi)部DSL或是外部DSL,要完成的本質(zhì)任務(wù)就是將DSL API調(diào)用及DSL語言腳本解析為應(yīng)用中的語義模型(通常為應(yīng)用中領(lǐng)域模型的部分)。

          實(shí)現(xiàn)DSL

          實(shí)現(xiàn)內(nèi)部DSL

          內(nèi)部DSL實(shí)際上就是一組精心設(shè)計(jì)的API,同時(shí)這種API及其對他的調(diào)用有著某些特定領(lǐng)域中自然語言的特性。

          以下分享兩種內(nèi)部DSL實(shí)現(xiàn)方法的實(shí)現(xiàn)經(jīng)驗(yàn)。

          實(shí)現(xiàn)要點(diǎn)

          不要將這種DSL API直接放置在領(lǐng)域模型中,這不符合關(guān)注點(diǎn)分離的思想,并且導(dǎo)致代碼難以維護(hù),應(yīng)該引入一個(gè)新的層次——Builder層,由Builder層來解析調(diào)用并創(chuàng)建為系統(tǒng)中的語義模型對象。

          幾種模式的實(shí)現(xiàn)要點(diǎn)

          方法鏈(Method Chain

          調(diào)用示例

          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);

                }

          }

          實(shí)現(xiàn)

          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;

                     

                }

               

          }

          實(shí)現(xiàn)要點(diǎn)

          1 返回值

          每個(gè)方法的返回都是Builder,這是為了可以實(shí)現(xiàn)這種鏈?zhǔn)秸{(diào)用。

          2 繼承

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

                       

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

          3 上下文變量(context variable

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

          這些上文變量在不同Builder將是通過構(gòu)造函數(shù)進(jìn)行傳遞的。

          嵌套方法(Nested function)

          調(diào)用示例

          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")

                                  )    

                                 

                            })

                           

                      });  

          }

          實(shí)現(xiàn)

          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;

                }

          }

          實(shí)現(xiàn)要點(diǎn)

          由源碼可以看出嵌套方法的實(shí)現(xiàn)比方法鏈要簡單得多。

          1 方法及返回值

          由于無需維護(hù)對象狀態(tài),所以方法均為靜態(tài),返回值則直接是方法所要?jiǎng)?chuàng)建的模型對象。

          2 方法及方法的參數(shù)來表明語義

          通過Builder中的方法來定義語法中的詞匯,方法的參數(shù)表明層次與包含的語義關(guān)系。

          3 無需上下文變量

          由于嵌套方法實(shí)現(xiàn)DSL巧妙的利用了系統(tǒng)中的方法調(diào)用棧,所以無需采用上下文變量來進(jìn)行上下文的維護(hù)。



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

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

          評論

          # re: DSL的實(shí)現(xiàn)要點(diǎn)(1) 2009-08-24 17:10 99書城

          不錯(cuò)啊!  回復(fù)  更多評論   

          # re: DSL的實(shí)現(xiàn)要點(diǎn)(1) 2009-08-24 22:53 vg

          camel  回復(fù)  更多評論   

          導(dǎo)航

          統(tǒng)計(jì)

          常用鏈接

          留言簿(12)

          隨筆分類(54)

          隨筆檔案(59)

          文章分類(2)

          文章檔案(1)

          相冊

          搜索

          積分與排名

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 玛沁县| 拜城县| 铜鼓县| 克拉玛依市| 白山市| 东山县| 淮北市| 登封市| 建阳市| 宝坻区| 宁陵县| 永兴县| 泰来县| 什邡市| 保亭| 尤溪县| 阿合奇县| 白城市| 靖安县| 池州市| 安阳市| 定日县| 奇台县| 平陆县| 东莞市| 宜昌市| 桐梓县| 绥阳县| 安溪县| 新疆| 金湖县| 四子王旗| 山西省| 牙克石市| 防城港市| 龙岩市| 比如县| 大埔县| 新沂市| 甘肃省| 萍乡市|