幾個禮拜前 Teddy 看了一點 DSL (Domain Specific Languages) 的書,後來有學弟問 Teddy 使用過 external DSL 還是 internal DSL,Teddy 答曰:『只用過 external DSL』。沒想到
看一小段從 What's New In Quartz Scheduler 2.0 節錄下來的文字:
The most obvious differences with version 2.0 are the significant changes to the API. These changes have aimed to:
modernize the API to use collections and generics, remove ambiguities and redundancies, hide/remove methods that should not be public to client code, improve separation of concerns, and introduce a Domain Specific Language (DSL) for working with the core entities (jobs and triggers).
講到這邊先稍微介紹一下 Quartz,這是一個用 Java 開發的開放原始碼工作排程系統(job scheduling system),這樣的系統有什麼用途呢?假設鄉民們所開發的軟體需要定期的執行許多工作,例如,
- 每一,三,五的晚上三點半執行備份檔案工作。
- 每天早上七點叫你起床
順便泡一杯咖啡。 - 隨時(每 5 秒)幫你監看硬碟中的檔案是否有異動。
- 每個月第一個禮拜四提醒你去繳信用卡卡費。
- 每隔兩週的週四下午一點幫你發 sprint demo meeting 的開會通知。
- Scheduler:用來排程工作與觸發工作的物件。Scheduler 可以設定 thread pool size,用以決定同時間有多少個 thread 可以執行 job。
- Job:要執行的工作邏輯定義在你自己的 Job 物件上面(要實做 Quartz 的 Job interface,如下圖所示)。基本上 Job interface 就類似 GoF 裡面的 Command pattern,只定義了一個 execute() method。
- Trigger:用來紀錄『觸發時間』的物件,一個 trigger 物件必須要關聯到一個 job 才會發生作用,但是一個 job 卻可以有很多個 trigger。例如,你希望每天早上八點和下午八點自動執行資料備份的程式,那麼你就可以產生兩個 trigger 物件,把他們的 start time 分別設定為早上八點和下午八點,然後再將這兩個 triggers 與備份資料的 job 建立關聯並使用 Scheduler 來排程這兩個 triggers。如此一來 triggers 設定時間一到 Quartz 就會自動執行這個 job。請看以下範例(Quartz 的 CronTrigger 物件有支援使用 Cron expression 來設定觸發時間,會用之後還滿方便的)。
- JobDetail:雖說 Quartz 『概念上』是將 trigger 關聯到一個 job 身上,但實際上在 Quartz 的實做中 trigger 是關聯到一個稱之為 JobDetail 的物件上。JobDetail 首先會關聯到某個 job,此外 JobDetail 還有一個 Map 物件,可以用來『夾帶』任何需要傳給 job 的資料,如下圖所示。
***
以上扯了這麼多,都沒還講到 Quartz 的 internal DSL。上面的程式碼是 Quartz 1.8.x 版的程式碼,鄉民們可以發現 Quartz 是採用 getter/setter 的方式來操作 JobDetail 與 Trigger 物件。到了 Quartz 2.0.x 版之後,Quartz 改用了 internal DSL 的方式來產生 JobDetail 與 Trigger。請看範例:
這是 Quartz 1.8.x 版的範例
這是 Quartz 2.0.x 版的範例
兩相比對之下就很容易看出不同之處。套用 Martin Fowler 在書中(Domain-Specific Languages,p. 16)的講法,Quartz 1.8.x 版使用的是 command-query API,而 Quartz 2.0.x 版則改用 fluent interface。
***
雖然剛開始不習慣,但 Quartz 的 fluent interface 用久了還滿好用的說...時間不早,該睡了,明天 8:30 還要開會....***
友藏內心獨白:今天有點拼...XD。
其實在書上也有個類似的例子,
回覆刪除但我看到時有個疑惑,
為了讓Java程式看起來像Internal DSL,
讓method回傳自己或是某個物件,
這算是一種talk to strangers的smell嗎?
這跟jquery的機制算是一樣的嬤? 看起來好像是這麼一回事
回覆刪除jQuery不熟
回覆刪除不過當物件的每個method都回傳自己時
就可以這樣串XD
可是 ... 實在不知道這有什麼好處?
回覆刪除之前Quartz用了三年多的時間,大部分的時間都是用傳統的 setXXX() 的方式來設定 Quartz 排程所需的物件。改用 DSL 之後,剛開始不太習慣,覺得有點卡卡的。但是習慣之後,覺得語法比原先的 setXXX() 方式容易讀、寫很多,
刪除