版本 | 日期 | 備注 |
---|---|---|
1.0 | 2021.8.22 | 文章首發 |
1.1 | 2021.8.26 | 增加對于核心思想的描述 |
之前的DDD文章——談談代碼:降低復雜度,從放棄三層架構到DDD入門
,通篇下來像 是簡單的講了一些概念,然后快速的實戰一下——很多同學反饋感覺就是入門了,但沒有完全入門,因此我們再加一篇。
1.什么是DDD
先看下萬能的維基百科:Domain-driven design (DDD) is the concept that the structure and language of software code (class names, class methods, class variables) should match the business domain. For example, if a software processes loan applications, it might have classes such as LoanApplication and Customer, and methods such as AcceptOffer and Withdraw.
這邊將其稱為了一個概念。在我看來DDD是設計模式的超集,一種指導思想——用來指導如何解耦業務系統,劃分業務模塊,定義業務領域模型及其交互。
2. DDD誕生的背景
領域驅動設計這個概念并不新穎,早在 2004 年就被提出了,到現在已經有十幾年的歷史了。不過,它被大眾熟知,還是基于另一個概念的興起,那就是微服務。因此在實現的時候樣子不一定是一模一樣的,更多時候還是根據業務場景來因材施教。
3. DDD的核心思想
核心思想是讓技術復雜度與業務復雜度隔離,并通過統一語言組織業務邏輯,降低認知成本。
具體主要體現在:
- 基礎設施層:它負責隔離技術復雜度,通過抽象封裝來對內提供服務,而不是讓內部服務直接使用它。這意味著當外部基礎設施變化時,業務并不會被迫進行變更。比如項目中的數據總線是Kafka,之后替換成了Pulsar,業務對其應該是無感知的。
- 厚領域層:同一領域的知識聚合在一個領域中,領域知識不再被割裂。這是單一職責原則的一種體現。
- 實體:用充血模型代替貧血模型,完全符合面向對象的思想。將業務中的對象完全投射到實體中,從面向資源轉換成面向過程和面向對象。
4. DDD能解決什么樣的問題
一般軟件會經歷幾個不同的周期:
- 大煙囪:每個應用各自為政,類似的需求重復開發,浪費人力
- 服務化:根據不同的業務屬性拆分服務。關注服務拆分、服務治理、模型抽象
- 平臺化:將相關的微服務同一成一個平臺暴露出來。關注領域收斂、領域自治、能力沉淀
- 中臺化:將通用能力下沉至中臺,快速響應前端服務。需要關注數據打通、能力串聯、業務響應力
DDD主要在技術密集型應用里有較大的作用,尤其是當該應用進入服務化、平臺化時,可以在:“服務拆分”、“服務治理”、“領域收斂”、“領域自治”發揮。在中臺化中的“數據打通”也有一定的作用。
而微觀來說,DDD可以有效減少代碼的冗余程度以及需求響應的速度。
5. DDD實踐中要注意的
5.1 使用IOC來保證層次之間的隔離
經常有小伙伴問我,分層之間該怎么做?因為分層的邊界沒做好,代碼會再度耦合再一起。對此我給出的答案是參考inversion of control
。其常見實現有:
- Object Dependency Inject
- Service Provider Interface
- Strategy
- Abstract Factory
也可以參考我之前寫的文章:技巧:遵循Clean Architecture寫好白盒測試。
5.2 模塊分離
模塊分離是一種較為“硬”的手段,它讓分層不再是一個約定,而是強制執行的規則。這樣當我們拆分微服務時候,也可以較快的完成拆分。
5.3 DDD并不是只有三層到四層
也有小伙伴問過我,轉DDD的是否只有三層過來的?其實并非如此。我這邊可以舉兩個例子:
5.3.1 流計算處理
我們以面向在線數據加密應用為例子:當一條數據流過我們的應用時,我們需要根據一些條件對其加密。
應用的基本流程為:Source(from kafka) -> Map(encryption) -> Sink(to kafka)
。
那么代碼中,kafka其實是基礎層的代碼。而encryption
屬于領域層,map(框架)和encryption之間的膠水代碼則屬于基礎層。
5.3.2 GUI應用
相信大家都在學生時代學過GUI or HTML 編程。那么按照DDD的做法來,業務邏輯應該與具體的界面無關——比如界面上的一個按鈕(數據模型)會觸發一種事件,當后臺的事件接受者收到這個事件時,則會尋找相應的執行者,執行對應的邏輯。
在這里面:
- 界面可以是Qt,可以是Flex,可以是Ios,可以是Android,也可以是Vue。其本質是用戶接口層。
- 后臺的事件接受者是基礎層。
- 具體的執行邏輯則放在領域層。