## 啟迪
領域可以理解為業務,領域專家就是對業務很了解的人。
限界上下文也就是微服務的邊界,也可以理解為微服務,壹個限界上下文=壹個微服務。
個人理解領域驅動設計就是微服務驅動設計,從戰略上先進行微服務的劃分,從戰術上針對某個微服務進行領域模型的設計也就是業務模型的設計。
領域模型包括:
- 實體
- 值對象
- 聚合
- 領域服務
- 領域事件
- 資源庫
- 應用服務
## 什麽是領域驅動設計?
理解領域驅動設計是什麽之前,我們先來理解下什麽是領域?
領域可以理解為業務,領域專家就是對業務很了解的人。
領域驅動設計的核心就是和最了解業務的人也就是領域專家壹起通過領域建模的方式去設計我們的軟件程序。
- 那麽領域如何驅動設計?或者說業務如何驅動設計?
傳統開發過程我們都是基於面向數據開發,拿到產品原型腦海裏想著都是應該創建哪些表和哪些字段才能滿足需求。
而領域驅動設計開發過程是讓我們基於面向業務開發、面向領域模型開發。
領域模型的核心是通過承載和保存領域知識,並通過模型與代碼的映射將這些領域知識保存在程序代碼中,
在傳統開發中,當業務被轉換為壹張張數據表時,丟失最多的就是領域知識(領域知識也就是我們在模型中定義的壹些業務邏輯行為)。
面向領域模型開發的優點:
- 存儲方便,統壹使用JSON進行存儲。
> 例:
> 訂單領域包含基礎信息、商品信息、金額信息、支付信息等包含訂單全生命周期的子域,
> 對於傳統面向數據的開發模式我們需要創建N張表進行存儲訂單的信息,但是面向領域開發時我們
> 可以通過利用nosql數據庫(mongo、es等)進行保存整個訂單域的信息,提高查詢、更新效率,簡化代碼
- 復用性高,引用某個領域模型,就可以擁有該領域模型的所有行為。
> 例:
> 基於微服務架構下,某個電商應用需要壹個判斷某個訂單是否是在線支付訂單的邏輯時,
> 對於傳統的開發模式我們需要調用訂單中心的服務查詢訂單信息,然後寫壹個判斷是否在線支付訂單的方法。
> 如果有多個應用都需要這個邏輯時,每個應該都需要重復寫相同的方法。
> 但面向領域開發時,只需要引用訂單中心的jar包,然後統壹調用訂單領域內的方法即可。
> 這樣就實現了業務的高內聚
## DDD可以做什麽
DDD主要分為兩個部分,戰略設計與戰術設計
- 戰略設計
- 圍繞微服務拆分
- 戰術設計
- 微服務內部設計
## DDD怎麽做
- 戰略設計
- 和領域專家壹起通過(過往經驗、事物聯系、事件風暴等)劃分限界上下文
> 限界上下文也就是微服務的邊界,也可以理解為微服務。
> 壹個限界上下文=壹個微服務
- 戰術設計
- 開發人員通過(領域模型)保存領域知識
> 領域知識也就是事物(角色)、行為(規則)和關系
>
## DDD領域模型
領域模型包含什麽?
- 實體
> 具有唯壹標識,包含著業務知識的充血模型對象,用於對唯壹性事物進行建模。
> 例:
> ```
> public class Order {
> private long orderId;
> private OrderAmount amount;
> private List item;
> }
> ```
- 值對象
> 生成後即不可變對象,通常作為實體的屬性,用於描述領域中的事物的某種特征。
> 例:
> ```
> public class OrderItem {
> private long orderId;
> private String productCode;
> private String productName;
> }
> ```
- 聚合
> 將實體和值對象在壹致性邊界之內組成聚合,使用聚合劃分微服務(限界上下文)內部的邊界
- 領域服務
> 分擔實體的功能,承接部分業務邏輯,做壹些實體不變處理的業務流程。不是必須的
> 主要承接內部領域服務調用和外部微服務調用,及壹些聚合業務邏輯處理。
> 例:
> ```
> @Service
> public class ShoppingcartDomainService {
> private final ShoppingcartRepository shoppingcartRepository;
> private final ProductFacade productFacade;
> private final UserFacade userFacade;
> private final PromotionFacade promotionFacade;
>
>
> // 1.查詢購物車信息
> ShoppingcartDO entity = shoppingcartRepository.loadShoppingcart(userId);
>
> // 2.調用用戶中心服務查詢用戶信息
> User user = userFacade.getUser(userId);
>
> // 3.調用商品中心服務查詢商品信息
> Product product = productFacade.getProduct(productCode);
>
> // 4.調用活動中心服務查詢活動信息
> Promotion promotion = promotionFacade.getPromotionByProductCode(productCode);
>
> // 5.創建購物車實體
> Shoppingcart shoppingcart = new Shoppingcart(entity.getId, user, product, promotion);
>
> // 6.購物車按活動分組
> shoppingcart.groupby4Promotion();
> }
> ```
>
>
- 領域事件
> 表示領域中發生的事情,通過領域事件可以實現本地微服務(限界上下文)內的信息同步,同時也可以實現對外部系統的解耦
- 資源庫
> 保存聚合的地方,將聚合實例存放在資源庫(Repository)中,之後再通過該資源庫來獲取相同的實例。
>
- 應用服務
> 應用服務負責流程編排,它將要實現的功能委托給壹個或多個領域服務來實現,
> 本身只負責處理業務用例的執行順序以及結果的拼裝同時也可以在應用服務做些權限驗證等工作。
> 