當前位置:
首頁 > 最新 > DDD究竟是個啥?怎麼落地?

DDD究竟是個啥?怎麼落地?

領域驅動設計(Domain Driven Design,以下簡稱DDD)這個話題,經常會出現在各大技術圈。特別是微服務出現後,海內外的大佬們又把微服務和DDD放到了一起說事情。

當「領域驅動設計」映入我的眼帘時,我心想「領域」這個詞我熟悉。

但「領域驅動設計」一下子就感覺高端了許多。

於是好奇的查了些資料,發現了vo,pojo,domain之類的。看到這裡時,我的心頭是一臉不屑,這不就是我每天都在使用的嗎?

我們每天新建的三層項目不是就老是出現domain目錄,還有vo目錄,還有service目錄嗎??這不就是這麼點事情嗎?!

什麼是「領域」?

嗯,另外「領域」這個詞,說的就是每個領域都有自己的領域語言,那麼我們開發軟體的時候,也應該沿用所屬行業的領域語言,比如銀行系統有銀行系統的特定的一套語言,這套語言你不能打破,因為這是人家多少年積累的約定俗成的行業語言。比如支付系統有支付系統的語言,雖然互聯網支付是最近些年才慢慢發展壯大,但現在它也發展出了一套自己專門的語言,你沒看每家的支付系統都會說訂單、商品、產品、庫存等等,這已經慢慢形成了一門專屬的行業語言,也就是領域語言。

總之,我要說的是,你在構建軟體時,請一定記住,先起名字,先起領域名字。這應該DDD的第一步。沒錯,我說的就是這麼赤裸裸,起名字就是DDD的第一步

這就是大概我理解的DDD。也是我目前能夠想到的。

但,我想著DDD這事絕對沒有我想的這麼簡單,我得去查查資料好好學學,以下是一些上面我沒有說到的一些點以及對上面的一些概念的細化以及如何落地的基本思路。

一步步來。

領域映射

「領域」這個兩個字,具體怎麼落地呢?

很簡單,就是把現實中(一般指線下)的約定俗成的現成行業術語映射到你的靜態和動態設計中。靜態設計指的是你的實體類的起名問題。動態設計是指你的業務類(也就是service)的方法名起名問題。現實中的動作名對應service中的方法名。

領域專家

領域專家這個角色是一個抽象的泛指。你可千萬別專門較真去招聘一個領域專家來。你心目中懂那一行的人就是你的領域專家。比如你去走訪一個銀行櫃員,你去問一個清潔工,或者你去問一個程序員(這個程序員在某行業開發多年早可能就是這方面的專家了,只是人家恰好寫代碼而已。)或者是產品經理等等。總之,白貓黑貓,懂那一行的人就是你的「領域專家」

領域分層

這裡的分層主要是DDD的歷史。就是最早大師們提出來的領域驅動設計這事,是一個更加抽象和底層的概念。後來由於領域驅動設計的日益發展,人們又封裝出來了一套基於這些底層領域概念的更高層的高級領域概念。就好比變成語言的底層語言和高級語言之分一樣。

最早的人們只是抽象出了最主要的兩個概念。一個是領域(Domain),一個是領域邏輯(Domain Logic)。是不是夠抽象,是不是看了以後根本無法直接落地,是不是像哲學 ,需要你好好的悟和實踐。

後來隨著發展,人們在此基礎上又發明了新的更加高級和可落地的概念。比如Entity、ValueObject、Aggregate、Service等等,還有一些你可能很少用的一些,比如:Repositories、Factories、Domain Event這些概念。

嗯,通過這樣的分層,你就知道了這些概念,哪些概念屬於底層概念,哪些屬於高級概念。核心就是抽象和具體、底層和高級。

高級落地概念

這裡說的高級不是歧視那個Context,哈哈,是指的high-level。

Entity有唯一標識的。就對應於你的實體類。

Value Object可以沒有唯一標識的。對應於你的返回數據格式類。一般只是為了前端顯示方便,只負責返回數據用的,官方說法:immutable object。

Domain Event對Domain進行各種的操作的事件。在如今的微服務當下,你可以理解為CQRS里的Command,用來同步數據的。

Aggregate是Entity和Value Object的集合。用來返回展示用的。通常用一個id,就可以獲取到一個Aggregate。有關這個概念你可以看一下mongodb的設計思路。

Service就是你三層里的那個service,裡邊一堆領域邏輯,一堆的操作和動作。對應於底層領域概念的Domain Logic,屬於動態(Domain屬於靜態)。

Repositories這裡的repositories不是版本控制系統里說的倉庫的意思。而是指的對於聚合中的entity和value object的單獨訪問,這裡你就對應於dao層好了。很多時候,我們的dao就是負責對entity的單獨而直接地訪問。而且這個概念早被引入了Spring框架了,就是那個用來做數據訪問的@Repository註解。

有圖有真相:

Factories這裡的Factories就是設計模式里的那個工廠模式。之所以DDD把工廠模式也拉攏過來,就是因為DDD的大師們認為工廠模式是一個牛逼的設計模式,它能把創建一個對象變得如此簡單,調用者不需要關心內部細節就可以使用一個對象了,所以建議大家多使用工廠模式來踐行DDD。事實證明,Spring框架中大量的使用了工廠模式,也許就是對DDD中Factories這個概念的踐行。

領域抽象

之所以有這一節,主要是我們很多時候並不能把領域一下子就定義的一步到位。如果按照前面所說的你完全按照現實中的領域名詞來一比一映射來構建你的代碼可能會出現一些重複的代碼。所以這時候就需要你對現實的領域進一步抽象,從而讓你的代碼足夠的簡潔。當然如果你從定義領域的時候就一眼看破了其中的本質,那自然也就無需專門的領域抽象了。

領域驅動吵架

這個小節里,我們主要介紹一些吵架時專用的一些概念。領域驅動設計的過程中,你難免要和別的團隊以及產品經理等等吵架,那麼DDD也為你抽象了吵架可以用到的一些方法論。

Context

相信看這篇文章的人肯定聽過Context。是不是很熟悉?好學的同學,肯定也聽說過Model、Ubiquitous Language、Bounded Context。那麼這些是用來做什麼的呢?其中一個主要功能就是吵架。沒錯,領域驅動吵架。你是不是經常說:「我們說的xxx不是你說的那個xxx」。這顯然兩個沒在一個Context下討論事情。或者還有「你這個功能不是xxx系統應該提供的,而應該是yyy系統來做,要不然就亂了。」等等。這些其實都是在說Context。我拜讀過不少有關領域驅動設計的文章,他們一上來就向你介紹一通Context。他們一般都是這樣介紹的:「上下文。xxxxxxxxxxx。。。。。。」。說實在的,你說上下文我並不知道你在說什麼。其實Context的意思很簡單,就是大家都在同一個語境下愉快聊天(或者「在一個範疇下」,或者「在一個大前提下」)。

Model

其實和Domain是有點接近的,相信你肯定看到一些項目代碼的目錄中有的寫的是model,有的寫的是domain,然後他們目錄下其實都是那些實體類。但Model和Domain還是有一點不同。Domain是領域的一個更廣的層面。而Model是解決Domain下特定問題的一些模型,也就是類似子集的概念。在具體的編程中有些時候是差不多的,此時你的Domain下有唯一的一個最大子集Model,就是Domain本身。但有時候一個Domain下可能有多個Model來共同成就一個Domain。這其實是一個粒度問題,得具體問題具體分析。

Ubiquitous Language

統一術語。大家都使用同一套行業話語體系,比如下單,預算單等等。這套話語體系也是衍生於「領域(Domain)」這個核心概念。並且是團隊內部成員之間以及團隊與團隊之間大家溝通的統一標準。

Bounded Context

這個概念核心就是Bounded,劃清界限,你是你,我是我,這麼做不是自私,而是一種明晰的分工體現。常用於跨團隊共同完成一個Context下的事情時。前面我們說的Context是一個沒有被標清邊界的Context,因為我們默認是沒有團隊協作的。但當涉及到團隊協作就需要一個有明確界限的Context,也就是BoundedContext。

比如一個大的系統,下面有一些子系統(subsystem),那麼這個子系統就是一個Bounded Context。另外比如我們的整個系統的一部分是由指定的另外的一個團隊來做,那麼這個團隊做的事情就是一個Bounded Context。

那麼這四個概念僅僅只是服務於吵架嗎?顯然不是,他還負責一個更高端的任務,那就是劃分系統邊界,特別適合分散式系統、微服務的拆分。這也是為什麼最近人們又開始討論DDD的原因之一吧。

實際代碼怎麼寫的?

DDD,我個人理解更多的是一門哲學。正如上面領域分層一節中說的那樣。DDD在最開始的時候,它是一個抽象的概念,這些抽象的概念你自己只能去領悟,直接後來,人們考慮到了技術人員喜歡二話不說上手的特點,決定進一步封裝成更高級的概念,這樣就好落地了,於是就有了entity、vo、aggregate等等。所以,如果這個問題你是希望更快上手,那麼就是後面的這些概念散落在了你的三層代碼中,entity目錄啦,service目錄了之類的。但DDD不僅僅這些。

DDD和微服務

可以說DDD和微服務是絕配。DDD本身就是一門哲學,它指引著你朝著美好的代碼結構不斷向前。如果說單體應用中,你可以不分青紅皂白的,馬馬虎虎,拉拉扯扯,黏黏糊糊的就可以寫完,那麼在微服務架構下,拆分的過程,以及拆分後的各自銜接的邊界劃分則是一項複雜的工程。恰好,DDD的核心就是用來劃分和理清邊界的。

配合使用

DDD的各種概念不是孤立存在的。你得配合起來使用。比如Context下是Domain,然後子系統是Bounded Context(有關Bounded Context的具體概念,你可以移步上面的「領域驅動吵架」那一節)。

為了讓你感受下Bounded Context以及和其他的概念的配合,上個圖:

有沒有體會到那麼一絲的韻味?

總結

好了,我們說了這麼多。總之你就記住DDD裡邊有很多的概念。但這些概念是可以分類的。有的概念是DDD的底層概念,比如Domain、Domain Logic。有的概念是高級概念,是後來基於底層概念開發的新概念,為了落地,比如Entity、Service、Value Object,Repositories等。還有一些概念是為了吵架和適應分散式系統的。比如Context、Bounded Context。通過這樣分類,你會發現,這麼多概念其實也蠻好理解的。還有就是,DDD,這個概念很早就有了,至少可以追溯到2004年,那個時候你是不是還在上小學。而且Spring框架里的好多概念和實現都是對DDD的一種踐行,值得去好好研究一番,光看看他的那些註解你就能感覺到了。對了,你的DDD旅程,別忘了從命名開始。

通過這次的整理學習,我明白了兩件事情:DDD真簡單,其實我們早就在使用了;DDD不簡單,它是一門哲學,簡單的形而上學的使用只是規範了你的代碼目錄,但涉及到更高層面的邏輯抽象,則需要在具體的代碼構建中慢慢體悟!

以上只是我個人觀點,歡迎拍磚!


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 ImportSource 的精彩文章:

TAG:ImportSource |