本週是編程範式系列的最後一次分享,讓咱們拉長視角,看向遠方,進入"元編程"的領域,在《冒號課堂》中起了個很酷的名字:"超級範式"。html
先給你們作一個小練習:java
如下哪些屬於編程語言:
A.Java B.Html C.Spring Bean Definition D.Comment正則表達式
答案是ABC,從中,咱們能夠感覺到編程語言的一些特性:編程
多樣性體如今哪裏呢?能夠是解決的問題不一樣,能夠是運行的環境不一樣,也能夠是用戶羣不一樣等。
咱們能夠用一個詞來歸納這種不一樣,就是"領域(Domain)"。而僅服務於某一領域的語言,稱爲"領域語言(DSL)"。dom
上面提到的html、Spring Bean Definition以及SQL都是領域語言,這裏列幾個更有趣的。jvm
Gradle是一個靈活的通用構建工具,讓java項目在構建上有了跨越性發展。能夠看到採用領域語言後,自有度有明顯的提升,開發人員也更容易進行擴展。編程語言
println 'This is executed during the configuration phase.' task configured { println 'This is also executed during the configuration phase.' } task testBoth { doFirst { println 'This is executed first during the execution phase.' } println 'This is executed during the configuration phase as well.' }
Cucumber是一個可以理解用普通語言描述的自動化測試工具,在普通測試工具可運行可跟蹤的基礎上,案例可讀性的大大提高了。工具
功能: 用戶登陸 爲了可以瀏覽網站只對在線會員可見的那些內容 做爲一名訪客 我但願可以登陸 場景: 用戶登陸功能 假如 沒有<somebody@somedomain.com>這個用戶 當 我以<somebody@somedomain.com/password>這個身份登陸 那麼 我應該看到<用戶名或密碼錯誤>的提示信息 並且 我應該還沒有登陸
在領域語言的幫助下,編程語言在"人性化"的方向上邁進了一步。學習
前面介紹了領域語言的概念,咱們一般會將其列到"工具"的範疇。如何成爲一個範式,就要引入"超級範式"元編程了。測試
元編程是編寫、操縱程序的程序。在傳統編程中,運算是動態的,但程序自己是靜態的;在元編程中,兩者都是動態的。
下面舉個處理客戶交易單的例子,採用通用語言Scala實現以下。
val t1 = FixedIncomeTradeImpl { tradeingAccount = NOMURA, instrument = IBM, currency = USD, market = NYSE, quantity = 100, unitPrice = 42 }
若是咱們站在編程外行的角度看,這段代碼是存在很多問題的。
下面使用領域語言進行優化,更加符合天然語言的表達。
val equityTrade = 100 discount_bonds IBM for_client NOMURA on NYSE at 42.ccy(USD)
具體實現上,採用了Scala的"隱式轉換"特性,這是一種元編程的方法。
object TradeImplicits { class InstrumentHelper(qty: Quantity) { def discount_bonds(db: DiscountBond) = (db, qty) def equities(eq: Equity) = (eq, qty) } }
目前來看,元編程仍是比較依賴於語言層面的支持,以Ruby、Groovy爲表明的動態語言支持最佳,Scala提供了部分支持。可是從整體看,更爲主流的Java語言還沒有提供支持。比較可行方法是採用Scala、Groovy等jvm語言,嵌入Java代碼中進行實現。
元編程從實現複雜看並不亞於通用語言,篇幅有限沒法深刻,對細節感興趣建議你們閱讀《領域專用語言實戰》。
最後,想用Martin Fowler的一段訪談來小結下。原文地址
InfoQ:面對某個領域的多種變化,咱們應該怎樣利用領域特定語言,比方說在開發某個產品線的時候?
MF:和其它許多事情同樣,我不認爲領域特定語言的代碼和其它代碼有多大的區別。領域特定語言可以表達人們更深層次的思想是由於,和普通的命令-查詢式API相比,領域特定語言以一種更加天然的方式表述領域內的不一樣變化。
領域語言的價值在於更加"人性",更易於使用。其出發點是一種"減法思惟",經過限定外部使用範圍而得到了更好的內在價值。
InfoQ:領域特定語言看起來很擅長解決某個系統內的子域問題,好比說系統配置管理。項目組該如何在創造一種可以覆蓋多個領域的複雜龐大的領域特定語言和多個小領域特定語言之間作出取捨?
MF:咱們其實很是鼓勵使用許多小的領域特定語言。比方說你不會試圖去擴展正則表達式來設計HTML頁面,也不會用CSS來進行文本匹配。對咱們來講,讓領域特定語言不同凡響的正是其有限表達這一特性。
在使用上,領域語言之間能夠互相組合,和而不一樣,目標是發揮1+1>2的效果。
InfoQ:一些組織和項目不接受領域特定語言的主要緣由是什麼?是由於複雜性,仍是由於缺少對問題域和解決方案域的瞭解?
RJP:除了新的工具和開發流程這些問題,使用領域特定語言還須要用新的思惟方式思考問題。關於哪些是構成好的領域特定語言設計的因素,還有待於咱們去逐步發掘。固然也少不了「咱們好久之前就據說過」的關於業務可讀/可寫程序的觀點以及它所引起的懷疑。
我最先接觸領域語言概念,是在學習Ruby語言的過程當中,當時的感覺徹底是顛覆式。因爲涉及到思惟方式的轉換,也是限制領域語言發展的一個重要因素。目前,領域語言並未成爲業界的主流解決方案,但其思考之深入、思路之精妙讓人很是驚豔,碼農們若是但願開拓視野、提高自我,強烈建議學習。