.NET領域驅動設計—初嘗
最近在研究DDD頗有收獲,所以整理出來跟大家分享,共同進步!
我們在設計業務系統的時候都會存在一個非常棘手而又無法回避的問題“業務擴展性”、“業務靈活性、”面向對象化“,盡管我們熟練掌握設計思想、設計模式、設計原則等等關于如何設計靈活性的系統設計理論,但是我們似乎都沒有將它們運用到真正業務系統設計、開發當中去,為什么?這樣的疑問如果對有心想設計好系統的朋友來說肯定是很早就出現過,只是無法解決,因為我們目前使用的設計方法是與面向對象設計背道而馳的。
漫長的數據庫驅動開發歷史,導致我們根本無法脫離這個環境進行學習和實戰。從教科書再到真正的企業項目開發都是先設計數據庫然后進行邏輯的編寫,大部分的業務邏輯都是存在于UI和數據庫【存儲過程、自定義函數】中,所謂的三層架構中的BLL層其實是形同虛設,根本沒有起到它應有的作用。
當然我們不是大師,我們只是普通的程序員,希望有一種方法論能引導我們進行真確的系統設計。在未接觸DDD之前,我也一樣有著同樣的困擾,我們編寫很多的開發框架、組件、插件、服務等等太多太多類似能提高開發效率的功能,夢想著自己的系統能想真正如書上所說的搭積木一樣搭建自己的系統,我們捫心問自己真的可以做到嗎?我嘆息,很難;
我一直感覺復雜的系統設計對我來說真的沒有辦法應付,只能憑借細心和對業務的熟悉程度,沒有正確的理論引導,那些所謂的大師們的設計思想的書真的對我幫助不大,看了不知道如何進行運用。時至今日我終于可以感覺到那種神秘的設計確實可以帶領我們穿越復發的系統設計。當然這條路對剛開始接觸DDD的朋友來說會存在很多問題,恰巧在下有幸接觸DDD有點心得,也通過分析了一個小的系統進行DDD的開發工作,所以在這里把自己最近研究的心得和疑惑跟同行們分享,如有不對的地方請多指點。
【1.1】疑問
在任何一項新技術被采納之前必須要解決幾個關鍵的問題,這也是我們程序員考慮使用一項新技術的必須過程,它的出現能解決哪些問題和將會帶來哪些問題。DDD固然很好,但是要想把它運用到自己的項目當中去,是需要很多時間和精力來分析它的實施過程和對項目團隊的要求。當然人為的因素和外在的環境問題我們這里不考慮,畢竟那些是我們無法改變的事情,這里只討論和我們密切相關的問題。
【1.1.1】UML何用
做程序開發的我們都知道UML是干什么的,簡單的講它屬于一種標準的系統建模語言,便于我們對系統進行分析和團隊之間的合作。既然是語言它的主要作用是溝通,技術人員和分析人間的橋梁。但是到目前為止我沒有發現它真正幫助過我進行系統分析和設計,上面已經提過其實是兩種開發方法論恰恰相反,所以導致根本無法集成,就拿UML中的類圖來講,我們都是先設計數據庫然后進行開發何來的對象?直接是表驅動,通過一些快速的代碼生成器進行界面和一些通用的單表的CDUS代碼的生成,程序中根本沒有對象的概念,業務邏輯遍布UI層[圖1.1]。UML畫的類圖無法在程序中表現出來,所以它無法在絕大部分的企業中普及。
1.1圖
上圖假設是一個簡單的模擬B2C的基本功能,通過它我們能簡單的了解到我們的系統開發的問題所在。
以上圖中的系統結構,我們很難知道系統的具體業務邏輯,更別說對系統的擴展性能有保障。這樣的結構在開發初期沒有什么問題,但是在后期的維護工作中將是費事費力的,最后的項目代碼無法進行的很好的閱讀,也就無法很好的進行穩定性維護。特別是業務系統,它的需求會變的很多甚至很變態,如果按照這種方式進行維護,那么界面上的代碼會越來越多,而BLL、DAL中的重復性的功能方法也會急劇變多或者是服務層的相同功能不同方法參數的代碼會越來越多。其實到最后也就談不上什么藝術了,更別說項目進行產品化后上市。
那么UML真的起不到作用嗎?或者說我們真的與UML無緣?當然不是,而是我們沒有使用相關的軟件設計、開發方法論而已。按照DDD的思想,我們是業務驅動開發,先進行領域模型的創建,然后才是數據庫的設計。其實只有按照DDD的開發理論來才能最大的保證系統的擴展性和業務整潔性,才能保證項目的良性循環。
#p#
【1.1.2】領域建模
“領域建模”很抽象也很藝術的一個詞,它是軟件設計藝術中的一個境界。
我們常常接觸面向對象編程、面向對象設計的書籍或者話題,大家都對它有獨特的見解,但是我們始終沒有將它用作真正的系統性開發中去。但是在編寫框架的時候我們都能得心應手的進行面向對象設計,為了保證框架的靈活性乃至最大的擴展性就要進行最細粒度的分解、抽象、提取,這些在非數據庫系統開發中都沒有問題。然而最大的問題出在對象需要與數據庫結合,對象的生命周期持久化在數據庫中,生也數據庫死也數據庫。所以這里的問題就是如何在面向對象設計與關系型數據庫設計之間平滑的過度持久化。這是領域驅動開發的最大的問題,也是很多面向DDD框架的開發重點。
在上圖中我們目睹了以數據庫驅動后系統的大致結構,假設我們需要保證功能模塊的最大的擴展性我們在編寫數據庫驅動代碼的時候,很難抽象出復雜的變化點,因為都是貧血型的業務模型或者說根本不知道變化點在什么地方。而且并不是普通的開發人員能發掘到的,當然數據庫驅動開發也一樣可以進行靈活設計、開發,但是這樣畢竟對開發人員要求很高,他需要具備很強的面向對象設計能力,在不污染現有的代碼的情況下進行擴展性重構。至少我的經驗告訴我很難,而且在需求階段并沒有一個完整的大局觀,很容易造成頭重腳輕。對后期的系統開發進度也很難控制,因為無法確定每個功能模塊到底存在哪些接口。
所以我們還是朝著光明的道路前進,掌握DDD進行系統設計開發。
我們下面試著用建模的方式對上圖中的功能點進行大致面向對象設計,盡量提取變化點。
【簡單用例】
根據上圖的基本功能我們確定兩組用例,第一組是【客戶Custom】發起的所有動作,第二組是【后臺管理人員Admin】,比如配貨部門、訂單審核部門等等。這里純粹是為了演示建模的功能不是特地的項目實踐,所以功能簡單明了。
1.2圖
客戶首次進去平臺之后肯定是需要進行賬戶的【注冊】,有注冊就會有【注銷】,這里的注銷不是退出系統的意思,而是注銷在當前平臺的使用,就跟銷戶是一個意思。
(當然有人會覺得注銷不妥,電子商務平臺是不應該有注銷的,這只是主觀的設計而已,每個人的想法不同所以可以取長補短 ,我覺得有一個正面的注銷功能很好,可以讓用戶進行使用,到底如何使用我們這里就不分析了。)
成為正式用戶之后就可以挑選自己喜歡的商品進行【下訂單】,下訂單后就會進入平臺運行管理的流程的,客戶會隨時收到平臺發過來的流程信息反饋。所以這里有一個【短信管理】用例,該用例當然會包含 【刪除信息】、【讀取信息】、【回復信息】包含的子用例。
(當然可能我分析的不夠細致或者有問題的地方,由于我也是最近接觸UML建模所以可能有點不熟悉,對UML有興趣的朋友可以參考相關專業書籍。)
1.3圖
后臺管理人員需要對客戶下的訂單進行【配送】處理,配送環節將牽扯到【客戶信息】、【更新訂單狀態】、【打印配送信息】用例,對【打印配送信息】
功能需要【發送收貨信息】給用戶,告知用戶貨物已經發出。這里還包括一個泛化的用例【物品清單、配送地址】,在【打印配送信息】功能里面需要具體的打印出跟配貨信息相關的信息。
(這里提一下UML用例圖其實是通過縱橫向的方式來尋找系統的所有功能點,縱向是系統的所有功能,橫向是系統的外部調用者。)
【領域模型】
根據上述用例我們基本能捕獲到大致的系統功能,下面我們通過創建UML類圖來描述領域模型。
模型的創建要根據上一步的用例圖來進行分析,只要創建的模型能滿足用例的所有功能點就已經完成了一個大致輪廓。有些隱藏的模型是需要不斷的重構才能逐漸的浮現出來。
1.4圖
大致的模型已經創建出來,這只能算是一個基本的草圖形式的建模,還有幾個過程沒有走完,比如:反復的重構、與領域專家討論模型的準確性、與DBA進行溝通等等,這些都是DDD的整個范疇。
有了領域模型之后我們基本算是有了一個大致的業務方向,剩下的就是精益求精的過程,不斷的去分析深層業務關系。
【場景序列】
得出了領域模型之后我們需要對它進行一個基本的驗證,也就是看看模型是否能滿足所有的功能需求。最常用的就是通過序列圖來走查場景,對我們創建的領域模型進行逐步驗證。
由于時間關系我這里就不給出所有的序列圖了,只給出有代表性的序列【配送】。
1.5圖
由于怕截圖片太大所以給出關鍵的序列流程,能表達其意思就行了。
這是經典DDD調用序列,對上面具體的對象不是很清楚的不要緊后面有專門的示例進行全面分析。
#p#
【1.2】模式
模式相比大家都知道是什么意思,一些通用的思考問題的思路、解決方法、分析方法。當然在DDD領域也有很多模式供我們學習和使用,在需求階段講解的是行為模式在分析階段有分析模式,在設計階段有設計模式,在實現階段有實現模式,還有宏觀的架構模式。
那么在進行領域建模的時候有些前人總結出來的分析模式可以供我們參考。
【1.2.1】四色原型模式
四色原型模式是我接觸的第一個分析模式,當然目前也是發現它確實很好用,所以給同志們分享一下。
四色原型模式是能幫助我們找出業務當中的核心模型,也就是說核型模式應該具備幾個比較重要的特征的。
基本上想要根據UML用例圖找出領域模型需要使用名\動詞法找出大概的模型,然后順著領域模型一點一點完善、發掘,從而找出相關的實體模型。但是有些實體模型是一眼就能看出來的,就比如上例中的【用戶】、【訂單】、【消息】都可以定義為實體類型,也就是當前小示例中的核心領域模型。
看一下四色原型模式的結構圖:
1.6圖
對照四色原型模式我們很容易發現模型中的核型實體模型,很明顯對照上面的領域模型我們確實都是核心模型。
1.7圖
對照該模式我們會發現這里的商品其實也是核心實體才對,但是我們能很快發現我們忽視它了,商品也存在狀態和一些值類型才對,比如商品的使用狀態是不是沒貨、商品的詳細屬性是不是也存在獨立的值對象。當然這些要看當前項目需求而定。太范式的設計會帶來一些問題,有性能問題、有開發成本問題,這些都要進行詳細的討論才能最終確定,所以反范式設計就出現了。
原文鏈接:http://www.cnblogs.com/wangiqngpei557/archive/2013/04/07/3005890.html