Friday, January 19, 2018

Never build an Application

最近看了一篇談軟體設計的文章,文章是 Never build an Application 。主要的概念大概有幾項:
1. Never build an application. Build a library of reusable functions specific to the problem domain instead.  不要針對「需求」設計一體成形的應用程式做為解決方案。取而代之的是,要對「需求」設計一套可復用的函式庫,透過函式庫來做出解決方案。

2. 這套針對「需求」而產生的函式庫,可以視為是一種 domain specific language 。而它也可以是各種的形式: 比方說,一堆 class 可以提供的服務、一些 meta data 、 XML config 檔等。換言之,並不是一定要有特殊的語法,才可以看成是 DSL 。重點是在於,要做出一個「抽象層」,這個抽象層可以很好地對 problem domain 做很好的塑模。於是 application 就會變得很小,因為 application 是利用抽象層來做出的。

3. UML 在設計的應用上,有一個明顯的問題。它的塑模是針對 solution domain ,而不是針對 problem domain 。然而,DSL 的解法之所以有用的原因,是因為 DSL 是針對 problem domain 的 modeling 。

真的要講的話,其實這篇文章講的核心概念,和 Paul Graham 在 On Lisp 的序言中提到的 programming bottom-up 概念近乎一致。然而,我自己在實際的 clojure 程式設計經驗中,得到的心得啟發則是:

(*) REPL-driven development  是促成 programming bottom-up 的首要條件。

用不同的程式語言來開發,一方面是語言的表達能力不同。但是,更關鍵的一點是:語言對於「單元測試」的表達能力也有差異。使用 OOP 來開發時,單元測試的最小單位,往往就已經是物件,所以最小的抽象層,也往往要用 object 和 interface 來表達。 而使用 Lisp 語言的話,因為最小的測試單位是 REPL-driven development ,所以往往可以做出理論上最小的抽象層組件。

換言之,使用 Lisp 之所以可以導致 elegant design ,主要的原因在於 REPL-driven development  。跟 Lisp 擁有最強大的 macro system 的關系則比較小一些。使用其它的程式語言來開發時,只要貫徹「讓被測試的組件最小化」的原則,也一樣可以做出高品質的抽象層。