板橋裡人 2006/8/12更新
靈活設計可以使我們隨著專案開發的進行,感到速度越來越快,而不是越來越慢,甚至 停滯不前。靈活設計是對領域建模的補充,當我們從領域中抓住那些隱隱約約的線索和概念原型後,就象準備好原料;下面就是通過迭代將原料錘煉成一定具體的形狀,可以俗稱「打鐵」,那麼打鐵打到什麼形狀算可以了呢? 也就是最終希望達到什麼樣的設計呢?
有些軟體打著「靈活性」旗號,卻出現很多多餘的抽象和間接層次,從而導致了複雜性,靈活性可能導致複雜性, 但是靈活性不是導致複雜性的必然原因,如何將靈活性的發展通往簡單,其中精湛技巧就需要學習和不斷實踐, 正確的理論指導是必不可少的,模型驅動設計(mdd)提供這樣乙個科學的方**。
在eric evans的「領域驅動設計」一書中專門**了這樣提供靈活設計的模式和方法,下面簡要述說如下:
明顯意圖的介面
介面的名稱必須表達明顯意圖,而不是模稜兩可,介面雖然是抽象,但是也不能抽象到別人不知你所云, 如果其他開發人員必須檢視介面的實現子類才能搞清楚你這個介面的意圖,那麼你的介面抽象無疑是失敗的,
使用明顯意圖的介面可以將整個子領域切分成乙個個單獨模組,每個模組使用帶有明顯意圖的介面封裝起來, 這種切割方式用來調整專案的焦點和對付大型系統的複雜性。
如果僅僅有大型系統開發經驗,但是沒有大型系統的分割經驗,更重要的是良好設計理論基礎,那些大型 系統開發經驗也只是如過眼煙雲,不會在你的程式生涯中佔據多大的重要位置。
下面我們聚焦被劃分成單個模組的內部設計模式:
邊界影響
在軟體中,操作分為:命令和查詢,命令就是能夠使 系統狀態發生改變的操作,如增刪改等操作。這些操作都可能需要有副功能,如希望增刪改完成後還要返回一些結果,這些主要功能之外的副業,也稱為邊界影響(side effect)。一些傳統過程經驗的程式設計師經常喜歡搞「一機多用」,喜歡將很多功能揉合在一起。
大多數操作會呼叫其他操作,造成任意深度的巢狀,這樣形成乙個樹形結構的呼叫關係,這就容易使我們很難 **呼叫乙個操作會產生什麼樣的結果,呼叫乙個操作變得謹慎,甚至戰戰兢兢,雖然ioc或di container使 得這種巢狀關係的管理變得容易,但是不能保證每個操作本身的設計能降低複雜性,後者就是我們現在關注的。
為什麼我們呼叫乙個操作時會變得小心,因為這個操作設計時可能不執行主要功能,還有其他副功能,這些 副功能可以認為是一種多餘***,解決辦法很簡單:設計這個操作時消滅***;如果不能消滅,就將其 分離顯式分離並單獨表達出來。
所以,我們設計增刪改命令和查詢功能時,盡可能分離它們到不同操作中實現,不要在增刪改命令執行的同時 返回任何領域資料。
如果邊界影響不能通過設計避免,那麼我們就直面它,在增刪改等命令執行同時返回資料,當這樣做的同時, 我們就使用斷言assertion來約束我們這樣的設計,通過斷言能夠易於使用單元測試junit等工具測試。從而 保證你的命令簡單有規則。
總之還是那句有些哲學意義的話:對於邊界功能,首先要去除它,如果不能迴避它,就承認它,但是同時會約束它。
邊界影響主要的是service介面怎麼做的問題。在實際專案中,model和service是相互結合不斷重構的。那麼model和service粒度是如何界定的?
粒度界定
物件的粒度到底是多大?這沒有乙個統一的規律,哪些屬性或行為屬於a物件,哪些屬於b物件,有時又需要將這些屬性和行為分離以便能夠靈活組合。我們一般很難確定類的粒度到底是怎樣規模表示達到設計目的?
首先,粒度不能太大,造成重複和冗餘,很多概念混在一起;當然粒度也不能太細,以至於太碎,不能完整表達乙個領域概念,例如半個鈾原子就不再是鈾。
類需要盡量準確表達領域概念,大多數領域中都包含某種邏輯上的一致性,而很多程式設計師有時只注意單純的設計原則,忽視領域邏輯,設計思考時需要兩條腿走路,實現平衡,比如jdonframework的快取設計主要應對企業領域大量查詢都是在時間上相對集中的查詢(如本月度),因為領域中某種邏輯存在(時間上相對集中的查詢),才使得我們決定採取某種設計方案,如果沒有這個前提,任何設計方案都是可行的,這也是我們通常討論的業務場景。
每個人對業務領域中很多概念都可能不一致,但不能否認:領域中一定在某個地方存在一種旋律,我們的模型肯定能夠與領域某個部分發生共振,問題關鍵是:我們需要通過不斷發現的過程來尋找這種共振,這過程就依賴反覆的重構重整refactoring。
通過重構,使我們的設計適應我們重新理解了的領域概念和業務需求,概念輪廓(conceptual contour)就會浮現。
注意「概念輪廓」是指對領域中概念的主要輪廓,大概樣子,需要忽視不重要的細節,設計人員必須理解領域中概念在哪些地方會發生改變?哪些地方保持相對穩定,然後使設計的模型盡量與領域中概念穩定面結合起來,這樣,當業務領域中概念發生變化時,我們的模型才會隨之一起翩翩起舞,發生共振,從而達到模型設計反應領域本質的目的。
所以,類的粒度是要能夠反應領域的概念輪廓,將能夠反應概念輪廓的那些重要元素聚合到當前正在設計的類中,這也是設計中高聚合原則的體現。
高聚合、低關聯是兩個設計基本原則,上面我們談了如何做到高聚合,實際上,也是反映一種類或模組的粒度設計規模。下面談談低關聯:
消滅依賴
複雜的依賴關係無疑提高了系統的複雜性,加劇我們大腦負載,所以,我們的模型之間關係必須精練,減少依賴,最後保留下來的依賴代表了領域概念之間某種根本的關係。有的系統中,甚至是0關聯,從而得到乙個個被完全孤立的單獨的類(standalone class),這才是方向(也有利於我們簡化配置hibernate這些模型持久化框架,無需考慮一對多等關聯配置)。
每個依賴都是值得懷疑的,這是我們思考的前提,重構時,乙個個去消滅那些象蜘蛛網一樣密集的關係,斬斷它們,低關聯時減輕概念過載問題的基本方法,孤立類是低關聯達到極致的一種標誌。
減少依賴不是意味不考慮業務領域場景概念,武斷實現,依賴和之前描述的邊界影響一樣,有時確實不能消滅,那麼我們就承認它,但是會又有一套設計原則來約束它。
模型驅動開發(MDD)介紹
在過去多年,軟體開發面臨了多個挑戰,新的需求和存在系統不斷增長,系統也變得越來越複雜,以至於我們很難及時的構建它們。為了解決這些問題,就出現了很多新的方法,其中最突出的乙個就是模型驅動開發。mdd代表了一套理論和工業化軟體開發的方法框架,在軟體開發全生命週期中系統的的使用模型作為主要工件,它主要為了...
模型驅動開發(MDD)介紹
在過去多年,軟體開發面臨了多個挑戰,新的需求和存在系統不斷增長,系統也變得越來越複雜,以至於我們很難及時的構建它們。為了解決這些問題,就出現了很多新的方法,其中最突出的乙個就是模型驅動開發。mdd代表了一套理論和工業化軟體開發的方法框架,在軟體開發全生命週期中系統的的使用模型作為主要工件,它主要為了...
模型驅動開發(MDD)介紹
在過去多年,軟體開發面臨了多個挑戰,新的需求和存在系統不斷增長,系統也變得越來越複雜,以至於我們很難及時的構建它們。為了解決這些問題,就出現了很多新的方法,其中最突出的乙個就是模型驅動開發。mdd代表了一套理論和工業化軟體開發的方法框架,在軟體開發全生命週期中系統的的使用模型作為主要工件,它主要為了...