LOP和MPS背后的思想并不新鮮,實(shí)際上已經(jīng)出現(xiàn)超過(guò)20年了;Language Oriented Programming本身這個(gè)詞也已經(jīng)提出十多年了。LOP放棄了傳統(tǒng)的基于文本的語(yǔ)言,用創(chuàng)造新的語(yǔ)言來(lái)代替類庫(kù),可以和編輯器所整合,并且每個(gè)程序員都可以創(chuàng)造自己的語(yǔ)言。Martin Flower卻對(duì)此饒有興趣,并寫了Language Workbenches和A Language Workbench in Action - MPS兩篇文章進(jìn)行了介紹。
概述
按照Dmitriev先生的觀點(diǎn),通用語(yǔ)言的問(wèn)題在于:它們描述領(lǐng)域模型的能力太差。在完成概念性的領(lǐng)域建模之后,開發(fā)者們還必須經(jīng)過(guò)一個(gè)漫長(zhǎng)的編碼過(guò)程,才能把模型描述為機(jī)器可理解的程序,反過(guò)來(lái)要理解這些代碼所描述的領(lǐng)域模型也是同樣困難。而DSL雖然能夠很好地描述領(lǐng)域模型、解決領(lǐng)域問(wèn)題,但這種語(yǔ)言又太少了,而且大多數(shù)開發(fā)者必須苦苦等待少數(shù)大廠商為他們提供適用的DSL。很大程度上,這種“語(yǔ)言的失位”造成了軟件開發(fā)的低效。
Dmitriev先生提出的解決方案就是LOP:借助工具的幫助,允許開發(fā)者創(chuàng)建自己的DSL。這樣的DSL當(dāng)然能夠最貼切地描述領(lǐng)域問(wèn)題,從而大大提高開發(fā)效率。而且,這樣的“自定義DSL”也不必是文本形式的,它可以直接保存為樹狀結(jié)構(gòu)(或別的結(jié)構(gòu)),并直接以圖象的形式展現(xiàn)。
主流編程中三個(gè)最糟糕的問(wèn)題
從理解問(wèn)題后到實(shí)現(xiàn)的時(shí)間很長(zhǎng)
在明白問(wèn)題和解決方案后,將解決方案編碼到計(jì)算機(jī)中將會(huì)花費(fèi)很長(zhǎng)的時(shí)間。這是因?yàn)榭梢允褂梅浅XS富的自然語(yǔ)言表達(dá)問(wèn)題,但我們只能通過(guò)通用的編程語(yǔ)言與計(jì)算機(jī)交流。而現(xiàn)在的編程語(yǔ)言只有幾十種,而自然語(yǔ)言表達(dá)可以有千萬(wàn)上萬(wàn)種,因此這種轉(zhuǎn)換的成本是比較大的。
在主流編程中,大部分時(shí)間都是在“編程”上,這實(shí)際上是在用編程層次的抽象術(shù)語(yǔ)來(lái)表達(dá)自然語(yǔ)言的概念,而這是很困難的,沒(méi)多少創(chuàng)造性,或多或少也是一種時(shí)間的浪費(fèi)。舉個(gè)例子,今天大量的開發(fā)時(shí)間花費(fèi)在面向?qū)ο蟮脑O(shè)計(jì)(OOD)上,在程序員表達(dá)類、繼承、關(guān)聯(lián)等方面這確實(shí)是一種還算有創(chuàng)造性的過(guò)程,但是使用Language Oriented Programming,OOD根本就不需要。
(個(gè)人觀點(diǎn):這個(gè)我還不是很了解,我想底層還是需要的吧,有待進(jìn)一步了解)
理解和維護(hù)代碼
在通用語(yǔ)言的程序中,很多高度概括的視角、藍(lán)圖都丟失了,這不利于我們對(duì)產(chǎn)品理解。解決這個(gè)問(wèn)題的傳統(tǒng)方法是寫注釋或用其它形式的文檔來(lái)記錄設(shè)計(jì)信息和模型信息,但這證明了這是一種脆弱的解決方案,因?yàn)樗枰帉戇@些輔助文檔的成本、以及文檔和代碼帶來(lái)的不同步麻煩等問(wèn)題;理想情況下,代碼應(yīng)該是自我描述的,我應(yīng)該只閱讀代碼本身來(lái)理解代碼,而不是什么注釋和外部的文檔。
學(xué)習(xí)曲線高
OOP很少能夠直接表述領(lǐng)域概念,它們必須引入額外的枝節(jié)(如一個(gè)類的運(yùn)行時(shí)行為)來(lái)完成到領(lǐng)域概念的映射。理解這些領(lǐng)域、學(xué)習(xí)這些類庫(kù)不是一項(xiàng)簡(jiǎn)單的任務(wù),我們需要用大量的指南和文檔來(lái)解決這個(gè)問(wèn)題,但是學(xué)習(xí)這些將花費(fèi)大量時(shí)間;當(dāng)一個(gè)類庫(kù)變得復(fù)雜的時(shí)候,它也變得更難以學(xué)習(xí),程序員將因此失去學(xué)習(xí)它的動(dòng)機(jī)。即使掌握了領(lǐng)域問(wèn)題和技術(shù)的這種復(fù)雜映射之后,依然還會(huì)很容易的誤用類庫(kù),因?yàn)殚_發(fā)環(huán)境(像編譯器和編輯器)不能幫助你正確的使用類庫(kù)。
LOP的切入點(diǎn)
通過(guò)計(jì)算機(jī)改變世界,程序員都希望自己對(duì)計(jì)算機(jī)有完全的控制,但實(shí)際上,我們經(jīng)常被那些不能輕易改變的編程語(yǔ)言和開發(fā)環(huán)境等基礎(chǔ)設(shè)施限制。當(dāng)需要進(jìn)行一些語(yǔ)言擴(kuò)展時(shí),我們只能等待語(yǔ)言的設(shè)計(jì)者去更新它;如果需要我的IDE有一些額外的強(qiáng)大功能,只能等待供應(yīng)商來(lái)添加新特性;就是這些依賴限制了我們完全的自由;當(dāng)然,程序員也可以寫自己的編譯器和IDE,但這樣將會(huì)花費(fèi)大量的時(shí)間和努力,并且并不一定能成功。
LOP的切入點(diǎn)就是允許我們可以創(chuàng)建、重用、修改語(yǔ)言和環(huán)境。要理解LOP是什么,可以從下圖的主流編程和LOP方法過(guò)程進(jìn)行一下比較,它使得編程階段已經(jīng)不是瓶頸了,而轉(zhuǎn)移到了“創(chuàng)建”這一步,作者開發(fā)可一個(gè)通用的平臺(tái)(the Meta Programming System)來(lái)設(shè)計(jì)DSL,它允許程序員像現(xiàn)在編寫程序一樣非常容易的就可以定義自己的語(yǔ)言;這個(gè)平臺(tái)將完全支持LOP,給程序員為程序的每一部分選擇使用最合適的語(yǔ)言的自由,而不是將他們綁在某個(gè)固定的通用編程語(yǔ)言之上。

LOP可以用許多不同的方法來(lái)實(shí)現(xiàn),MPS只是Language Oriented Programming的一個(gè)示例,就像OOP的概念不等同于Java或C++或Smalltalk一樣。
LOP是什么
Language - Oriented Programming is a style of programming that tries to produce code that looks like it came from a Domain Specific Language but is still valid in a general purpose programming language.
LOP將不只是編寫程序,還包括創(chuàng)建用來(lái)編寫程序的語(yǔ)言
今天,百分之九十九的程序員認(rèn)為編程就是編寫一串計(jì)算機(jī)能夠執(zhí)行的指令集,但這種編程的觀點(diǎn)是有缺陷的,它混淆了編程的目的和手段,首先需要澄清一個(gè)事實(shí):一個(gè)LOP的程序,不是一串指令集。那它不是指令集,又是什么呢?
當(dāng)我有一個(gè)問(wèn)題要解決,我會(huì)用單詞、標(biāo)記、概念等來(lái)形成自己的解決問(wèn)題模型,這時(shí)候從未把它們想象成一堆指令集,而是一個(gè)在領(lǐng)域中一些特定的具有內(nèi)在聯(lián)系的概念集合。例如當(dāng)思考GUI領(lǐng)域時(shí),我會(huì)想象如何布局,這個(gè)按鈕到那邊去,這個(gè)輸入域到這邊來(lái),這個(gè)組合框里面需要有一些數(shù)據(jù)的列表,這時(shí)可能只是在頭腦中把它畫出來(lái),而根本不用任何語(yǔ)言。應(yīng)該有一種方法允許我們使用這種表述作為真正的程序,而不僅僅是通過(guò)與其它程序員交流的手段來(lái)編寫解決方案,一個(gè)程序是對(duì)某個(gè)領(lǐng)域的某個(gè)問(wèn)題領(lǐng)域以及解決方案的清晰而明確定義的模型表示。
這就是我認(rèn)為程序員應(yīng)該擁有創(chuàng)建他們自己的語(yǔ)言的自由的主要原因:GPL是無(wú)歧義的,但是太冗余和易于出錯(cuò);而自然語(yǔ)言表達(dá)能力十分豐富,但是又太不精確太不結(jié)構(gòu)化了;所以我們?cè)试S程序員可以自己創(chuàng)建一種結(jié)構(gòu)化的、精確定義的、能夠更加自然表示的語(yǔ)言來(lái)形成解決方案。因此LOP將不只是編寫程序,還包括創(chuàng)建用來(lái)編寫程序的語(yǔ)言;我們的程序?qū)⒈痪帉懙母咏鼏?wèn)題域而不是計(jì)算機(jī)指令集領(lǐng)域。
將程序直接存儲(chǔ)為結(jié)構(gòu)化內(nèi)容
因?yàn)楫?dāng)前的閱讀和編輯程序最方便和最通用的方法是使用文本編輯器,所以人們習(xí)慣性的認(rèn)為程序是作為文本來(lái)存儲(chǔ)的。但是程序的文本表示有重大的缺點(diǎn),其中最重要的是基于文本的編程語(yǔ)言非常難以擴(kuò)展;如果程序以文本的形式存儲(chǔ),你就會(huì)需要一個(gè)無(wú)歧義的文法器來(lái)解析程序;當(dāng)為語(yǔ)言加入新特性時(shí),維護(hù)語(yǔ)言無(wú)二義性的擴(kuò)展變得日益困難;我們將需要發(fā)明更多類型的括號(hào)、操作符、關(guān)鍵字、順序規(guī)則、嵌套,等等;語(yǔ)言的設(shè)計(jì)者們花費(fèi)了無(wú)數(shù)時(shí)間來(lái)思考語(yǔ)法,并試圖發(fā)現(xiàn)擴(kuò)展語(yǔ)言的新方法。
如果打算讓創(chuàng)建語(yǔ)言變得容易,我們就需要將程序的表示和存儲(chǔ)從程序本身分離開;我們應(yīng)該直接將程序存為一種結(jié)構(gòu)化的內(nèi)容,編輯器能夠提供我們喜歡的可視化表現(xiàn)形式;我們可以把程序做成文本、表、圖、樹、或其它任何形式,我們甚至能為不同目的使用不同的表現(xiàn)形式,比方說(shuō),圖形化表示用來(lái)瀏覽,文本化表示用來(lái)編輯;我們能夠?yàn)榇a的不同部分使用領(lǐng)域相關(guān)的表示,比如為數(shù)學(xué)公式使用圖形化的數(shù)學(xué)符號(hào)、為圖表使用圖形化的圖表、為spreadsheets使用行和列等等;我們能夠?yàn)閱?wèn)題域使用最合適的表現(xiàn)形式,可以是文本,但不限于文本;最好的表現(xiàn)形式依賴于我們?nèi)绾嗡伎紗?wèn)題域;表現(xiàn)形式的靈活性也將使我們的編輯器比以往更加強(qiáng)大,因?yàn)椴煌谋憩F(xiàn)形式有不同的方式去編輯它們。
(個(gè)人觀點(diǎn):感覺(jué)存儲(chǔ)為結(jié)構(gòu)化內(nèi)容,不需要解釋器進(jìn)行文法分析,有點(diǎn)類似意圖編程思想)
三要素:結(jié)構(gòu)、編輯器和語(yǔ)義
在LOP中,一種語(yǔ)言有很多方面,如約束和類型系統(tǒng),但LOP主要有下面三個(gè)要素來(lái)定義:
結(jié)構(gòu):定義了抽象語(yǔ)法、支持的概念
編輯器:定義了具體的語(yǔ)法,如何展現(xiàn)和編輯
語(yǔ)義:定義了行為,如何被解釋,以及如何被轉(zhuǎn)換成可執(zhí)行代碼
(個(gè)人觀點(diǎn):我覺(jué)得LOP語(yǔ)言有點(diǎn)建于在文本DSL和圖形DSL之間的一種形態(tài))
IDE支持
現(xiàn)今至少有三家主要廠商正為面向語(yǔ)言編程提供這一類工具:Charles Simonyi開發(fā)的Intentional Software,Microsoft的Software Factories和JetBrains開發(fā)的Meta Programming System。這些工具,Martin Fowler稱之為語(yǔ)言工作臺(tái)(Language Workbench),讓設(shè)計(jì)并使用DSL變得更加簡(jiǎn)單。這些工具提高了面向語(yǔ)言編程的競(jìng)爭(zhēng)優(yōu)勢(shì),雖然Fowler相信“還要過(guò)幾年大多數(shù)人才會(huì)考慮用[語(yǔ)言工作臺(tái)]來(lái)開發(fā)實(shí)際的項(xiàng)目。”
MPS(Meta Programming System)提供的軟件開發(fā)環(huán)境可以創(chuàng)建新的定制語(yǔ)言,也可以擴(kuò)展現(xiàn)有語(yǔ)言,然后用它們開發(fā)面向領(lǐng)域的應(yīng)用。它是在2003時(shí)作為一個(gè)研究項(xiàng)目而啟動(dòng)的,2004年時(shí)對(duì)LOP概念進(jìn)行了專門的描述(可參考此文)。MPS 是Martin Fowler在Language Workbenches: The Killer-App for Domain Specific Languages? 發(fā)明的,它是自由和開放源碼,并提供一個(gè)有趣的建立在Java上的語(yǔ)言擴(kuò)展的DSL新方法!
參考內(nèi)容:JetBrains元編程系統(tǒng)支持面向語(yǔ)言編程和DSL
使用MPS生成語(yǔ)言
應(yīng)用LOP的思想,使“創(chuàng)建新語(yǔ)言”更容易的方法,就是創(chuàng)建一種特定的專注于“創(chuàng)建新語(yǔ)言”這個(gè)領(lǐng)域的DSL;通過(guò)應(yīng)用這些創(chuàng)建語(yǔ)言的DSL可以使得容易的創(chuàng)建一種新的領(lǐng)域語(yǔ)言。下面先看看幾種創(chuàng)建語(yǔ)言的例子,以便我們能更好的理解它們是如何工作的。
結(jié)構(gòu)語(yǔ)言(Structure Language)

在實(shí)踐LOP的時(shí)候,大部分情況下,你會(huì)工作在兩個(gè)層次的編程中:元層次和程序?qū)哟;你在元層次中定義語(yǔ)言,在程序?qū)哟沃芯帉懗绦颉?br />
用Structure Language定義一種語(yǔ)言的抽象語(yǔ)法,只是枚舉這種語(yǔ)言所有的類型;類型簡(jiǎn)單的表示了這種語(yǔ)言支持的特性或者概念;每個(gè)概念應(yīng)該用它的名字、實(shí)例的內(nèi)部屬性、實(shí)例與其它節(jié)點(diǎn)之間的關(guān)聯(lián)關(guān)系來(lái)定義。存在兩種可能的關(guān)聯(lián);第一種是類似聚合的關(guān)聯(lián),它形成了概念模型的父子樹結(jié)構(gòu);第二種是非聚合的,自由形式的關(guān)聯(lián),它可以連接到系統(tǒng)中任何其它的節(jié)點(diǎn);關(guān)聯(lián)有兩個(gè)端點(diǎn):源和目標(biāo);關(guān)聯(lián)有角色,你可以定義每個(gè)角色的名稱、每個(gè)端點(diǎn)的多重性,每個(gè)目標(biāo)節(jié)點(diǎn)的類型;多重性可以是1, 0..1, 0..n, 1..n等,讓你能夠約束關(guān)聯(lián)可以創(chuàng)建多少連接;關(guān)聯(lián)的目標(biāo)類型可以被用來(lái)約束哪些類型的節(jié)點(diǎn)可以被連接在一起。
使用新語(yǔ)言編寫程序包括:創(chuàng)建語(yǔ)言中概念的實(shí)例、為實(shí)例的屬性賦值、根據(jù)語(yǔ)言概念定義的關(guān)系將程序中的節(jié)點(diǎn)連接在一起
編輯器語(yǔ)言(Editor Language)

編寫和操作概念模型的界面應(yīng)該是什么樣子的呢?經(jīng)驗(yàn)表明通用的編輯器不能像我們希望的那樣有用,所以MPS也支持我們?yōu)檎Z(yǔ)言定做特定的編輯器,它把程序和語(yǔ)言構(gòu)造成圖形。
MPS將程序存儲(chǔ)為圖形,但這不是我們一般說(shuō)的圖形編輯器,MPS的Editor Language是一種創(chuàng)建編輯器的語(yǔ)言,它有更好的靈感來(lái)源(個(gè)人觀點(diǎn):這點(diǎn)也是吸引我的地方)。
如果你用文本編輯器瀏覽一個(gè)典型的程序,你可以想象編輯器被分成了矩形單元;一些單元包含必需的標(biāo)識(shí)如關(guān)鍵字、花括號(hào)、圓括號(hào)等,其它的單元包含用戶定義的標(biāo)識(shí),如類和方法的名稱;大的單元由小的單元組成,像方法塊包含語(yǔ)句,而語(yǔ)句可能包含自己的嵌套塊;事實(shí)上,任何主流編程語(yǔ)言中任何良好構(gòu)造的程序都可以分解為矩形單元的集合;那么,在Editor Language中,你不需要想象這些單元,因?yàn)榫庉嬈骶褪呛?jiǎn)單的由矩形單元組成的。
單元的使用有一些有趣的優(yōu)點(diǎn);首先,當(dāng)直接工作在程序圖形而不是程序文本上時(shí),單元可以完美的模仿甚至超過(guò)標(biāo)準(zhǔn)的文本編輯器;第二,單元不局限于文本,你可以往單元里塞進(jìn)顏色選擇器、數(shù)學(xué)符號(hào)、圖表、矢量圖、或任何別的什么;最后,這種單元形式的layout是可選的,程序員可以提供不同的機(jī)制,單元形式的layout只是一種有用的缺省設(shè)置。
因此,Editor Language幫助你定義語(yǔ)言中每個(gè)概念對(duì)應(yīng)的單元的布局;你可以定義哪些部分是不變的,像括號(hào)或其它修飾符號(hào),哪些是可變的,需要用戶去定義的;Editor Language也幫助你在你自己的編輯器中加入強(qiáng)大的特性,像自動(dòng)完成、重構(gòu)、導(dǎo)航、語(yǔ)法加亮、錯(cuò)誤加亮、以及任何其它你想到的事情。
轉(zhuǎn)換語(yǔ)言(Transformation Language)
Structure Language和Editor Language已經(jīng)共同提供了一些功能,你能夠用它們和其他人交流思想,比如畫UML圖,或者編寫其它類型的文檔;然而,大部分時(shí)間我們是想讓我們的代碼做點(diǎn)什么,因此必須找到一種方法讓它能夠執(zhí)行;有兩種主要的方式來(lái)做這件事情:解釋和編譯
DSLs支持的解釋方式幫助定義計(jì)算機(jī)應(yīng)該如何解釋程序,DSLs支持的編譯方式幫助定義如何為程序產(chǎn)生可執(zhí)行代碼。
下面主要說(shuō)明一下MPS是如何支持編譯方式的。
編譯意味著拿到源代碼,并從中產(chǎn)生某種形式的可執(zhí)行代碼;對(duì)于結(jié)果代碼有多種可能的形式;為產(chǎn)生可執(zhí)行代碼,你可以生成本地機(jī)器碼,也可以生成虛擬機(jī)字節(jié)碼;或者,你可以生成另外一種語(yǔ)言的源代碼(比如Java,C++),然后用現(xiàn)有的編譯器轉(zhuǎn)換為可執(zhí)行代碼;類似的,你甚至可以產(chǎn)生某種解釋型語(yǔ)言的源代碼,用現(xiàn)有的解釋器解釋執(zhí)行。
為了避免處理這么廣泛的目標(biāo)格式,我們的方法是用MPS來(lái)做每一件事;首先,你在MPS中使用Structure Language定義一種目標(biāo)語(yǔ)言,這種目標(biāo)語(yǔ)言和目標(biāo)格式之間應(yīng)該有直接的一對(duì)一的映射;例如,如果你的目標(biāo)格式是機(jī)器碼,你應(yīng)該用MPS定義一種對(duì)應(yīng)機(jī)器碼的目標(biāo)語(yǔ)言;如果目標(biāo)格式是Java源代碼,你應(yīng)該定義一種類Java的目標(biāo)語(yǔ)言;目標(biāo)語(yǔ)言不必支持目標(biāo)格式所有的功能特性,只為你需要的語(yǔ)言特性進(jìn)行簡(jiǎn)單的一對(duì)一的映射即可
那么現(xiàn)在,編譯分為兩個(gè)階段:一個(gè)簡(jiǎn)單的從目標(biāo)語(yǔ)言到最終結(jié)果的翻譯,一個(gè)更復(fù)雜的從最初的原始語(yǔ)言到中間目標(biāo)語(yǔ)言的轉(zhuǎn)換;翻譯階段是微不足道的,因此我們把精力集中于更有意思的轉(zhuǎn)換階段;至少,現(xiàn)在的問(wèn)題簡(jiǎn)化為了如何將模型從一種語(yǔ)言轉(zhuǎn)換到另一種語(yǔ)言;但是,有可能源語(yǔ)言與目標(biāo)語(yǔ)言是完全不同的,導(dǎo)致轉(zhuǎn)換非常復(fù)雜,比如映射一個(gè)源節(jié)點(diǎn)到許多散布在目標(biāo)模型中的目標(biāo)節(jié)點(diǎn);我們想讓定義轉(zhuǎn)換盡可能的簡(jiǎn)單容易,因此我們需要一種模型轉(zhuǎn)換DSL來(lái)幫助我們;在MPS中,這種DSL被稱為Transformation Language
代碼生成有三種主要的方法,我們將結(jié)合使用它們來(lái)定義模型轉(zhuǎn)換;第一種是遍歷方式,你枚舉源模型中所有節(jié)點(diǎn),檢視每一個(gè),并基于檢視到的信息生成目標(biāo)模型中的一些目標(biāo)節(jié)點(diǎn);第二種方式是使用模板和宏來(lái)定義如何生成目標(biāo)語(yǔ)言;第三種方式是使用模式匹配來(lái)查找在源模型中的哪些節(jié)點(diǎn)上應(yīng)用轉(zhuǎn)換
我們通過(guò)定義DSLs把這些方式結(jié)合起來(lái)以支持任何一種方法;這些DSLs將一起工作來(lái)幫助你定義從一種語(yǔ)言到另一種語(yǔ)言的轉(zhuǎn)換;例如,遍歷方式激發(fā)了Model Query Language的靈感,它使枚舉節(jié)點(diǎn)和從概念模型中收集信息變得簡(jiǎn)單容易;你可以把它想象成某種針對(duì)概念模型的SQL;做為一種額外的獎(jiǎng)賞,擁有一種強(qiáng)大的查詢語(yǔ)言不只是對(duì)代碼生成有用(例如,能夠使編輯器更聰明)
模板(Templates)

模板方法工作方式類似Velocity或者XSLT;模板看起來(lái)很像目標(biāo)語(yǔ)言,但是允許你在模板的任何部分中添加宏;宏本質(zhì)上是當(dāng)運(yùn)行轉(zhuǎn)換的時(shí)候被執(zhí)行的代碼段;宏允許你檢視源模型(使用Model Query Language),并使用得到的信息對(duì)模板進(jìn)行“填空”,得到最終的目標(biāo)代碼
在上圖中,你可以看到為概念“Property”生成Java代碼的模板的定義,模板為屬性添加了field declarations, getters, setters等;這個(gè)模板是將代碼從Structure Language轉(zhuǎn)換為Java的生成器的一部分。當(dāng)使用一種模板語(yǔ)言的時(shí)候,可以認(rèn)為它是用目標(biāo)語(yǔ)言編寫的,只是某些部分的代碼是參數(shù)化的,或者是由宏來(lái)計(jì)算的;這種技術(shù)極大的幫助簡(jiǎn)化了代碼生成;模板還可以用在其它任務(wù)上,如重構(gòu)、代碼優(yōu)化、還有更多...
模式(Patterns)
模型的模式匹配方法給我們一種作為Model Query Language的代替的查找模型的強(qiáng)大方法;你可以把模式想象成概念模型的正則表達(dá)式;與模板方法類似,我們基于源語(yǔ)言產(chǎn)生模式語(yǔ)言;模式語(yǔ)言看起來(lái)像源語(yǔ)言,只是添加了一些特性,來(lái)幫助你定義處理復(fù)雜源模型匹配的靈活的標(biāo)準(zhǔn);你可以把這種方法想象成一種強(qiáng)大的“查找替換”的技術(shù);再一次,模式語(yǔ)言不只是對(duì)代碼生成有用,例如,它們?cè)跒樵凑Z(yǔ)言編輯器編寫自動(dòng)化的代碼檢查工具方面非常有用
記住Model Query Language, template languages, 和pattern languages都由強(qiáng)大的編輯器支持其自動(dòng)完成、重構(gòu)、引用檢查、錯(cuò)誤勘測(cè)、等等;即使復(fù)雜的查詢、宏、模式,都可以很容易的編寫;代碼生成從來(lái)沒(méi)有這么強(qiáng)大過(guò)
語(yǔ)言之間互相使用
前面有關(guān)代碼生成的章節(jié)帶來(lái)了一些關(guān)于這些語(yǔ)言如何一起工作的有意思的問(wèn)題;事實(shí)上有幾種方法能讓語(yǔ)言一起工作;在MPS中,所有的概念模型都互相知曉;既然語(yǔ)言也是概念模型,那么便意味著所有的語(yǔ)言都彼此知曉,可以潛在的被連接在一起。
語(yǔ)言彼此之間可以有不同的關(guān)系;你能夠通過(guò)擴(kuò)展現(xiàn)存的語(yǔ)言來(lái)創(chuàng)建新語(yǔ)言,繼承所有的概念,修改其中的一些,并加入你自己的概念;一種語(yǔ)言可以引用其它語(yǔ)言中的概念;你甚至能將一種語(yǔ)言插入到另一種語(yǔ)言中去;我將在以后的文章中討論進(jìn)一步的細(xì)節(jié)。
平臺(tái)、框架、類庫(kù)和語(yǔ)言
我們支持Language Oriented Programming的系統(tǒng)需要比元編程能力更多的功能才能更有用;它應(yīng)該提供程序員依賴于當(dāng)前的編程語(yǔ)言提供的所有事物:集合,用戶界面,網(wǎng)絡(luò),數(shù)據(jù)庫(kù)連接,等等;程序員不止是單單基于語(yǔ)言本身來(lái)選擇語(yǔ)言;例如,Java的大部分功能不是語(yǔ)言提供的,而是有成千上萬(wàn)的framework和API供Java程序員選擇;他們買的不是Java語(yǔ)言,而是整個(gè)Java平臺(tái);MPS也將有一個(gè)它自己的支持平臺(tái)。下面介紹隨MPS提供的三種最重要的平臺(tái)語(yǔ)言:The Base Language, the Collection Language, and the User Interface Language
Base Language
GPL支持近乎通用的語(yǔ)言特性諸如算術(shù)、條件、循環(huán)、函數(shù)、變量等等,而在MPS中也有這樣一種語(yǔ)言,它被稱為Base Language。Base Language之所以如此命名,是因?yàn)樗呛芏嘈枰揪幊讨С秩缱兞俊⒄Z(yǔ)句、循環(huán)等的語(yǔ)言很好的基礎(chǔ)。
它能夠以三種方式使用:你可以擴(kuò)展它以創(chuàng)建出你自己的基于它的語(yǔ)言,你可以在你的程序中引用它的概念,你還可以以Base Language生成你的代碼;將會(huì)有幾種可用的生成器來(lái)將Base Language轉(zhuǎn)換成其它語(yǔ)言如Java,C++等;當(dāng)然,不是每種語(yǔ)言都需要使用Base Language,但是在很多情況下,它是一個(gè)很好的起點(diǎn)
Collection Language
每種主要的主流語(yǔ)言都提供了對(duì)集合某種類型的支持,每個(gè)人都需要集合,如果每種DSL都提供自己的對(duì)集合的支持,那么將會(huì)出現(xiàn)語(yǔ)言之間的不兼容現(xiàn)象,這就是為什么MPS必須提供一種單一的Collection Language的原因。下圖顯示了一個(gè)例子,Collection Language是如何beats the tar out of a 類庫(kù)的;例子是一個(gè)計(jì)算一組給定的點(diǎn)的convex hull的算法

User Interface Language
User Interface Language是我們的平臺(tái)中下一種最重要的DSL;有趣的是,我前面提到的Editor Language能夠另人信服的用來(lái)提供用戶界面,但是一種專為圖形用戶界面設(shè)計(jì)的語(yǔ)言將會(huì)更靈活;這種語(yǔ)言帶來(lái)的益處是巨大的;Java Swing代碼就是一個(gè)想成為DSL的類庫(kù)的極好的例子:功能有了,但很容易被誤用,并且Swing的代碼是徹底雜亂的;很多如今的開發(fā)環(huán)境都包含GUI builder來(lái)簡(jiǎn)化用戶界面的創(chuàng)建;User Interface Language將把這項(xiàng)任務(wù)帶到一個(gè)更高的層次(這個(gè)我還不清楚)