我在《
小議領域模型Domain Model》討論了service和object,以及關聯邏輯(咳咳,該文中的一些觀點我已修正,合適的時候放上來)。關聯邏輯就是本文討論的重點--specification
一、從DDD(Domain Driven Design)說起
這個Specification來自DDD,DDD有對specification分為三個類型
1. Validation
2. Selection
3. Building
不過在初看這個Specification的概念的時候,相信很多人都有一種似曾相識的感覺。我們日常開發中, 基于SRC原則寫的那些xxxxProvider,xxxHelper,xxxChecker,而此外還有討論了無數遍的Dao。不就是這個specification嘛,換了一個馬甲嘛。
二、應用Specification的好處:
現在就是我要高舉specification的理由了。
1. 統一Domain model的相關支持邏輯,屏蔽了dao的存在。
請注意這個selection,即從repository中(通常是數據庫)取出合適的對象列表。嗯,這個有意思了,原來總覺的dao在系統中的地位挺尷尬的,
由于先前的開發理念,Domain Model沒有出現之前,我們是Transaction Script的開發模式,在ORM技術出現后,從TS轉向Domain過程中,數據庫訪問轉成dao層, 大量的約束邏輯則散落在Service層中。因而開發系統,無論是那張系統結構(架構)圖中(可以參考AppFuse),我們見貫了Dao層的存在,甚至我們習慣了Dao的存在。
而應用Specification則統一了這些概念,屏蔽了dao。dao做的最多的工作是查詢邏輯,而查詢邏輯也是一種邏輯嘛,和validation以及building都是支持Domain Model。這個specification算是給dao正名了。不過概念上正了名,如果僅僅在于此,恐怕大多數人都會說“嗯,不錯,但是還是那么不實用”:要是按specification的做法,也就是把dao的下的代碼分散出去,沒有獲得太多的好處,搞不好還給背上類型膨脹的罪名。別急DDD還有后手呢。
2. Specification引入了FP的開發思路
DDD可不是技窮于此,隨后就提出了specification的closure。明眼人一看就知道這個closure來自FP。
回顧一下函數式編程基本特性先: 1. 閉包計算和高階函數。 函數本身是first class對象,閉包是起函數作用并可以像對象一樣操作的。高階函數是可以接受一個函數為參數,并可以返回一個函數。 2. 延遲計算(lazy evaluation) 不是在函數綁定時計算,而是在求值時計算。 3. 遞歸的計算機制 4. 引用透明 同樣的輸入返回同樣的結果,與上下文無關。 5. 沒有副作用 賦值后不能更改,即是constant |
現在看看DDD三種specification的組合情況。
1. Validation的組合,DDD也給出了例子代碼--看著就清爽!
2. selection的組合,DDD并沒有給出例子。也不幸就是這個selection比較難辦,因為涉及到sql問題(這個問題往往又和性能連在一起)。剛好javaeye上有人開貼討論組合sql的問題(http://forum.javaeye.com/viewtopic.php?t=21760)
我的想法是:從domain object的角度把selection的組合范圍限制在where和order兩個clause。
這是最簡單的,不考慮select和from,更不考慮join了。對于同一domain object其where和order的組合是簡單的。DDD一書中的and,or和not操作是容易支持的。
接著要考慮支持join和union了。我估計應用系統中:普通的sql(不帶join和union),帶join和union的sql以及更復雜的sql語句的比例是4:4:2。
不過join處理實在麻煩,我需要一些額外的信息。所幸從試驗的代碼看起來還是可以接受的。
那么對于那些確實復雜的sql查詢怎么辦(那剩下的2)?簡單。單獨寫一個,我的觀點是太復雜的東東復用的可能性也不大,日后出現類似的東東可以考慮用OO的繼承的方式搞定,CO和OO本來就不是相互排斥的。
除此外,還有和domain object無關的”分頁”以及”top n”就可以獨立提供specification來。
(BTW:ajoo說不能光說不練,準備和buuawhl在sql的parser上作文章了。向偶像學習,抓緊試試看能不能作出來。)
3. building的組合
這個看起來像curry,沒有想好,暫時不討論。
除此之外,系統中其它很多邏輯可以用FP的思想做,如業務規則(業務規則分類看《DSL:基于規則系統組織業務規則》)中的Computation,至于業務規則的Constraint和Action enabler可以直接參考validation。
BTW:ajoo在javaeye的blog給出了一些很好的例子。
三、其它問題
到目前為止,一些看起來都還不錯。但是還有幾個問題沒有解決:
1. Selection的組合問題是否真的可以實現。
這個。。。嘗試中
2. 難道在開發中要為每一種類型的specification單獨寫組合操作的處理函數。難道不能有一種統一的。
到目前為止,還不能。 對于各個specification,無論是參數還是返回對象的類型,以及組合的細節都不同,我們不得不獨立處理。
2.1 首先是參數還是返回對象的類型,真的統一的話,就會變成這樣:
interface Action{ Object execute(Context ctxt); } interface Context{ Object get(String key); } |
很明顯這不是我們要的
2.2 另外就是組合細節問題:
buuawhl在
http://forum.javaeye.com/viewtopic.php?t=21533中列舉了3個不同類型都是我們要考慮的
3. 其它
還沒有想到,想到再說。