2013/12/30

DSL(Domain Specific language) vs GPL(General Purpose Language)

DSL 不是 Digital Subscriber Line,也跟家裡面 ADSL 沒有關係,而是 Domain Specific language 的縮寫。GPL 也不是 General Public License,而是 General Purpose Language 的縮寫。

專有名詞的縮寫

學習專業知識,一開始都會被專業的縮寫搞亂,也要能將這些專有名詞縮寫脫口而出,才能嚇唬人,突顯自己的專業。DSL 不是比較常聽到的 Digital Subscriber Line,而是 Domain-specific language 中文有些人翻譯為領域特定語言,但依照中文的習慣,要念成特定領域語言,為了遵循英文原文的順序,還是應該改成「領域專用語言」比較順口。

跟 DSL 對應的語言為 GPL,GPL 也不是常常聽到的 General Public License ,而是 General Purpose Language 的縮寫,舉個簡單的例子來說,Java、C 都屬於 GPL,而 HTML、SQL、MathML、Unix Shell Script、groovy 等等語言都算是 DSL。

其實大家最常遇到的,最常見的,會是各式各樣的 DSL,而不是 GPL,嚴格地來說,沒有一種語言會是 GPL,形成某一種語言之後,就會馬上變成是 DSL了,因為總會有某一些應用,是無法簡單地用 Java、C 這樣的 GPL 所描述的,那究竟怎麼判斷,那一種語言是屬於 GPL 呢?

GPL 如何分類?

開發人員的逆襲: Domain-Specific Languages 裡面提到:Karl Frank 認為,DSL泛指任何特定領域的語言,甚至連 C#、Java 都算是特定領域的語言,因為它們都是針對特定目的(軟體開發),用於特定場合的語言。就軟體開發這塊領域而言,C#、Java 可運用於各類型的軟體開發,所以我們通常將它們視為GPL。

但其實在分辨 GPL 的時候,必須還要再加上子分類,必須先知道是那一種類別的 GPL,從 Is UML a domain specific language (DSL)? 的討論得知,當我們在討論 Programming Language 的時候,C、Java 就是一種 General Purpsose Programming Language,而討論 Modeling Langage 的時候,UML就是一種 General Purpose Modeling Language,而 XML 是一種 General Purpose Markup Language。

Java 跟 Groovy 的關係,就像是 Erlang 跟 Erlang OTP 的關係一樣,Erlang 可類比 Java,而 OTP 並不屬於 GPL,他是一種 DSL,適用的領域是 high concurrency 與 distributed 的伺服器運算環境。

Compiler

講到程式語言,就馬上會回想起十幾年前學習的 Compiler,當時老師教的是 Lex(Lexical Analyzar) 與 Yacc(Yet Another Compiler Compiler) ,雖然是有學過,也可以很順口地落出 lex and yacc,但也僅只於此,再深入的東西也都忘光沒有了。你可以自行參閱 Lex 與 Yacc 介紹以lex/yacc實作算式計算機

如果想要做個新的語言編譯器,a list of compiler books — 汗牛充棟的編譯器參考資料 列出了一堆相關書籍,但我想我應該不會跳進那個大坑洞裡。

在 Java 領域中,就必須要認識 ANTLR,ANTLR 是 ANother Tool for Language Recognition 的縮寫,從 使用 Antlr 開發領域語言 得知,ANTLR 是用來開發一種 DSL 的工具。

大概的過程就是先撰寫語法定義 Compiler.g,定義好語法之後,用 ANTLR 產生詞法分析器和語法分析器,使用這個分析器,就可以用來驗證,我們輸入的語言expression,到底有沒有符合這個語言的定義規則,ANTLR支援,可以將分析器生成為 Java,C#,C,Python,JavaScript 等多種語言。

另外還有個工具 Antlrworks,可將 .g 的語法定義檔案,用視覺化的方式呈現出來。

為什麼要了解 DSL?

當你進入 IT 的領域,想要學習使用關聯式資料庫時,別人就會建議你去學SQL,想要當個 SE,就會建議你要學習 shell script,想要學習網頁程式設計,就會建議要學習 Javascript、HTML、CSS 等等東西,每一種語言都是一種工具,是前人為了特定的目的,而定義出來的一種特殊的語言。

重要的是,當我們學習某一種語言的時候,要很清楚的知道,這個語言的使用範圍跟目的。雖然也會有意外的創新發生,例如原本設定在網頁上使用的 JavaScript,轉身一變,成了運作在 nodejs 之下的一種熱門的 Server Side 語言。

DSL 的目標是要為了解決商務業務邏輯與特殊應用領域,跟GPL之間的距離,對於系統設計者來說,先了解 DSL 的理念與技術,才能以最適當的方式,設計出一套最適合的 DSL 語言,當然,所有的設計,都必須符合「恰當」的要求,不能為了設計而設計,以免變成了畫蛇添足,甚至是增加負擔的 DSL。

2013/12/25

DSL - Domain Specific Language 簡介

Martin Fowler 針對 DSL 的主題,寫了一本書 Domain Specific Language(有篇文章提供了讀後心得:領域特定語言,被忽視多年的編程利器),另外也有一篇短文 Language Workbenches: The Killer-App for Domain Specific Languages?,根據這篇文章,在 InfoQ 還有一個演講影片 Introduction to Domain Specific Languages

以下以自己的理解,來解釋 Martin Fowler 想要說明的東西。

Language Oriented Programming

DSL 並不一種嶄新的概念,Martin Fowler 認為的新趨勢是 Language Oriented Programming,也就是要用設計一個新的 DSL 的想法,嘗試去做一個更具有彈性的程式實作,他先以一個例子來說明 DSL 的發展過程。

  1. 一開始因為有一份 Evet Data 純文字文件,它有特定的格式,因此產生了撰寫程式處理這個文字資料的需求。

    SVCLFOWLER 10101MS0120050313.........................
    SVCLHOHPE  10201DX0320050315........................
  2. 接下來他用了一個 class diagram,strategy pattern 說明他寫的Java處理程式,基本的想法,就是根據 Data 前面四個字元的識別 keyword,來判斷要使用那一種 strategy,以處理某種特定的Event。

    public void Configure(Reader target) {
     target.AddStrategy(ConfigureServiceCall());
     target.AddStrategy(ConfigureUsage());
    }
    private ReaderStrategy ConfigureServiceCall() {
     ReaderStrategy result = new ReaderStrategy("SVCL", typeof (ServiceCall));
     result.AddFieldExtractor(4, 18, "CustomerName");
     result.AddFieldExtractor(19, 23, "CustomerID");
     result.AddFieldExtractor(24, 27, "CallTypeCode");
     result.AddFieldExtractor(28, 35, "DateOfCallString");
     return result;
    }
  3. 後來他發現,可以將程式抽象化,拆分成兩個部份,就是用固定的程式碼,搭配一個 XML 設定檔。可以用某個 XML Reader 將設定讀進來,然後再對應到上面那個步驟的 strategy class,這樣的好處是,不需要重新編譯程式碼,改寫設定,就可以直接執行。

    <ReaderConfiguration>
     <Mapping Code = "SVCL" TargetClass = "dsl.ServiceCall">
         <Field name = "CustomerName" start = "4" end = "18"/>
         <Field name = "CustomerID" start = "19" end = "23"/>
         <Field name = "CallTypeCode" start = "24" end = "27"/>
         <Field name = "DateOfCallString" start = "28" end = "35"/>
     </Mapping>
    </ReaderConfiguration>
  4. XML 的標籤看起來太礙眼了,可以用另一種更簡潔的語法,來描述這個設定。

    mapping SVCL dsl.ServiceCall
     4-18: CustomerName
     19-23: CustomerID
     24-27: CallTypeCode
     28-35: DateOfCallString
  5. 最後,我們可用另一種自訂的 syntax 語法來改寫,因為要是一種語言,就必須要符合 EBNF 的定義規則。

    mapping('SVCL', ServiceCall) do
     extract 4..18, 'customer_name'
     extract 19..23, 'customer_ID'
     extract 24..27, 'call_type_code'
     extract 28..35, 'date_of_call_string'
    end

Language Oriented Programming 就是一種開發模式,嘗試用創造與使用 DSL 的方式,來完成一個軟體系統。基本上,所有用 DSL 設計的系統,都可以用 GSL 的方式完成。

Internal vs External DSL

接下來,Martin Fowler 說明了 Internal 跟 External DSL 的差異。

他問了一個問題:以下這個設定的程式碼,是不是一種 DSL?

public void Configure(Reader target) {
    target.AddStrategy(ConfigureServiceCall());
    target.AddStrategy(ConfigureUsage());
}
private ReaderStrategy ConfigureServiceCall() {
    ReaderStrategy result = new ReaderStrategy("SVCL", typeof (ServiceCall));
    result.AddFieldExtractor(4, 18, "CustomerName");
    result.AddFieldExtractor(19, 23, "CustomerID");
    result.AddFieldExtractor(24, 27, "CallTypeCode");
    result.AddFieldExtractor(28, 35, "DateOfCallString");
    return result;
}

答案要根據你在那一種 GSL 上運作,上面這些 code ,如果放到 Ruby,那就是 DSL,但如果在 Java,就不是 DSL,因為 Java 本身並沒有提供任何語言的擴充工具,讓我們可以直接處理這樣的 Configuration Code。

External DSL

  1. 跟運行環境的程式語言完全不同
  2. 需要有 compiler/interpreter 才能運作

缺點:

  1. 缺少IDE
  2. parser/generator 技術太複雜
  3. 自創的語法,產生了很多語言,會出現學習上的困擾及 gap,雖然用Inernal的方式,不需要學很多語言,但還是要學習使用特定的 API

Internal DSL

  1. 以運行環境的程式語言撰寫
  2. 直接使用該程式語言的 syntax

缺點:

  1. 跟運行環境的程式語言緊密結合在一起,例如 因為 ruby 語法的限制 4..18 就不能寫成 4-18
  2. Java, C# 這種 mainstream languages,很難做出 Ineternal DSL,因為當初設計時,就不支援 (不過Java7已經支援 scripting 了)

跳脫 XML,將視野放在 DSL

Martin Fowler 提醒我們,多數的 Java Programmer 會使用 XML,會知道怎麼製作設定檔,但是不知道其實設定檔,也可以再往前推進,形成一種 DSL,下一次當我們面對這麼多繁雜的設定檔時,或許該換個角度想想,是不是能用某種 script,設計出一種領域專用的 DSL 來解決問題。

2013/12/13

奇峰異石傳 - 鄭丰

奇峰異石傳回到雙主角的設定,應該是天觀雙俠的故事太成功了,奇峰異石傳依照這種雙主角的方式,也成了一部還算不錯的武俠小說。還有另一個特別的地方,就是請李阿寬先生畫的插畫,插畫的品質看來是很高的,但可能受限於小說版面大小的限制,畫面上有些細節就看不清楚。

不知道是不是印刷的問題,墨色的深淺差異沒有很大,黑色的地方乍看就一團一團的,是不是要讓這些插畫,用印漫畫的方式處理才能突顯出價值?不過這樣可能會讓成本上升不少。

讀小說,通常都是把自己投射到某個主角身上,去想像故事情節跟畫面,插畫讓讀者更明確地描繪出主角跟人物的形象,雖沒有了想像自己就是主角的樂趣,但卻能幫助讀者以第三者的角度,去看這個故事。

說還算不錯的意思是,還是覺得有些不滿意的地方。

奇峰異石傳的配角群,沒有天觀雙俠那麼精彩,趙觀的情人們就有好幾個,光是跟這些不同的人相處,就能寫出很多對手戲。韓峰跟小石頭宇文還玉之間,很從頭到尾兩個人都連在一起,中間只一段時間出現過通雲。

小石頭從男變女,就像是梁山泊與祝英台一樣,也真難為男主角了,他跟小石頭互動那麼融洽,就算是經過通雲那一段,最後還是發現怎麼自己還是一直在想著跟小石頭在一起的時光。如果真發生在自己身上,首先就要先想想自己的性別跟性向的問題。從朋友變情人已經很不一樣了,自己的小老弟變成情人,韓峰還是經歷了一段時間才能適應,並確認自己的感情,不然總以為自己只是在照顧他,沒有別的私情。

可能是商業的考量,文末的地方,作者自己說有刻意想要縮短篇幅,結果最後還是變成三本。故事的長短應該不需要刻意為之,而是長短要恰到好處,長篇小說,讀起來要不讓人覺得疲倦(最近讀的死亡之門,就讓人有這種感覺,看完的時間只能一直推遲),想要一本接著一本趕快讀完,就成功了。短篇也有短篇的趣味,因言簡意賅而讓人意猶未盡,更有想像空間。

應該也沒幾個人能像布蘭登·山德森那麼神,點子那麼多,又能同時進行多個長篇故事,長篇故事不需要一次寫完,一本一本推出,而我們這些讀者就會自動一本接著一本買了。

奇峰異石傳讀來沒有讓人覺得疲累,從剛開始閱讀,只花了不到一週的時間,就把三本讀完了。

專訪鄭丰:隋唐亂世的奇峰異石,說一個相知相惜的武俠故事

十八分鐘 《奇峰異石傳》

[心得] 奇峰異石傳心得

奇峰異石傳

2013/12/9

陣學師:亞米帝斯學院 - 布蘭登.山德森

你能徒手在黑板上畫個完美的圓形嗎?陣學師可以,或者應該說,一個厲害的陣學師,必須要能徒手畫出多個完美的圓形,完成一個陣形,越複雜的陣形,就需要越多完美的圖形,更多能在正確位置的完美圖形。除了理性的陣形外,另外一部份,就是帶著感性的、藝術性的粉筆精,要能同時專精這兩項的陣形師似乎不多。

陣形師的戰鬥畫面,比不上迷霧之子系列,因為主角受限於地面與粉筆,並不會有身體上的接觸,就像是遊戲王卡牌一樣,出牌然後,等著現形的怪物攻擊對方的陣形。沒有對手間的身體互動,就失去了很多刺激的戰鬥畫面,再加上只能在原地,在地上畫畫,又再度失去了場景變換的趣味。

故事背景設定造成了戰鬥畫面的限制,就有點先天不良的感覺,也許就因為是這個原因,作者把發生故事的地點設定在學校,再加上懸疑的學生失蹤事件,聽起來,又產生了哈利波特跟科南的印象。

小時候上數學課,總是會遇到幾位能徒手在黑板上畫個完美的圓形的數學老師,通常都是教學上有獨到之處的老師,以手肘為虛擬的圓心,一瞬間就能畫出一個大圓,一下子就能讓底下的孩子驚呼並懷疑,這樣的圓到底是怎麼畫出來的,陣學師的陣形圖,除了圓形,有些還搭配了三角形,疊合出一些特定的交點,這是圖形幾何。

防禦線是簡單的直線切割,而攻擊線可以看作是sin正弦圖形,但更應該想是直線傳遞的橫波圖形,這能將能量直線傳遞出去的能量波形。如果我猜對了,也許能在續集看到縱波,單就形狀帶給人的感受,縱波感覺起來比橫波力量更集中,傳遞速度更快,問題是縱波比較不容易用粉筆表現出來。

陣學師並不像迷霧之子有那麼多原創的創新元素,故事更像是個可以在其他有名的故事中看到,整合許多元素,而混裝出的一個全新故事。

讀書心得:陣學師:亞米帝斯學院 The Rithmatist

完美九點圈