天天看點

DDD領域驅動設計-概述-Ⅰ

 如果我看得更遠,那是因為我站在巨人的肩膀上。(If I have seen further it is by standing on ye shoulder of Giants.)

                                                                                                                                                                                                                    Newtown,I. 1676

DDD:指領域驅動設計,是domain driven design的縮寫。

介紹DDD基礎知識的相關文章很多,本文就不普及相關的基礎知識了,基礎理論知識可參考如下文章:

  • 《DDD基礎知識與總結》
  • 《DDD與分層架構》

1. 初識DDD

腳本式程式設計(dao+service)與DDD領域驅動模式差別如下:

DDD領域驅動設計-概述-Ⅰ

其每一層的作用範圍和含義如下:

1)展現層(Presentation Layer):負責以Restful的格式接受Web請求,然後将請求路由給Application層執行,并傳回視圖模型(View Model),其載體通常是DTO(Data Transfer Object);

2)應用層(Application Layer):主要負責擷取輸入,組裝上下文,做輸入校驗,調用領域層做業務處理,如果需要的話,發送消息通知。當然,層次是開放的,若有需要,應用層也可以直接通路基礎實施層;

3)領域層(Domain Layer):主要是封裝了核心業務邏輯,并通過領域服務(Domain Service)和領域對象(Entities)的函數對外部提供業務邏輯的計算和處理;

4)基礎實施層(Infrastructure Layer)主要包含Tunnel(資料通道)、防腐層,Config和Common。這裡我們使用Tunnel這個概念來對所有的資料來源進行抽象,這些資料來源可以是資料庫(MySQL,NoSql)、搜尋引擎、檔案系統、也可以是SOA服務等;Config負責應用的配置;Common是通用的工具類。

常見的領域驅動業務調用鍊過程如下圖所示:

DDD領域驅動設計-概述-Ⅰ

 調用過程大緻如下:

  1. 業務調用方基于網關傳入DTO資料,為了便于區分業務場景,将DTO資料又細分為CQE三種模式的資料。
  2. 業務資料傳入後,基于Spring Validation等模式做基礎資料驗證(如必填,格式,大小等基礎驗證);
  3. 資料進入到Controller層,并調用應用層相關的應用功能;
  4. 應用層不做具體的業務實作,隻做編排處理,做業務的流程處理。應用層可做如下操作:
  • 應用層調用防腐層查詢其他系統的資料;
  • 應用層調用倉庫層查詢本系統相關的資料;
  • 應用層調用工廠建立實體(簡單實體,可在應用層直接生成);
  • 應用層調用第三方領域服務,實體或聚合根的方法處理業務邏輯;
  • 應用層調用倉庫層儲存資料;
  1. 工廠建立實體,簡單的實體可不基于工廠建立;
  2. 領域層處理實體的行為,核心業務邏輯處理放在領域層,領域層可調用基礎層的所有子產品處理業務(領域層原則上不直接調用倉庫層儲存資料,儲存資料應該放在應用層調用);
  3. 倉庫實作層最終落地資料,進行資料存儲(其他層不能直接與Tunnel(資料通道)互動,必須基于倉庫層才可以);
  4. 一個業務行為結束後,若産生副作用,再應用層發出事件通知,其他子產品再監聽處理。(事件歸屬應用層還是領域層,網上各有不同的方案,本例是放在應用層。領域層本身隻是記憶體化操作。等一個實體行為真正資料存儲成功後,再發出事件,便于了解和維護。)

2. 巨人的肩膀

作者接觸DDD相關知識,是從一篇名為《一文教會你如何寫複雜業務的代碼》的文章開始的。帶着好奇,越看越有共鳴,初步發現了DDD的神奇之處并一發不可收拾,開始入坑DDD領域驅動設計。在檢視DDD各種教程部落格時,綜合對比并摒棄一些低品質的部落格,強烈推薦以下兩位老師的系列教程。

阿裡-張建飛:張老師的新書《代碼精進之路》。

阿裡-殷浩:

  1. 《DDD系列第一講》
  2. 《DDD系列第二講:應用架構》
  3. 《DDD系列第三講:Repository模式》
  4. 《DDD系列第四講:領域層設計規範》
  5. 《DDD系列第五講:如何避免寫流水賬代碼》

3. 為什麼要寫DDD系列部落格

在初步了解了DDD的相關知識後,作者的第一感受是:DDD概念很多,各種專業術語,一堆下來還有點複雜,看了理論知識,還是雲裡霧裡。看了諸多理論部落格,總結一句就是:“聽君一席話,如是一席話”。似乎明白了,又似乎還是什麼都不懂。

經過第一輪的理論知識打擊後,作者決定還是繼續學習。既然理論知識太多,那就在實踐中去尋找真理。

DDD到底應該怎樣落地?

網上介紹DDD理論知識的相關文章很多,但真正介紹DDD如何應用在項目中的高品質技術文章就鳳毛麟角了,更别提有完整示例的項目了。在這個探索的過程中,作者發現了殷浩的系列DDD教程,張建飛的COLA 4.0開源項目。

為了更透徹的掌握DDD相關的知識細節,并考慮落地DDD模式到公司的項目,還是沒有采用開源項目COLA 4.0。作者選擇通過殷浩老師的系列教程,一步一步開始DDD的探索之路。

适逢公司剛好存在一個老項目急需改造,老系統是基于(dao+service)腳本式程式設計開發的。由于時間較遠且不同時間段由不同的開發人員維護,這種老代碼,呵呵呵,懂的都懂。團隊讨論決定就用這個項目來做DDD的落地。

雖然一開始看了很多理論知識文檔,一些技術實作細節文檔。但在編寫初版本的DDD設計文檔時,依舊發現特别的别扭,總感覺很奇怪。本質原因還是缺乏DDD設計經驗,并且對DDD的各個知識點,分層細節了解不夠深入。在這個迷茫階段,作者抱着試一試的心态,嘗試加了殷浩老師的釘釘,所幸他同意了。後續就是請教學習了,請教各種理論細節的實作和注意事項。在這個過程中,有以下幾點感想:

  1. 深入了解理論知識,需要落地去反複的驗證,總結出來的理論知識一般具有高度的概括性,為什麼是這樣,不這樣會如何往往需要自己去驗證;
  2. 自以為已經明白了理論知識,但在實際項目使用中,卻是錯誤的使用,比如倉庫層,領域層的一些細節問題;
  3. DDD落地困難的點還在于實作一個功能可以有不同的模式,這些模式不一定都對,但從功能實作層面來說卻是都可以完成功能。比如,你在領域層直接調用倉庫層儲存資料,但領域層本身隻是做純記憶體化的業務邏輯處理,領域層是不可直接操作資料的。諸如此類的問題,導緻不同的人對DDD了解不同,實作模式也不同。由于每一層的标準,實作方案不完全不同,才導緻了DDD落地的複雜性。
  4. DDD做設計時,不單是對領域層做業務設計,應該是拉通整個流程一起做設計。
  5. 實體,聚合根,這些概念在實際項目中落地到具體的業務場景時,需要反複的疊代設計。
  6. 規範無處不在,注重程式設計細節,小到名命,大到使用設計模式,都需要規範編碼。DDD在不同的層面,需要開發人員更加注重規範,不可張冠李戴,錯誤如:在倉庫層裡面寫業務邏輯。
  7. 特别感謝殷浩老師的耐心指導,技術人傳道授業,簡單而純粹。這份技術人獨有的編碼情懷和工匠精神,很帥。

本文旨在為使用或學習DDD模式的同行者,提供一個快速的入門案例(案例gitHub位址),抛磚引玉,共同學習。目前網上還缺乏完善的DDD設計案例,本着互相探讨和學習的思想,現基于實際的案例,在脫敏處理後,詳述DDD從理論到落地的流程。大緻分為以下子產品:

  1. 《DDD領域設計-案例-需求說明文檔》
  2. 《DDD領域設計-案例-模組化設計說明》
  3. 《DDD領域設計-項目目錄結構說明》
  4. 《DDD領域設計-案例-源碼使用說明》
  5. 《DDD領域設計-設計規範》

特别說明DDD落地的方案沒有統一的标準,本系列文章采用的技術方案也不一定能完全實作DDD的思想。由于作者水準有限,在一些了解上面若出現偏差,歡迎指導和批評。

分類: 系統設計

标簽: DDD, DDD 領域驅動設計

繼續閱讀