關於核心DDD的相關的描述

其實,在以前的Nature框架中已經描述了很多,不過,這裏,仍是想完整的闡述一下其中的概念。
不過,確定比較簡略,若是真的要深刻理解,仍是要讀《領域驅動設計》《實現領域驅動設計》這兩本書。
好啦,接下來進入正題。
首先是關於聚合的內容。咱們認爲,相關聯的一些事物,構成了一種叫作聚合的概念。好比,說到書,他就會有封皮,書名,每頁書,做者等等等等。他們是聚合在一塊兒的,說到書,就表明了那一堆東西。而書這個概念,咱們則稱之爲聚合。若是把每種東西抽象成類和引用的關係,則總會有一個東西在最上層,表達着總體的概念,咱們稱之爲聚合根。
那麼,聚合是由什麼構成的呢?值得一提的是,咱們如今在說的聚合的概念,是一種結構性質的東西,與之相對的,它不是一種流程。
而構成聚合的構件,咱們使用兩個東西,實體,值對象。
什麼是實體?什麼是值對象?以個人語言能力,解釋起來略困難了一點。這麼說吧,實體的特色是,具備生命週期,在其生命週期之中,其內部狀態可能會發生變化。可是,實體具備其惟一的標誌,即便兩個實體除了標誌外全部屬性均徹底相同,咱們也認爲他們是兩個實體。那麼,這個標誌是什麼呢?這也是我最近才領悟的,這個標誌,是值對象。說說值對象吧。值對象,如字面所述,是表示值的對象。它表示了一種值,那麼,它就具有了這麼幾個特徵。首先,它不會改變本身的一部分,或者說,它的狀態不會變,由於它沒有生命週期,因此,它沒有狀態。它要麼,是這個值,要麼是那個值,而不存在這個值能夠被變爲何的說法。其次,若是兩個值對象的全部狀態都相等了,那麼,它們就是同一個值,這個與實體可以造成鮮明的對比。
那麼,爲何說實體的標誌是值對象呢?曾經,咱們的框架中,爲了通用,將實體的標誌,設置成了字符串。這能夠知足惟一ID的需求,並且,也有最佳實踐告訴咱們,這樣管理全部的表是好的。可是,在我以往的實踐中就碰見過這種狀況。有的記錄是使用組合主鍵標誌本身的惟一性的。固然,咱們能夠經過添加一個惟一ID的方式來使其統一,但,這引發了兩個後果。首先,這增長了複雜度,其次,事情不是這樣的,而卻偏要這樣實現,後面會遇到麻煩,其實,也是增長了複雜度。而在讀《實現領域驅動設計》時,裏面強調的,即便只是一個字符串,其實,它也是一個值對象。這是咱們很容易混淆的一點,而值對象的引入,無疑,增長了咱們對值這一律唸的掌控。我但願在我此次的框架裏,能夠達到這一目的。最後說明一點,聚合根,必定是實體。
而聚合由實體和值對象構成,實體能夠經過自身的方法改變自身的狀態,而這些操做在聚合範圍內,也表明着實現了聚合自身的業務。由此,聚合表達了本身所表明的業務的含義。
其實,這裏,是有問題存在的。聚合是須要被持久化的東西,咱們須要長期得跟蹤其生命週期,改變其狀態。那麼,它的持久化,和讀取或者說加載是怎麼進行的呢?是由倉儲進行的。倉儲對聚合的持久化進行支持。提供了有限的幾個操做:建立,保存,刪除,經過標誌加載。而正如倉儲的字面意思,倉儲,是一個倉庫,作儲備只用。而其中存儲的東西,就是聚合。這裏還有幾個東西須要注意,既然,倉儲是操做聚合的東西,那麼,倉儲,就不會在聚合內部被調用。而聚合之間,也是相互獨立或者說是離散的。聚合和聚合之間,並沒有法直接相互操做,不然,他們就應該是一個聚合。
那,聚合之間的寫做是怎麼完成的呢?經過領域服務。那領域服務和聚合是什麼樣的關係呢?或者說,有什麼類似或者不一樣呢?聚合,表達了領域中的一些結構,他們有屬性,有生命週期,會被長時間的維護。而領域服務,也表達了領域中的一些結構,所不一樣的是,它沒有屬性,單純的,提供服務。好比說,轉帳。若是帳戶是一個聚合的話,那麼轉帳這個操做就會牽扯至少兩個聚合。顯而易見,在聚合內部是沒法完成這個操做,這裏須要一個服務來協調兩個帳戶進行轉帳,而這個服務,咱們則稱之爲領域服務。
在咱們團隊的實踐過程當中,老大最初定義的領域服務是面向用例的,而我認爲的領域服務是構成領域的一部分,而面向用例的那部分,不過是相似門戶的存在。不過,最近的一次實踐老大妥協了,容許兩種同時存在。而其實,面向用例的那部分,我在我以前的框架中,是定義爲命令,與應用服務進行通訊的。
那麼,什麼是應用服務呢?
其實,應用服務是獨立於領域以外的,它是面向應用的,面向用例的。咱們領域中的模型並不能直接在應用中使用,由於應用要的不必定是他,他不必定夠。因此,在應用服務中,會把領域中的東西,組裝成應用想要的東西,再丟給應用。應用服務,大概就是這樣的用處,轉發,同時,也可以防止領域被應用所腐蝕。
其實,這裏,還有兩個構造塊咱們沒有說,領域事件,查詢。
先說說領域事件吧。還以上面轉帳的例子來講,這,其實,是發生了一件事情。事實上來講,它除了把錢從一個帳戶轉到另外一個帳戶外,還記錄下了轉帳的流水。這是這個服務自己作的事情。而事實上,在以後,咱們爲了可以更加清晰的對系統進行監控,咱們引入了日誌。這裏,是須要記錄日誌的。怎麼記?修改原來的服務?能夠。只是,彷佛存在如下的問題。開閉原則,咱們修改了原來的代碼。單一職責原則,服務不只要進行本身的業務,還要記錄日誌。高內聚低耦合,原來的服務須要認識並使用日誌模塊,看樣子,日誌模塊會變得無所不在。那麼,咱們彷佛看到,隨着系統內容和複雜度的增長,這將會是一種災難。但是,咱們發現,事情並非這個樣子的。其實應該是,轉帳這件事發生了,由於這件事的發生,相關係統要進行對應的操做,好比,日誌系統要記錄日誌。那麼,發生的這件事,就是領域事件。領域事件的實現通常是發佈訂閱的模式來實現的,咱們這裏也是,這彷佛是很天然的一件事情。
剩下的構造塊,我稱之爲,查詢。這個,是我在讀了cqrs以後,引入的一個構造塊。不瞭解的你們能夠查一下cqrs的東西,之後有時間的話,我會整理一篇cqrs的文章。而cqrs採用事件溯源重構聚合,用領域事件更新查詢源,供應用查詢。而其解決的主要問題是,在經典DDD中,對業務的查詢,是複雜的,低效的,由於應用須要的查詢每每和領域自身的結構衝突,從而致使,連表查詢,致使查詢複雜度上升,效率下降。而起推崇以響應領域事件來維護一個供應用查詢的數據源,而這個數據源中的數據,是咱們爲了知足應用的查詢,而維護在那裏的。值得注意的是,咱們並無定義新的構造塊給這些數據,他們依然是,聚合,其實更接近dto,雖然有些不天然,可是,也算知足了咱們的須要。另外,咱們能夠經過屬性,來對這些數據進行查詢。


相關文章
相關標籤/搜索