本書是Eric Evans對他自己寫的《領域驅動設計-軟體核心複雜性應對之道》的一本字典式的參考書,可用於快速查找《領域驅動設計》中的諸多概念及其簡明解釋。 其它本系列其它文章地址: [譯文]Domain Driven Design Reference(一)—— 前言 [譯文]Domain Driv ...
本書是Eric Evans對他自己寫的《領域驅動設計-軟體核心複雜性應對之道》的一本字典式的參考書,可用於快速查找《領域驅動設計》中的諸多概念及其簡明解釋。
其它本系列其它文章地址:
[譯文]Domain Driven Design Reference(一)—— 前言
[譯文]Domain Driven Design Reference(二)—— 讓模型起作用
[譯文]Domain Driven Design Reference(三)—— 模型驅動設計的構建模塊
[譯文]Domain Driven Design Reference(四)—— 柔性設計
Ⅲ.柔性設計
要讓一個項目加速發展,而不是被其自身的歷史包袱所拖累,需要一個能與之良好協作的設計,它會帶來改變。一個柔性設計。
柔性設計是對深度建模的補充。
開發人員扮演兩種角色,每種角色都必須通過設計來完成。同一個人可能扮演這兩個角色,甚至可以在幾分鐘內來回切換,但與代碼的關係卻不是這樣。一個角色是客戶端的開發人員,他們利用設計的方式將領域對象編織到應用程式代碼或其他域層代碼中。柔性設計揭示了一個深層次的潛在模型,使其潛在性變得清晰。客戶端開發人員可以靈活地使用一組最小鬆散耦合的概念來表示域中的一系列場景。設計元素以自然的方式融合在一起,其結果是可預測的,清晰的特征並且是健壯的。
同樣重要的是,設計必須服從於開發人員來改變它。要做出改變,設計必須易於理解,並能表達出客戶端開發人員正在使用的相同底層模型。它必須遵循該領域深層模型的概念,所以大多數變化都會在靈活點上柔性設計。其代碼的影響必須透明明顯,因此更改的後果將很容易預測。
• 使行為特征明顯
• 降低變更成本
• 創建與之合作的軟體開發人員
釋意介面
如果開發人員必須考慮組件的實現才能使用它,則封裝的價值就沒有了。如果原始開發人員以外的人必鬚根據其實現來推斷對象或操作的目的,新的開發者可能會推斷出一個意圖——操作或類只是偶然地執行。如果這不是意圖的話,那麼代碼可能暫時有效,但設計的概念基礎已經被破壞了,兩個開發人員將在交叉目的下工作。
因此:
命名類名和操作名來描述它們的效果和目的,而不用參考它們做出履約的方法。這減輕了客戶開發者理解內部的必要性。這些名字應符合通用語言,以便團隊成員可以快速推斷其含義。在創建它之前為行為編寫一個測試,以強制您的思維進入客戶端開發人員模式。
無副作用方法
多個規則或計算的組合的相互作用變得非常難以預測。開發人員調用一個操作必須理解它的實現以及所有委托的實現,以便預測結果。如果開發人員被迫刺破遮罩層,任何抽象介面的用處都是有限的。如果沒有安全可預測的抽象,開發人員必須限制組合爆炸,對可行的豐富行為設置較低的上限。
因此:
將儘可能多的程式邏輯放入函數中,返回沒有明顯副作用的結果。嚴格地將命令(引起明顯的狀態改變的方法)分隔成不返回領域信息的非常簡單的操作。當發現了一個符合職責的概念時,通過將複雜的邏輯轉化為值對象來進一步控制副作用。
值對象的所有操作都應該是無副作用的函數。
斷言
當操作的副作用只是通過實現而隱含地定義時,大量委托的設計就會成為一種混亂的因果關係。理解程式的唯一方法是通過分支路徑來跟蹤執行。封裝的價值失去了。跟蹤具體執行的必要性使抽象也失敗了。
因此:
狀態操作的後置條件以及類和聚合的不變性。如果斷言不能直接用你的編程語言編寫,請為它們編寫自動單元測試。將它們寫入符合項目開發過程風格的文檔或圖表中。
尋找具有相關概念集的模型,這些概念引導開發人員推斷預期的斷言,加速學習曲線並降低矛盾代碼的風險。
斷言定義了服務和實體修飾符的契約。
斷言在聚合上定義了不變性。
孤立類
即使在同一個模塊中,隨著依賴性的增加,解釋設計的難度也會大幅增加。這增加了理解的負擔,限制了開發人員可以處理的設計複雜性。隱式概念對此負擔的促進作用甚至超過了顯示的引用。
低耦合是面向對象設計的基礎。如果可以,一直這樣做。消除圖中的所有其他概念。然後類將完全獨立,可以單獨研究和理解。每個這樣的自包含類都顯著減輕了理解一個模塊的負擔。
閉合操作
大多數有趣的對象最終都只能做一些無法用基本元素來表示的東西。
因此:
在適當的情況下,在定義操作時讓它返回類型與其參數的類型相同。如果實現者的狀態在計算中會被用到,那麼實現者實際上就是操作的一個參數,因此參數和返回值應該與實現者有相同的類型。這種操作就是在該類型的實例集合中的閉合操作。閉合操作提供了一個高層介面,而不會引入對其他概念的依賴。
這種模式通常應用於值對象的操作。因為一個實體的生命周期在領域中具有重要意義,所以你不能創造一個新的實體來回答一個問題。也有一些操作在實體類型下閉合。可以向其主題對象請求一個屬性對象並取回另一個屬性。但總的來說,實體並不是那種適合成為計算結果的概念。所以,大多數情況下,這是一個尋找值對象的機會。
你有時會陷入這種模式的一半。參數與實現者匹配,但返回類型不同,或者返回類型與接收者匹配,參數不同。這些操作並不是閉合的,但是他們給與了思考閉合的一些優勢的想象空間。
聲明式設計
在程式軟體中不可能有真正的保證。僅以一種逃避斷言的方式命名,代碼可能會產生額外的副作用而這些副作用並沒有被排除在外。無論我們的設計如何以模型為導向,我們仍然最終編寫程式來產生概念上的交互效果。並且我們花費大部分時間在編寫樣板代碼上,而這些代碼並沒有實際增加任何意義或者行為。本章中的釋意介面和其它模式有所幫助,但是它們不可能給傳統的面向對象提供形式上的嚴謹。
這些是聲明式設計背後的動機。這個術語對很多人來說意味著許多東西,但通常它指示一種編寫一個程式或者程式的某個部分的方式,作為一種可執行的規範。對屬性的非常精確的描述實際控制著軟體。在它的各種形式中,可以通過反射機制或編譯時通過代碼生成來完成(基於聲明自動生成傳統代碼)。這種方法允許其他開發人員以錶面價值接受聲明。這是一個絕對的保證。
如果開發人員有意或無意地繞過它們,很多聲明式方法可能會被破壞。當系統難以使用或限制過多時,這很可能發生。每個人都必須遵守框架的規則才能獲得聲明式編程的好處。
一種聲明式的設計風格
一旦你的設計有釋意介面,無副作用函數和斷言,你就會進入聲明式領域。聲明式設計的許多好處都是在您具有可交流其含義的可組合元素,並且具有特征或明顯效果,或根本沒有可觀察效果時獲得的。
柔性設計可以使客戶端代碼使用聲明式的設計風格成為可能。為了說明這一點,下一節將介紹本章中的一些模式,以使規範更加靈活和聲明性。
圖上的形式主義(形式化的繪畫)
從零開始創建一個嚴格的概念框架是你每天都不能做的事情。有時在項目的生命周期中,您會發現並改進其中的一個。但是你可以經常使用和調整那些長期在你的領域或其他領域建立起來的概念系統,其中一些已經經過了幾個世紀的精煉和提煉。例如,許多商業應用程式都涉及會計。會計定義了一套完善的實體和規則,可以輕鬆適應深層模型和柔性設計。
有許多這樣的形式化的概念框架,但我個人最喜歡的是數學。讓人驚訝的是,在基本演算法上做一些改變是多麼有用。很多領域包括數學。尋找它。挖出來。專業的數學是乾凈的,可以通過清晰的規則組合起來,並且人們發現它很容易理解。
在本書的第8章討論一個真實世界的例子“Shares Math”,領域驅動設計。
概念輪廓
有時人們會為了靈活的組合而砍掉一些功能。有時候他們會把它封裝得很複雜。有時他們會尋求一致的粒度,使所有類別和操作達到相似的程度。這些都是過於簡單化的,不像一般規則那樣有效。但是他們通過基本問題來激發。
當模型或設計的元素被嵌入到一個整體結構中時,它們的功能會被覆制。外部介面並不表示客戶端可能關心的所有內容。他們的意思很難理解,因為不同的概念是混合在一起的。
相反,分解類和方法可能會使客戶端無意識去複雜化,迫使客戶端對象瞭解如何將小塊組合在一起。更糟糕的是,一個概念可能完全喪失。鈾原子的一半不是鈾。當然,重要的不是顆粒度的小大,但這隻是顆粒度的來源。
因此:
將設計元素(操作、介面、類和聚合)分解為內聚單元,同時考慮到您對領域重要分支的直覺。通過連續的重構觀察核心的變化和穩定性,並尋找解釋這些切分方式的基本概念輪廓。對比模型與領域一致的方面,首先讓它成為一個可行的知識領域。
基於深度模型的柔性設計產生了一組簡單的介面,這些介面邏輯上可以在通用語言中作出合理的聲明,並且沒有無關選項的干擾和維護負擔。
作者:Zachary_Fan
出處:http://www.cnblogs.com/Zachary-Fan/p/DDDReference4.html
如果你想及時得到個人自寫文章的消息推送,歡迎掃描下麵的二維碼~。