領(lǐng)域特定語言(domain-specific languages,簡稱DSL)
在定義DSL是什么的問題上,F(xiàn)lowler認為目前經(jīng)常使用的一些特征,例如“關(guān)注于領(lǐng)域”、“有限的表現(xiàn)”和“語言本質(zhì)”是非常模糊的。因此,唯一能夠確定DSL邊界的方法是考慮“一門語言的一種特定用法”和“該語言的設計者或使用者的意圖”:
如果XSLT的設計者將其設計為XML的轉(zhuǎn)換工具,那么我認為XSLT是一個DSL。如果一個用戶使用DSL的目的是該DSL所要達到的目的,那么它一個DSL,但是如果有人以通用的方式來使用一個DSL,那么它(在這種用法下)就不再是一個DSL了。
以Fowler的觀點,DSL首先是一種幫助用戶從一個系統(tǒng)中抽象出某些部分的工具。所以“當你意識到你需要一個組件,或者當你已經(jīng)有了一個組件而你希望簡化操作它的方式的時候”,DSL是有用的。使用DSL確實提供了某些益處。DSL不僅提高了代碼的易讀性,讓開發(fā)者可以和領(lǐng)域?qū)<腋玫慕涣?,而且是改變?zhí)行上下文的一種手段,例如:把邏輯從編譯時切換到運行時,或者當命令式編程不是很合適的時候轉(zhuǎn)用聲明式計算模型。
DSL包含哪些部分,有哪些分類
DSL主要分為三類:外部DSL、內(nèi)部DSL,以及語言工作臺。
外部DSL是一種“不同于應用系統(tǒng)主要使用語言”的語言。外部DSL通常采用自定義語法,不過選擇其他語言的語法也很常見(XML就是一個常見選擇)。宿主應用的代碼會采用文本解析技術(shù)對使用外部DSL編寫的腳本進行解析。一些小語言的傳統(tǒng)UNIX就符合這種風格。可能經(jīng)常會遇到的外部DSL的例子包括:正則表達式、SQL、Awk,以及像Struts和Hibernate這樣的系統(tǒng)所使用的XML配置文件。
內(nèi)部DSL是一種通用語言的特定用法。用內(nèi)部DSL寫成的腳本是一段合法的程序,但是它具有特定的風格,而且只用到了語言的一部分特性,用于處理整個系統(tǒng)一個小方面的問題。用這種DSL寫出的程序有一種自定義語言的風格,與其所使用的宿主語言有所區(qū)別。這方面最經(jīng)典的例子是Lisp。Lisp程序員寫程序就是創(chuàng)建和使用DSL。Ruby社區(qū)也形成了顯著的DSL文化:許多Ruby庫都呈現(xiàn)出DSL的風格。特別是,Ruby最著名的框架Rails,經(jīng)常被認為是一套DSL。
語言工作臺是一個專用的IDE,用于定義和構(gòu)建DSL。具體來說,語言工作臺不僅用來確定DSL的語言結(jié)構(gòu),而且是人們編寫DSL腳本的編輯環(huán)境。最終的腳本將編輯環(huán)境和語言本身緊密結(jié)合在一起。
多年來,這三種風格分別發(fā)展了自己的社區(qū)。你會發(fā)現(xiàn),那些非常擅長使用內(nèi)部DSL的人,完全不了解如何構(gòu)造外部DSL。我擔心這可能會導致人們不能采用最適合的工具來解決問題。我曾與一個團隊討論過,他們采用了非常巧妙的內(nèi)部DSL處理技巧來支持自定義語法,但我相信,如果他們使用外部DSL的話,問題會變得簡單許多。但由于對如何構(gòu)造外部DSL一無所知,他們別無選擇。因此,在本書中,把內(nèi)部DSL和外部DSL講清楚對我來說格外重要,這樣你就可以了解這些信息,做出適當?shù)倪x擇。(語言工作臺稍顯粗略,因為它們很新,尚在演化之中。)
另一種看待DSL的方式是:把它看做一種處理抽象的方式。在軟件開發(fā)中,我們經(jīng)常會在不同的層面上建立抽象,并處理它們。建立抽象最常見的方式是實現(xiàn)一個程序庫或框架。操縱框架最常見的方式是通過命令/查詢式API調(diào)用。從這種角度來看,DSL就是這個程序庫的前端,它提供了一種不同于命令/查詢式API風格的操作方式。在這樣的上下文中,程序庫成了DSL的“語義模型”,因此,DSL經(jīng)常伴隨著程序庫出現(xiàn)。事實上,我認為,對于構(gòu)建良好的DSL 而言,語義模型是一個不可或缺的附屬物。
談及DSL,人們很容易覺得構(gòu)造DSL很難。實際上,通常是難在構(gòu)造模型上,DSL只是位于其上的一層而已。雖然讓DSL 工作良好需要花費一定的精力,但相對于構(gòu)建底層模型,這一部分的付出要少多了。
1. 我們常常會看到這樣一種劃分:一方面是程序庫/框架或者組件的實現(xiàn)代碼;另一方面是配置代碼或組件組裝代碼。從本質(zhì)上說,這種做法分開了公共代碼和可變代碼。用公共代碼構(gòu)建一套組件,然后根據(jù)不同的目的進行配置。
2. “聲明式”是一個非常模糊的術(shù)語,但是它通常適應于所有遠離了命令式編程的方式。。。。遠離變量倒換,用xml的子元素表示狀態(tài)的動作和轉(zhuǎn)換。
3. DSL扮演領(lǐng)域?qū)<液蜆I(yè)務分析人員之間的交流媒介。。。
4. 文本DSL有兩種,稱為外部DSL和內(nèi)部DSL。外部DSL是指,在主程序設計語言之外,用一種單獨的語言表示領(lǐng)域?qū)S谜Z言。內(nèi)部DSL是指,用通用語言的語法表示的DSL;
5. 是什么讓內(nèi)部DSL不同于通常的api呢?。。。連貫接口,這個術(shù)語強調(diào)這樣一個事實:內(nèi)部DSL實際只是某種形式的api,只不過其設計考慮了連貫性難以琢磨的質(zhì)量。
xx:后續(xù)在4.1節(jié)還會論述這個問題,DSL與api調(diào)用的區(qū)別,從這里看,兩者都提供一種抽象,但DSL在抽象的設計上考慮了連貫性。
在講完以上內(nèi)容后,提出DSL由三部分組成,即語言,語義模型和代碼生成。語言只是用一種可讀的方式來組裝語義模型。
6. 我強烈建議,幾乎始終應該使用語義模型。。。。語義模型,清晰的將語言解析和結(jié)果語義的關(guān)注點切分開,。。??梢詥为毻凭繝顟B(tài)機的運作機制,增強和調(diào)試,無須估計語言。
DSL只是模型一個薄薄的門面
7.許多人用了代碼生成之后,就舍棄了語義模型,他們在解析 輸入文本之后,就直接產(chǎn)生生成的代碼。。。不推薦任何人這么做。語義模型的存在,可以將解析,執(zhí)行語義以及代碼生成分開。
最后推薦一個開發(fā)DSL的語言工作臺,MetaEdit
評論