閱讀目錄:程序員
對軟件開發方法論有興趣的博友應該發現最近「領域驅動設計」慢慢的被人發現被人實踐起來,園子裏也慢慢有了DDD的學習氣氛和寶貴實戰經驗的分享。其實以前我也癡迷於DDD,爲何會癡迷於它並非由於它是所謂的新技術,也不是由於各類對它的炒做,而是我以爲我找到了能解放咱們進行企業業務系統開發的方法論。數據庫
DDD能夠很好的指導咱們開發可靠的軟件系統,尤爲是如今的企業業務複雜多變的狀況下,使用DDD能夠很好的隨着業務變化不斷的重構現有的領域模型,最爲重要的是我以爲DDD是可以很好的實施敏捷價值觀的軟件開發方法論。設計模式
若是你想重構、測試你所寫的業務代碼,少不了對代碼進行適當的羅動,若是沒有一個好的結構讓你存放你所提取出來的代碼是比較無奈的。包括如今敏捷軟件開發方法論中最重要的TDD方法論更加的依賴代碼的結構是否可以容許進行重構,若是你的結構是很死板的,扁平化的其實很難實施TDD,你會發現你所抽象出來的概念無恥容納。緩存
因此我認爲DDD是爲了解決上述這些問題的一個好的方法,固然前提是你本身實施過以後纔有資格去評判它的優劣,並且是客觀公正的。架構
實施DDD是很費時費力的工程,沒有傳統的開發方法那麼簡單快捷,並且對開發人員的總體要求有了一個新的標準,因此本篇文章將介紹一個能夠用來替代DDD模式的另一個比較好的企業模式「活動記錄模式」。性能
領域模型模式其實就是領域驅動設計,兩個是一個意思。有興趣的朋友能夠進一步學習領域驅動設計,我認爲DDD對於一名企業應用開發人員來講是必不可少的一門設計思想,就比如設計模式同樣,它也有着一套模式,用來指導咱們進行相關業務場景的設計。學習
領域模型模式也稱領域驅動設計,對業務模型進行等價的面向對象建模,無需太多考慮數據存儲的技術細節,可是並非說徹底不考慮如何存儲,若是誰告訴你說徹底不須要考慮存儲那是錯誤的,由於你要考慮這個領域模型最終是要如何持久化的,以避免你將領域模型建立成一個巨大的蜘蛛網。說不須要考慮領域模型如何持久化實際上是說你目前只須要把握領域模型建立,不去完成持久化設計細節而已,可是這兩個工做每每是互相考慮的。測試
難道一個不懂得如何存儲關係數據的人可以建立出能知足程序員很好的開發的模型嗎。this
活動記錄模式是最靠近DDD的模式,它將數據庫中的表中的一行做爲本身的對象化字段,而後圍繞着這些字段展開的業務邏輯,將數據字段與業務邏輯都封裝在一個實例對象中。spa
活動記錄模式與表模塊模式不一樣的是,表模塊模式是一個對象對應着一個數據庫中的表,而活動記錄模式是一個對象對應着一個行記錄,因此稱爲活動記錄模式。
此模式最大好處是能夠基本上知足業務不是很複雜的情景下,我倒以爲活動記錄模式在如今的面向SOA架構下可以更適合企業的業務系統開發團隊。使用領域驅動太過於複雜,不使用又會面臨着業務快速變化的困境,因此活動記錄模式能夠考慮試試。
咱們來看一個簡單的示例,瞭解活動記錄模式的開發及要點。
活動記錄模式是使用與數據庫中的表結構一直的方式使用類的,也就是說表中的列就是類的字段,固然也能夠在處理業務邏輯時的輔助字段,儘可能不包含多餘的字段,這樣能夠有效保證乾淨的活動記錄。
1 namespace Business.RecordModels.OrderModel 2 { 3 using System; 4 using System.Collections.Generic; 5 6 /// <summary> 7 /// Order table fields. 8 /// </summary> 9 public partial class OrderFields 10 { 11 /// <summary> 12 /// Order id. 13 /// </summary> 14 public long OId { get; set; } 15 16 /// <summary> 17 /// Order name customer declare. 18 /// </summary> 19 public string OName { get; set; } 20 21 /// <summary> 22 /// Product ids. 23 /// </summary> 24 public List<long> PIds { get; set; } 25 26 /// <summary> 27 /// Order sum price. 28 /// </summary> 29 public float Price { get; set; } 30 31 /// <summary> 32 /// Order distribute status. 33 /// </summary> 34 public int DistributeStatus { get; set; } 35 36 /// <summary> 37 /// Order payment status. 38 /// </summary> 39 public int PaymentStatus { get; set; } 40 41 /// <summary> 42 /// Order signer. 43 /// </summary> 44 public string Signer { get; set; } 45 46 /// <summary> 47 /// Submit datetime. 48 /// </summary> 49 public DateTime SubmitDt { get; set; } 50 } 51 }
定義一個Order活動記錄的字段類,也能夠直接將該字段定義在Order類中,可是通常我喜歡獨立出來,由於字段一旦多了看起來實在很累。若是你想將字段直接定義在Order類中我建議你使用部分類來處理,這樣比較乾淨。
字段中的public List<long> PIds { get; set; } 商品ID集合字段是有意聚合到該字段類中的,由於不論是業務處理仍是數據持久化都是須要相關連的業務字段的。 (活動記錄模式不要求你很死板的一個表一個記錄實例,只要你使用你本身的方式可以讓代碼結構看上去很天然就是很恰當的。)
雖然你直接使用了int類型來描述業務字段,不過你可使用其餘方式讓來該字段在業務處理中不直接使用語言類型而是業務概念。
1 namespace Business.RecordModels.OrderModel 2 { 3 /// <summary> 4 /// Distribute status const. 5 /// </summary> 6 public class DistributeStatusConst 7 { 8 public const int NoDistribute = 1; 9 10 public const int BeginDistribute = 2; 11 12 public const int EndDistribute = 3; 13 } 14 }
配送狀態常量類,定義明確的業務概念的值。
1 namespace Business.RecordModels.OrderModel 2 { 3 /// <summary> 4 /// Payment status const. 5 /// </summary> 6 public class PaymentStatusConst 7 { 8 /// <summary> 9 /// No payment. 10 /// </summary> 11 public const int NoPayment = 1; 12 13 /// <summary> 14 /// End payment. 15 /// </summary> 16 public const int EndPayment = 1; 17 } 18 }
配送狀態常量類,定義明確的業務概念的值。
對活動記錄的建立我建議是用工廠來處理,畢竟這裏麪包含了不少業務邏輯在裏面的。
1 namespace Business.RecordModels.OrderModel 2 { 3 using Common; 4 5 /// <summary> 6 /// Order class factory. 7 /// </summary> 8 public class OrderFactory 9 { 10 /// <summary> 11 /// Create a order instance. 12 /// </summary> 13 /// <param name="fields">Order fiels instance.</param> 14 /// <returns>Order instance.</returns> 15 public static Order CreateOrder(OrderFields fields) 16 { 17 if (fields.IsNull() || fields.OName.IsNullOrEmpty() 18 || fields.PIds.IsNullOrEmpty() || fields.Price.IsLessThanOrEqual0()) return null; 19 20 fields.DistributeStatus = DistributeStatusConst.NoDistribute;//No distribute. 21 fields.PaymentStatus = PaymentStatusConst.NoPayment;//No payment. 22 23 return new Order(fields); 24 } 25 } 26 }
活動記錄模式不等於沒有DDD那麼好,其實在業務相對不是很是複雜的狀況下,活動記錄模式仍是至關不錯的,簡單快捷,對一些原子類型的字段處理使用常量就很不錯。
這裏咱們使用DistributeStatusConst.NoDistribute、PaymentStatusConst.NoPayment 常量字段來明確的傳達業務概念,而不是非要用枚舉,經驗告訴我有時候枚舉沒有常量方便。
活動記錄對象中包含了該記錄所表達的業務邏輯,這裏的Order將包含該表所表達的業務邏輯處理。
1 namespace Business.RecordModels.OrderModel 2 { 3 using System; 4 5 /// <summary> 6 /// Order table record 7 /// </summary> 8 public partial class Order 9 { 10 /// <summary> 11 /// Order table columns. 12 /// </summary> 13 private OrderFields fields { get; set; } 14 15 /// <summary> 16 /// New a order instance only internal use. 17 /// </summary> 18 /// <param name="fields">Order fields.</param> 19 internal Order(OrderFields fields) 20 { 21 this.fields = fields; 22 } 23 24 /// <summary> 25 /// Calculate order expiration time. 26 /// </summary> 27 /// <returns>DateTime</returns> 28 public DateTime CalculateExpirationTime() 29 { 30 //Here you can use strategy. 31 if (this.fields.PaymentStatus == PaymentStatusConst.NoPayment)//No payment logic 32 { 33 return this.fields.SubmitDt.AddDays(1); 34 } 35 else if (this.fields.DistributeStatus == DistributeStatusConst.NoDistribute)//No payment logic 36 { 37 return this.fields.SubmitDt.AddDays(30); 38 } 39 40 return this.fields.SubmitDt.AddDays(3); 41 } 42 } 43 }
這裏我有一個簡單的計算當前訂單到期時間的方法(CalculateExpirationTime),在方法內部有一些業務邏輯,而該業務邏輯和當前實例一塊兒存在。
經過使用活動記錄模式能夠很好的將字段與業務方法有效的集合起來,這樣會使得業務邏輯處理比較有條理性,也便於測試和重構。
這裏須要強調的是活動記錄模式是業務層和數據層共用的模式,當時這裏咱們所講的是面向業務層的,也就是說你數據層可使用任何方式來和活動記錄模式整合,如今比較流行ORM了,若是你對性能有要求你可使用手工處理,建議使用表入口模式來結合,由於數據層沒有什麼邏輯,若是你的數據層有相關的邏輯我像也不會出現最後的數據源上,而是應該在數據適配層上處理掉,如:緩存、填補字段等。
很難在一篇文章中說明全部問題,活動記錄模式若是是用在讀寫分離大的架構中的寫端時必須須要「工做單元」模式來協調多「記錄」之間的事務性。可是若是你在查詢端使用活動記錄模式,那麼大部分狀況下是不須要事務性的,固然查詢端我以爲使用事物腳本模式比較直觀點,由於業務邏輯也不會有多少。
仍是那句話,本篇文章只是分享點本身學習過程當中和工做過程總結的經驗,僅供參考。其實企業應用架構是一個看似簡單其實很複雜的方向,但願與各位一塊兒學習一同進步,謝謝。