領域驅動(1)認識瞭解什麼是領域驅動 廢話 領域驅動設計已經出現很早了,說實話很早以前的我很不喜歡看書、不論是pdf還是書本、買過的書籍還是有幾本的,這僅有的幾本書還是因為公司的業務或者某項技術遇到瓶頸需要自己和團隊進行突破的時候用來填充自己的大腦用的,當然這是被動的,畢竟:生下來、活下去很重要的。 ...
領域驅動(1)認識瞭解什麼是領域驅動
廢話
領域驅動設計已經出現很早了,說實話很早以前的我很不喜歡看書、不論是pdf還是書本、買過的書籍還是有幾本的,這僅有的幾本書還是因為公司的業務或者某項技術遇到瓶頸需要自己和團隊進行突破的時候用來填充自己的大腦用的,當然這是被動的,畢竟:生下來、活下去很重要的。這兩年微服務的出現好像又推動了領域驅動設計的發展。
一、解釋什麼是領域驅動:
其實對於IT的行業的我們理解起來很容易,很有可能在日常生活工作中我們也都有過接觸,對於領域是一個什麼樣的概念
舉例:
比如說我們要做一個有關用戶登錄的功能,使用最簡單的RBAC來進行設計但是在進行設計的時候我們首先需要明白的是用戶(甲方)有幾種級用戶的級別,每種級別處於什麼樣的角色,又有多少許可權,這個時候產品經理開始去接觸軟體使用方(方法),去瞭解他們的需求以及,期初因為產品經理不明白甲方的企業架構導致採集需求的時候工作異常難做,摩擦不斷,後來漸漸的接觸的多了,明白了甲方的企業架構,並且對甲方的一些專業的稱呼、名詞也漸漸的懂得了,在往後的溝通過程中雙方之間的摩擦也漸漸的少了起來。 在這個由壞變好的過程中,是因為產品經理漸漸的融入了甲方的領域內。
然後產品把業務拿了回來,軟體開發人員開始了設計開發工作,大多數開發人都把技術作為自己的能力,對領域並不去瞭解,導致了後來功能實現後,代碼不能很好的擴展,有一天產品經理拿了一份變更的需求回來了,為了實現新的需求,迫不得已軟體開發人員只有重新來過,導致了前面做的很多工作都是無用工,我相信這樣的場景很多的開發人員都遇到過,也埋怨過,其實開發人員也是有錯的假如我們開發人員也同樣進入了對方的領域中,在真正的實現過程中,就可能會提前發現隱藏的問題,再不濟也能寫出可擴展的設計或代碼,當真正的發生變更的時候,也不至於前面的所有的工作都成為了無用功。
其實領域驅動設計需要領域驅動專家和開發人員相互協作來完成的,在這個過程中無論是開發人員還是業務人員都積累了該領域的相關知識。
但是在開發過程中,時長會有人員流失的可能性,其實人員的流失也是相對應的領域知識的流失,有人這樣說,真正的高手寫出的代碼是可以讓菜鳥維護起來都不是很吃力的,為什麼呢,其實高手在寫代碼的時候已經傳承下了該領域的知識,等到新人來到的時候,根據代碼分析學習代碼中傳承下的領域知識,可以做到更快的瞭解業務。
代碼舉例:利用策略模式實現一個簡單的領域模型
用一個比較靠近生活的例子:一套服裝的價格在不同的地區出售不同的價格
我們把地區和服裝的價格聯繫起來
/// <summary> /// 獲取衣服價格 /// </summary> /// <returns></returns> public decimal GetClothing(string ClothingNO, string AreaNo) { ClothingModel clothingModel = new ClothingModel(); SellAreaModel sellAreaModel = SellAreaModellist.Where(x => x.AreaNo == AreaNo).SingleOrDefault(); if (sellAreaModel != null) { clothingModel = ClothingModellist.Where(x => x.ClothingNo == ClothingNO&& x.AreaNo==sellAreaModel.AreaNo).SingleOrDefault(); //乘以折扣比率 return clothingModel.ClothingPrice* clothingModel.Discount; } else { return 0.00M; } }View Code
由於季節發生了改變,衣服的價格需要根據不同的季節進行價格上的改動,這種情況被稱為商品的季節性,這是商品銷售領域的基本常識,然而有的技術人員對這項規則並不瞭解。
需求文檔中增加了這樣一句話:衣服根據不同的季節會發生價格上下浮動的變化。春季下調10% 冬季上調10%.
/// <summary> /// 獲取衣服價格 /// </summary> /// <returns></returns> public decimal GetClothing(string ClothingNO, string AreaNo,int SeasonMark) { //根據季節規定價格浮動比例 double floatNum = SeasonMark != 0 ? 0.1 : 1.1; ClothingModel clothingModel = new ClothingModel(); SellAreaModel sellAreaModel = SellAreaModellist.Where(x => x.AreaNo == AreaNo).SingleOrDefault(); if (sellAreaModel != null) { clothingModel = ClothingModellist.Where(x => x.ClothingNo == ClothingNO && x.AreaNo == sellAreaModel.AreaNo).SingleOrDefault(); //乘以該地區的折扣比率*季節價格調動比例 return clothingModel.ClothingPrice * clothingModel.Discount* (decimal)floatNum; } else { return 0.00M; } }View Code
這樣的代碼已經變得複雜了起來,當業務規則在增加的時候代碼將變得更加的複雜,這個時候我想一個新人想要在代碼中得到業務規則也將變得困難起來。規則越複雜情況越糟糕。
現在代碼這樣改動:使用策略模式
策略模式(Strategy)概念:策略模式一般指定義一組演算法,將每個演算法都進行封裝,可以使程式可有由一個或多個可替換的策略組合成。
/// <summary> /// 獲取衣服價格 /// </summary> /// <returns></returns> public decimal GetClothing(string ClothingNO, string AreaNo, int SeasonMark) { //根據季節規定價格浮動比例 double floatNum = SeasonMark != 0 ? 0.1 : 1.1; SellAreaModel sellAreaModel = SellAreaModellist.Where(x => x.AreaNo == AreaNo).SingleOrDefault(); if (sellAreaModel != null) { ClothingModel clothingModel = ClothingModellist.Where(x => x.ClothingNo == ClothingNO && x.AreaNo == sellAreaModel.AreaNo).SingleOrDefault(); return ComputedPrice(clothingModel, floatNum); } else { return 0.00M; } } /// <summary> /// 計算衣服的價格 /// </summary> /// <param name="clothingModel">服裝信息</param> /// <param name="floatNum">滑動比例</param> /// <returns></returns> public decimal ComputedPrice(ClothingModel clothingModel, double floatNum) { //乘以該地區的折扣比率*季節價格調動比例 return clothingModel.ClothingPrice * clothingModel.Discount * (decimal)floatNum; }View Code
/// <summary> /// 獲取衣服價格 /// </summary> /// <returns></returns> public decimal GetClothing(string ClothingNO, string AreaNo, int SeasonMark) { //根據季節規定價格浮動比例 double floatNum = SeasonMark != 0 ? 0.1 : 1.1; SellAreaModel sellAreaModel = SellAreaModellist.Where(x => x.AreaNo == AreaNo).SingleOrDefault(); if (sellAreaModel != null) { ClothingModel clothingModel = ClothingModellist.Where(x => x.ClothingNo == ClothingNO && x.AreaNo == sellAreaModel.AreaNo).SingleOrDefault(); return ComputedPrice(clothingModel, floatNum); } else { return 0.00M; } } /// <summary> /// 計算衣服的價格 /// </summary> /// <param name="clothingModel">服裝信息</param> /// <param name="floatNum">滑動比例</param> /// <returns></returns> public decimal ComputedPrice(ClothingModel clothingModel, double floatNum) { //乘以該地區的折扣比率*季節價格調動比例 return clothingModel.ClothingPrice * clothingModel.Discount * (decimal)floatNum; }View Code
這樣寫的好處在於,當開發設計人員看到這段代碼的時候可以明確的看到衣服不通季節有不同的價格計算策略,而不是像上面代碼一樣把一個重要的業務規則,寫成一句不引人註意的計算問題。這樣的代碼讀起來會開發人員更快的理解代碼
深層模型:
每一個項目都會隨著對領域和需求的理解,模型也會逐漸的加深,可能項目剛開始的時候對於我們來說很重要的錶面元素,將變得不是那麼重要,也或者那些不重要的元素,隨著業務理解的深度或切換角度後變得重要起來。模型在一步步的變得龐大這也是知識消化後的產物,如果當領域專家和開發人員通過領域模型就能對業務需求有一定的認知,我想最起碼溝通的過程中目的的一致性也做到了。同樣會減少很多本不應該出現的需求變更的出現。
最近一兩個月將持續更新領域驅動設計。有偏差的望大家指出,相互學習。
有不足之處 希望大家指出相互學習,
本文原創:轉載請註明出處 謝謝!