開發人員的逆襲: Domain-Specific Languages

本文最後的更新日期為 2008-4-26

軟體開發技術不斷改進,其背後推動的力量主要是為了應付軟體固有之複雜與善變的特性,而解決這些問題的其中一項重要關鍵,就在於抽象化(abstraction)。觀察整個軟體開發技術演進的歷史,可以發現它其實就是不斷提高抽象層次的過程。舉例來說,電腦只看得懂機器碼,因此組合語言便可視為第一次抽象化的成果--它讓程式設計師更容易撰寫程式碼。後來出現的高階語言,如 C 語言、Pascal 等,則又再提升了程式語言的抽象層次,直到我們現在使用的 VB、C#、Java 等,不難看出每一代程式語言的功能與抽象層次都不斷提升。然而,軟體系統的規模與複雜度也同樣與日俱增,那種訪談需求之後立刻埋頭寫程式的做法已經無法應付複雜的軟體系統,因此我們需要分解複雜系統的方法,將事物理出一番頭緒,並利用人類更容易理解的文字或符號來表達我們的設計。經過多年的努力與整合,軟體開發社群終於對如何表達設計有了共識:UML。

模型驅動

剛開始,UML 只是用來表達問題領域概念的工具,讓我們可以將軟體設計的想法以一套多數人都能理解的符號呈現出來,方便與他人溝通、討論。能夠做到這樣,UML 就已經是貢獻良多了。畢竟,軟體工程社群也是花了十幾年才逐漸達成此共識(如果從 1990 年代的 OMTOOSE、和 Booch'93 算起)。然而模型最終還是得透過程式語言實作出來,從抽象概念到具體實作,這當中有太多繁複的細節需要開發人員填補,於是,我們不斷在 OO 專案中討論究竟模型要畫到多細(文件要堆多高)才夠、table schema 究竟什麼時候才可以開始設計、要不要用 OR mapping...諸如此類的,其過程不只麻煩,開發成本也高。試想,要是模型畫好了,就能夠直接產生可執行的程式碼,不就一舉消弭了分析設計和實作之間的鴻溝嗎?對此問題,以 UML 為基礎所衍生的解決方案主要是 executable UML 和 OMG(Object Management Group;物件管理組織)提倡的模型驅動架構(Model-Driven Architecture;MDA)。

回想數年前,當時去參加一場 OOAD 課程,休息時間私下請教講師,他們的團隊是否真的有用那套 modeling 工具的 code-gen 功能(從畫好的 UML 模型自動產生程式碼),答曰沒有。那麼,現在的 UML 塑模工具是否已經進步到足以讓我們在實際的專案開發中使用 code-gen,甚至逆向工程(從程式碼產生模型)呢?支援 MDA 的工具,其模擬、驗證模型、以及產生程式碼的功能是否真的實用,且值得我們投資(購買工具、學習如何使用工具、以及描繪模型)?

關於這點,個人是抱持懷疑的態度。UML 原本就是用來表達較高層次的抽象模型,這模型是給人看的(而不是機器),其基本表示法在語意上並未精確到能直接和實作對應。然而,就算用上 stereotypes、tagged values、和 OCL(Object Constraint Language),如此是否就夠精確、完整,還是令人存疑;若要做到精確、完整的表達,是否又會弄出一套非常複雜的表示法(例如 MDA 的另一項關鍵技術:Meta-Object Facility;簡稱 MOF),也是需要考慮的因素。想用 UML 畫出可直接執行的模型,或者將模型直接轉成可執行的程式碼,距離實用的程度似乎還有一些距離。Booch 在 2004 年 MDA Journal 中說的一段話或許是最好的註腳:

「唯有當塑模的概念能夠直接對應到領域概念,而非電腦技術的概念,MDA 方能展現其完整價值。」
(The full value of MDA is only achieved when the modeling concepts map directly to domain concepts rather than computer technology concepts.)

如此說來,難道軟體開發的過程就無法再系統化、自動化一些嗎?既然以 UML 呈現的抽象分析設計模型不夠精確,那麼是否有什麼方法可以讓我們用精確的方式描述問題領域,並直接與實作接軌?相較於 UML 和 MDA,微軟給我們的答案是 DSL 與軟體工廠(Software Factories)。

什麼是 DSL?

DSL 是 Domain-Specific Language 的縮寫,中文譯為「特定領域語言」(或譯「領域特定語言」),也就是開發人員為了解決特定領域的問題所定義的專用語言。Karl Frank 認為,「domain-specific languages」可以泛指任何特定領域的語言,例如 UML、XML,甚至連 C#、Java 都算是特定領域的語言,因為它們都是針對特定目的(軟體開發),用於特定場合的語言,這是比較廣義的看法。不過,就軟體開發這塊領域而言,UML、C#、Java 可運用於各類型的軟體開發,所以我們通常將它們視為通用目的語言。另一方面,由於微軟近年大力提倡 DSL 及其支援工具,因此當我們提到 DSL 時(至少在討論 .NET 平台上的軟體開發時),通常是指微軟提出的概念和支援工具,而講到「特定領域語言」(domain-specific languages)時,則可能泛指任何特定領域的語言。

Martin Fowler 指出,DSL 並不是新觀念,早期 Unix 的 "little languages" 使用 lex 和 yacc 產生程式碼,以及在 LISP 中定義的語言,都是運用 DSL 技術的例子。微軟方面最早則是由 Charles Simonyi 開始研發支援 DSL 程式設計的工具,他稱之為「Intentional Programming」。為了明白區分,Fowler 將所有使用 DSL 的程式設計方式統稱為「語言導向程式設計」(Language-Oriented Programming),而將支援語言導向程式設計的開發工具統稱為「語言工作檯」(Language Workbench)[1]。

呼~真多術語。其實大概知道有這些名詞就好,簡單地說,就像程式語言需要編譯器和 IDE 工具,DSL 也一樣需要編譯或解譯的工具才有實質的意義。

DSL 範例

有在寫程式的人其實多少都有用到 DSL,例如曾經紅極一時的 Delphi,它的 .DFM 檔案就是一種特定領域語言。我們只要利用 Delphi IDE 提供的視覺化拖拉設計方式,將控制項放在 Windows Form 上面,並設定其屬性,IDE 就會幫我們在 .DFM 檔案中產生對應的描述,其內容與格式類似這樣:

object Form1: TForm1
Left = 192
Top = 107
Width = 509
Height = 462
Caption = 'Form1'
object DBGrid1: TDBGrid
Left = 60
Top = 80
Width = 341
Height = 293
end
object Database1: TDatabase
AliasName = 'DBDEMOS'
Connected = True
DatabaseName = 'testdb'
LoginPrompt = False
end
end

當然,我們也可以為自己量身訂作一套特定領域語言。舉例來說,假設我們要設計一款射擊遊戲,此遊戲的每一關都有一隻魔王(boss),而我們希望用一個外部檔案來定義魔王的運動路徑,例如:

Stage: 1
BossClass: Dragon
InitialPosition: 400, 300
MovingPath1: (3,2,10) (-4,2,30) (5,-1,30) ......
MovingPath2: (7,-2,5) (12,0,10) ......

第 1 列到第 3 列分別描述了第幾關、魔王的類別名稱、初始位置,第 4 列則為魔王的第一種移動路徑,第 5 列是另一種移動路徑,其中每一對括弧中的三個數字分別代表 x 偏移量、y 偏移量、以及在該位置持續多少個時間單位。

為了處理魔王的運動路徑,我們自行定義了一種語言來描述這些資料,這就是我們的 domain-specific language。

上述資料也可用改 XML 格式來描述,例如:

<Stage>
<Number>1</Number>
<BossClass>Dragon</BossClass>
<InitialPosition>400,300</InitialPosition>
<MovingPath1>(3,2,10) (-4,2,30) (5,-1,30) ......</MovingPath1>
<MovingPath2> (7,-2,5) (12,0,10) ......</MovingPath2>
</Stage>

其實我們可以發現很多軟體技術都是採用 XML 來描述特定領域,例如 JSP 和 ASP.NET 應用程式的組態檔、Windows Presentation Foundation 使用的 XAML 等都算是特定領域語言的應用。

以上所提的例子都是純文字的 DSL,但是它也可以是圖形符號。文字型的 DSL 好處在於容易給電腦處理,例如字串的搜尋、代換,以及文字內容的差異比對、合併等等。圖形式 DSL 的優點則是一目瞭然,很容易掌握整個模型的概觀以及各元素之間的關係。微軟的 DSL 是偏向以圖形符號的方式呈現。

誰要使用 DSL?

DSL 既然是處理特定問題領域的語言,除了程式開發人員之外,領域專家(domain expert)也必須會用。此時外部 DSL 就明顯佔優勢:你可以為特定領域定義一套比較簡單的,甚至連 end-user 都能夠自行修改的語法。DSL 擁護者認為(希望),將來一定會演進到由 end-user 自行修改領域邏輯的地步,屆時程式開發人員大部分時間都會用在開發 DSL 支援工具上面,而不是與不斷變動的需求奮戰。這種境界似乎太過美好,好到不夠真實。然而就算這一天真的到來,也不代表開發人員的工作內容將有一百八十度大轉變,或程式設計師會突然丟掉飯碗--軟體開發的工作總是需要優秀、嚴謹、細心的程式設計師。不過,有了 DSL,那些容易變動的軟體需求或許能夠大部分交給 end-user 自行掌控,讓他們也能調整軟體的行為;能夠由 DSL 控制的部份愈多,軟體的維護成本就愈低,開發人員也夠將心力投注在其他更有價值的工作上面。這或許是一個理想境界,但是退一步想,即使只有開發人員會使用 DSL,對提升軟體開發的生產力應該也有不少幫助。(怎麼個有幫助法?這部份等下次再寫一篇文章討論吧。)

在決定是否使用 DSL 時,還有一些問題必須考慮。首先,問題領域是否複雜到值得花費人力、時間來定義一套 DSL?如果只是一般的小問題,其實就用不著大費周章定義一套 DSL,至於哪種問題算大,哪種問題算小,這恐怕還得看每個 case 的情況,以及靠經驗來判斷。
Good judgment comes from experience. Experience comes from bad judgment.
Jim Horning


其次,如果 DSL 由領域專家負責撰寫,領域專家與程式設計師之間的溝通可能會是比較棘手的問題。而且,在結構化設計與物件導向設計世代交替時,系統分析師已經歷過一段學習 UML 的痛苦期,現在又要他們學習另一套(甚至多套)DSL,這恐怕會造成不少反彈。

開發人員的逆襲

UML 最近幾年在軟體工程領域可說是引領風潮,然而,隨著時代進步,更新更好的開發技術會不斷出現,UML 的地位也勢必面臨挑戰。這應是好事,至少可以提醒我們:到底 UML 對軟體開發帶來哪些好處?我們是否過度使用、推崇、甚至迷信 UML,以至於碰到任何問題都只想著該用哪種 UML 圖來表達?正如 Abraham Maslow 說的:「當你手中只有鐵槌,你會傾向將所有碰到的問題看成釘子。

個人的看法還是以實用觀點出發,在分析設計時,碰到覺得適合用 UML 圖形表達的,當然還是用 UML,但不用太在意如何第一次就把圖畫得盡善盡美,以及設想如何好好的保存這些圖,以免大部分的注意力侷限在畫圖這件事情上,原本分析設計的目的反而被模糊掉。

如果您有使用 UML,我想您應該會同意 UML 仍有它擅長的地方(表達較高層次的抽象概念),而且它仍然有持續擴充的機會。畢竟,UML 已經是廣為接受的表示法,在既有的基礎上改進,總是比另創一套新的語言更省力,這也是某些 UML 擁護者的看法。

從塑模的角度來看,UML 是從比較高抽象層次的角度出發,嘗試以通用的表示法來呈現系統分析設計的結果,然後逐漸細化,銜接到軟體的實作。DSL 則是強調與實作更緊密的整合,雖然它也是一種塑模語言,但我覺得它是比較從程式開發人員的角度出發,一種由下往上銜接的嘗試。

這樣的嘗試能否成功?

從現有的文章、討論、和書籍來看,微軟大約是從 2003 年開始研發推廣 DSL 和軟體工廠的概念,到現在已過了四個年頭,從 Visual Studio 對 DSL 的支援,我們可以看出微軟正逐漸落實軟體工廠的理念。此方法若能廣為軟體開發社群接受,想必又是一次典範轉移。至於結果如何,還是讓時間來回答吧。

小結

DSL 的目標很明確,就是要協助軟體開發人員提高生產力。然而,要吸引更多軟體開發人員的目光,需要的是強大的輔助工具和令人眼睛為之一亮的殺手級應用。在這方面,微軟正不斷地加強 DSL Tools,而且微軟一向強調 eat your own dog food(吃自己做的狗食),再加上愈來愈多專家(如 Martin Fowler)的投入,其後續發展頗值得我們關注。

此外,如 Steve Cook 所言,DSL 只是協助軟體開發的其中一項工具,我們還必須有靈活的(agile)開發流程(process)、軟體框架(framework)、以及模式(patterns)的搭配,方能大幅提高生產力,而其最終的理想目標,是讓軟體開發也能像製造業的生產流程一樣,建立具有多條產品線的軟體工廠 [2]。關於軟體工廠的概念,可以參考 Jack Greenfield 的文章 [3];他和 Keith Short、Steve Cook、以及 Stuart Kent 等人合著的《Software Factories》有更完整詳細的介紹,中研院的吳信輝先生也曾發表過一系列「細說軟體工廠」的文章,可以用 Google 找到一些。

備註
  1. Martin Fowler, "Language Workbenches: The Killer-App for Domain Specific Languages?"
    URL: http://martinfowler.com/articles/languageWorkbench.html
  2. Steve Cook, "Domain-Specific Modeling and Model Driven Architecture," MDA Journal, January 2004.
  3. Jack Greenfield, "Software Factories: Assembling Applications with Patterns, Models, Frameworks, and Tools."
    URL: http://msdn2.microsoft.com/en-us/library/ms954811.aspx

Post Comments

技術提供:Blogger.