DSL 在軟件系統中的運用和實踐

本文來自:http://lunwen.1kejian.com/jisuanjiyingyong/69913.html

摘 要:基於實際項目中的實踐,介紹了DSL在軟件系統中的重要價值和運行,分析DSL如何通過DSL的開發態和運行態來保證其在軟件系統的運行。

關鍵詞:DSL;業務模型;DSL開發態;DSL運行態;語法 [本文轉自:lunwen.1kejian.com]
1、DSL總體概述
  DSL(Domain Specific Language),領域特定語言,Martin Fowler認爲DSL自從我們使用計算機時就在使用了,但是我們一直以來缺乏對DSL進行系統性的研究和實踐,截止2011年的今天,業務依然沒能對DSL給出一個權威的定義。從DSL從服務的場景的來看,它是一種針對特定領域,只具備有限表達能力的語言。比如:SQL是針對關係數據庫查詢維護業務的特定計算機語言;CSS是用來描述HTML頁面樣式的特定語言;Ant用來描述任務構建和組織任務構建過程的一種特定規則語言,類似於Makefile;如表格 1所描述的特定語言用來描述某種考卷的答題結果評價:
  業務描述  DSL  一種考試,滿分100。0-59不及格;60-69及格;70-89良好;90以上優秀  Exam->Score:
  90..100:優秀;[本文轉自:lunwen.1kejian.com]
  70..89:良好;
  60.69:及格;
  0..59:不及格;  表格 1 一種自定義的DSL
  按照Martin Fowler的觀點[1],DSL可分爲內部和外部兩種DSL。內部DSL,語法直接採用宿主語言的語法或者進行了適當的擴展,開發時可借鑑宿主語言的環境,直接運行在宿主語言的執行環境下,比如Rails之於Ruby。外部DSL,具有業務相關的特定語法,只能通過轉換成相應的通用語言的代碼並在這種通用語言的環境下執行,或者通過解析執行,比如前面介紹過的SQL、Ant等。
  不同於彙編等底層語言、Java等高級通用語言,DSL只關注與軟件系統所要解決的特性業務環境和業務痛點,一種DSL也只能運用在其所服務的軟件系統中。因此DSL具有如下幾個基本的特性:
  1.1直接面向特定業務。一種DSL因軟件系統所要解決的業務而生,該DSL的語法本身就具有很強的業務描述能力,而且也只是定義了業務要做成什麼,而不是描述具體某個業務應該如何做。從用戶的角度來看,DSL是爲了提供給軟件系統的用戶使用的,用戶說我關心的是業務是什麼,然後我使用這種語言將我的業務描述出來就可以了,所以這種語言必須用業務的術語來描述。比如表格 1中的例子,抽取其語法可如所示。那麼這種語法就正好是描述對於某種試卷的分數,有多少種不同的級別來評價最終的考試結果。
  Exame:score=int "":""
          Levels += Level
  Level: from=int "".."" to=int "":"" estimate=String "";""  表格 2 自定義DSL的語法
  1.2語言簡單。因爲DSL就是爲解決具體的業務而生,那麼就只需要定義成剛剛好解決此類具體業務就可以了。而且正因爲這種語言的簡單易懂,對於喜歡偷懶的用戶來說,他才肯接受基於此種語言來描述具體的業務。表格 1中定義的語言就非常的簡單,而如果換成Java之類的語言,將需要開發更多的更復雜的代碼。
  1.3有限的表達能力。正因爲簡單,所以DSL的表達能力就有限。同時,DSL不必也不能追求能夠表達更多更通用的業務場景,不然就成爲Java之類的通用語言了。DSL的這個特性本身也符合軟件架構設計的一個重要原則:設計剛剛好的架構,以支撐2-3的業務發展。
2、DSL在軟件系統中的價值和運用
  正如本文引用Martin Fowler所述的,計算機界很早就是用DSL了,並且衆多的軟件系統都或多或少是用不少於一種的DSL,比如當前大量的Web化的業務系統,幾乎都用到了CSS、SQL等DSL。所以,DSL在軟件系統中的運用時非常之廣的,其價值也可見一斑。那麼,DSL主要有哪些運用場景呢。
  從我們的實踐中,我們認爲,如下的場景非常適合使用DSL:
  2.1軟件系統有一個清晰的業務模型,並且如果是用通用語言開發,業務模型的邏輯代碼散落在系統的各個位置,難以集中維護和管理。
在業務軟件的開發過程中,涉及到對業務模型的UML建模、數據庫設計、業務模型的代碼實現,業務數據的讀取管理等,並且業務模型還需要對上層具體業務代碼提供穩定的接口,那麼算下來,同樣的模型,在不同的地方都用到了,但是很明顯這些模型散落在各種不同的物理位置中,要同步這些模型簡直是非常困難的;同時,業務經常變化,那麼要同步更新這些地方的模型已經不可能了。通過DSL來解決這個問題,我們可以設計出一套服務於此中業務的DSL語法,然後針對具體的業務模型編寫相應的DSL代碼,藉助於DSL代碼的生成工具,同步生成業務模型的UML模型、數據庫設計、代碼實現等等。但業務變化時,只需要更新該DSL語法或者代碼,就可以快速的同步不同位置的代碼了。
  2.2軟件系統中使用到了大量相似的、可重用的代碼,這些代碼基本通過COPY-PASTE再加上少量修改得到。
  常見的例子是開發UI界面的代碼。UI界面本身可以通過抽象得到UI的業務模型,這種模型在大量的通用語言都得到體現,比如Java的Swing框架和Eclpse的SWT/JFace框架。那麼可以開發基於XML的用來描述UI界面的DSL語言,然後藉助處理這種DSL語言的工具,自動生成相應通用語言的UI界面代碼。比如YUI組件就是這麼做的。那麼通過這種DSL,可以爲我們節省大量的工作量,也有利於充分保證整個軟件系統的質量。
  2.3具體業務邏輯只能由代表業務的人員才能開發指定。
  首先,這種業務是開發軟件的人不可能具備的,也是不可能通過編寫相應的軟件代碼就可以支持的。比如DIY一臺PC,買了一個STAT的硬盤,就必須配STAT的數據線,如果只有IDE數據線,那麼要配IDE轉STAT的接口;買了一個電源,這個電源需要配套幾條不同類型的電源線。同時,隨着IT技術發展,這些配置規則都在不斷的變化。所有這些配置規則在開發軟件時,都無法通過寫代碼完成,而是隻能交給掌握業務的人員來做,軟件系統支持對這些配置規則進行執行處理。那麼通過定義一種直接服務於業務的DSL,使掌握業務的人員方便快速的開發。如表格2所定義的簡單DSL。
  2.4可以通過制定嚴格標準的規範加以執行,並且在大量的軟件系統中可以複用。
  這一類顯著的例子就是SQL、CSS、HTML、ANT等等。這些DSL語言都已經是業界通用的特性語言。
  2.5基於框架式編程的組件或者軟件系統,整個框架在運行過程中必須對外開發業務節點,以便實現具體的業務功能,但是這些業務功能的開發必須受限於整個框架的架構和環境。
  框架式編程的重要特徵

 是框架負責整個業務流程的運行和生命週期管理,框架不理解業務,但是,框架是服務於一類業務的,因此必須開放出一些業務節點出來,使負責業務的人員能夠開發業務功能。但是,這些業務的代碼要受到整個框架的限制,那麼在設計框架時,就要指定,這些業務節點只能是什麼。這種場景最典型的例子就是Eclipse中的擴展點機制。開發框架時,以擴展點(Extension Point)的方式描述業務節點,具體的業務功能只能是一個個基於此擴展點的擴展(Extension)。
3、DSL在軟件系統的運行
  這部分主要關注外部DSL,因此本部分內容中所述的DSL都是指外部DSL。[本文轉自:lunwen.1kejian.com]
  通過前文的描述,我們知道DSL代碼都是一些簡單的文本,並且這些文本是現有通用語言的運行時環境不能支持的,那麼開發出來的DSL代碼如何幫我辦法如何能夠在軟件系統上運行呢。通過將DSL分成開發態和運行態,可以保證。所謂DSL的開發態,指DSL在開發階段的呈現方式和狀態;DSL的運行態,指DSL真正落實到軟件系統後,其執行的呈現方式和狀態。繼續表格1的例子,這種DSL,在開發態是表格1的呈現方式,但是這種呈現方式他無法執行在軟件系統中運行,那麼在運行態,它就被轉換成諸如Java等通用語言的呈現方式進行運行了。如圖表 2所示。
  
圖表 2 DSL的開發態和運行態
  通過圖表 2我們可以看到,支撐DSL代碼能夠從開發到最終執行,需要經過如下幾個階段:[本文轉自:lunwen.1kejian.com]
3.1能夠在一個集成的開發環境下開發代碼。
3.2通過一定的手段,將DSL代碼轉換成特定的通用語言,比如Java、Python等語言。
3.3在軟件系統的運行環境中,需要有一個適當的框架來執行這些轉換後的通用語言。比如Eclipse中的擴展點機制,用戶配置了擴展之後,系統需要相應的代碼來獲得擴展,使用擴展中配置的信息,實例化並運行擴展中配置的Java類。
  階段1,DSL代碼處於開發態,開發的主體是軟件系統的用戶,他基於能夠理解的特定業務的語法進行開發。當然如果本身DSL代碼量非常少,語法也非常簡單,那麼用戶只需藉助記事本等簡單文本編輯工具就能夠完成,對於規模的軟件系統,這種場景是比較少的,因此提供一個集成的編輯環境(IDE)就成爲一種必要。在此環境下,用戶可以進行DSL代碼開發、實時檢查代碼的語法正確性、進行所見即所得的單元測試、進行小批量的集成測試,從而提高代碼開發的效率。用戶開發DSL代碼時,如IDE提供以文本的方式編輯代碼,那麼代碼編輯器應當能夠提供現在成熟的通用語言的編輯器該有的功能,比如undo/redo、語法着色、代碼模板、重構、代碼自動完成、代碼Folder、實時語法檢查等等。更好的方式是IDE應當支持以圖形等可視化的方式編輯代碼,這對用戶更加直觀。開發好的代碼持久化時,常用的兩種格式:XML格式和普通文本格式。
  階段2,DSL代碼處於開發態和運行態之間。此階段一個重要的角色就是DSL代碼轉換工具,保證DSL代碼能夠轉換成特定的通用語言。通過開發代碼轉換模板,然後交給代碼轉換器,對輸入的DSL代碼進行轉換。開發代碼轉換模板時,基於DSL語法結構、要生成的通用語言的代碼結構兩個要素進行,同時還要考慮到DFx因素,以保證生成的通用語言代碼可讀性,執行效率等。
  以上兩個階段,都可以通過工具來支持,常用的工具有Eclipse下的Xtext、微軟的DSL Tools、MetaEdit+、JetBrains MPS等。Xtext支持以文本或者圖形化的方式開發DSL代碼,並且代碼以普通文本方式存儲,藉助Eclipse超強的文本編輯能力和GMF的圖形表達能力,使用基於Xtext開發DSL代碼效率非常高。同時,Xtext藉助Xtend/Xpand支持編輯DSL代碼生成通用語言代碼的模板。微軟的DSL Tools支持以圖形化的方式開發,代碼以XML格式存儲,同時它藉助集成TT工具來開發生成通用代碼的模板。以下是引子Xtext官方網站的實例[2]。
參考文獻:
[1]Martin Fowler.Domain Specific Languages[A].Addison-Wesley Professional.2010
[2]Jan K?hnlein.Combining Text and Graphics in Eclipse-based Modeling Tools[Z/OL].
http://www.slideshare.net/schwurbel/combining-text-and-graphics-in-eclipsebased-modeling-tools.

發佈了21 篇原創文章 · 獲贊 4 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章