天天看點

[轉]領域專用語言(DSL)

轉自:http://blog.csdn.net/mfowler/archive/2006/08/16/1069927.aspx

原文:DomainSpecificLanguage (http://www.martinfowler.com/bliki/DomainSpecificLanguage.html)

所謂領域專用語言(domain specific language / DSL),其基本思想是“求專不求全”,不像通用目的語言那樣目标範圍涵蓋一切軟體問題,而是專門針對某一特定問題的計算機語言。幾乎自計算機發明伊始,人們就開始談論DSL使用DSL了。

Unix社群是一個頻繁使用DSL的社群,他們通常稱之為小語言或迷你語言。(關于這一傳統,Eric Raymond的《Unix程式設計藝術》有上佳探讨。)要建構一種DSL,按最常見的Unix風格的做法,就是先定義它的文法,然後通過代碼生成技術把DSL代碼轉成一種通用語言代碼,或者寫一個這種DSL的解釋器。Unix有很多工具能讓這件事做起來輕松些。我為這類DSL定了一個術語:“外部DSL”。XML配置檔案是外部DSL的另一種常見形式。

DSL也是Lisp和Smalltalk社群的一項重要傳統,但方式不同,他們不是動手新造一套語言,而是讓Lisp或Smalltalk這種通用目的語言換個顔面變成DSL。(Paul Graham的文章《自底向上程式設計》對此有精彩講述。)利用程式設計語言自帶的文法結構定義出來的DSL,我稱之為“内部DSL”,也叫做“内嵌DSL”。這是種通用政策,不僅适用于Lisp和Smalltalk,用任何語言都可以這麼做,我面對問題時總是考慮着用這種政策定義出具有DSL功能的東西來解決,不過Lisp和Smalltalk程式員走得要深遠得多。

關于這兩類DSL,在我最近的文章《語言工作台(Language Workbench)》中有進一步的例子,我希望DSL能使用得更普遍,文中詳細讨論了這兩種風格各自的優缺點,還介紹了語言工作台工具的最新進展。

直到出現了一位人物,原本内外分流的DSL走向了一個有趣的彙合,他就是PragDave。沿襲Unix的傳統,用本主義程式員們(The pragmatic programmers)老早就是DSL粉絲了(《用本主義程式員》(中譯本連結)第十二節對這個話題的讨論引人入勝——我幹脆把它稱作“用本要義12”好了)。Dave在一次富有見地的訪談裡說到,盡管代碼生成是他的慣用技術,但在用Ruby程式設計時很少用到。

我做設計時,經常借建構一套DSL的思路來類推——有意把class和方法設計成DSL的樣子。不論用什麼語言,我都盡量這麼做,如果做不到,我就樂得轉用代碼生成技術了。在我們ThoughtWorks公司的較大型系統上,代碼生成以及類似的技術使用得非常普遍。

什麼時候需要把DSL和主語言劃清界線,我認為這個問題的答案因主語言而異,用Smalltalk時我幾乎從沒感覺有必要分離出一種DSL來,而這種需求在用C++/Java/C#時則非常常見。

是以,我認為有的語言适合設計内部DSL,有的不适合。适合的是那種“一條道跑到黑”的風格簡約的語言,它們在某一方面比其他傳統語言走得更遠更純粹(例如Lisp的函數式風格,Smalltalk的“對象-消息”思想),這是我分析Lisp和Smalltalk得出的結論。再看Ruby,它比前兩者更正常化一些,也比它們都龐大,但仍不失為一門用來建構内部DSL的好語言。

這麼看來,語言設計者需要對語言的精練程度有一個良好的決策,既要保證正常性内容可以輕松地表達,又要為原本費神的複雜東西提供舒适的文法支援。總之,我認為這是非常重要的一點。我喜歡用Smalltalk和Ruby的程度比喜歡用Java或C#的程度高那麼多,其原因我總是覺得難以言傳,最常聽到的解釋是靜态類型與動态類型的差別所緻,但我總覺得這個說法并沒有抓住要害,更接近兩者差別本質的是它們對建構内部DSL友好程度的差異。

譯注:Brian W. Kernighan與Rob Pike合著的《程式設計實踐(The Practice of Programming)》第9章也是一份關于DSL的極好的參考資源。

繼續閱讀