2017首屆領域驅動技術大會一直是我非常期望的,要非常感謝右軍贈送的門票能夠讓我領略大會風采。
image.png
這屆大會組織者非常用心,組織了非常多的話題可供探讨,确實大會的内容給我帶來的感覺是震撼的,我之前對領域的了解也僅從《領域驅動設計》以及《實作領域驅動設計》這兩本書中有過學習,以及在實作微服務生态體系的過程中有過一些接觸。
在大會的整個程序中,聽了很多老師不同主題的演講,讓我印象極為深刻的還是:張逸老師的《Bounded Context的實踐意義》、騰雲老師的《DDD-沒那麼難》。下面我将分别結合這二個議題談談我自己的一些想法。
Bounded Context(限界上下文)的實踐意義
(因為光線和距離的原因照片可能不清晰,望大家見諒)
首先我們先來解釋一下,什麼是限界上下文。
《實作領域驅動設計》這本書中解釋到:限界上下文是一個顯式邊界,領域模型便存在于邊界之内。在邊界内,通用語言中的所有術語和詞組都有特定的含義,而模型需要準确地反映通用語言。
用一段更形象的語言來描述:我們每天都去上班,上班的時候會換乘地鐵,我從8号線下車,換乘2号線,然後再去換乘10号線,這樣最終到達某一個地點,結束上班這個過程。在這個過程中,8号線、2号線和10号線都可以了解為不同的限界上下文,我們中間換乘的動作可以了解為領域事件,而我們最終的目标是為了上班,這個就是關鍵事件,我們上班就是在不同的上下文中切換。
我們還可以把上下文了解為一個子產品,一個系統、一個應用或者一個服務。在我看來,限界上下文的存在對微服務的劃分是有重大意義的,但是限界上下文不是新的概念,早在SOA時代就已經存在,隻是當時在企業應用的時候并沒有将SOA和DDD過多的聯系在一起,不知道還有多少同學知道闆橋裡人(彭晨陽)的,早在2008年的時候在他的json網站中就已經對SOA和DDD的關系做過一些解釋:
SOA服務是在松耦合元件分離後的再次打包,而Evans DDD則是一把切斷元件關系的利刃。從這個方面看,DDD應該是更基礎平台,萬丈高樓平地起啊,而DDD是對象方法論集大成,集合分析模式和設計模式
----出自
SOA 與 DDD
通過當時的文章和解釋我們不難看出實際上在SOA中更多的是使用DDD的OO來取代資料庫分析設計,SOA是粗粒度的服務化打包,而DDD則是一把斬斷粗粒度的利刃。正如這次大會張逸老師一句玩笑的話所說,正因為微服務拯救了DDD,通過這句話可以看出微服務的提出是真正的将DDD給與結合在了一起,而微服務的細粒度的服務與DDD本身的理念也是契合,進而達到了互相發展的境界。
張逸老師在這次演講中深入探讨了幾個關鍵詞:康威定律,邏輯邊界和實體邊界,切斷資料庫的耦合、識别上下文的方法等等,能夠明顯的感覺出來,DDD也在發展也在和微服務和網際網路領域不斷的演進。
DDD-沒那麼難
騰雲老師的分享更多是在實踐過程中的總結,首先談了資料驅動與領域驅動的不同點,表格如下:
資料驅動 | 領域驅動 |
---|---|
資料庫優先 | 領域模型優先 |
算法和資料機械結合 | 算法和資料有機結合 |
技術導向 | 業務導向 |
代碼不能反映業務 | 代碼即是設計 |
業務邏輯分散 | 業務邏輯内聚 |
擴充性差 | 擴充性佳 |
我記得在2010年以前,研發人員和産品聊完需求後第一步就是要使用PowerDesigner畫資料庫表結構圖,根據資料庫表結構圖倒推項目架構,後面DDD開始推廣以來,慢慢的由UML圖開始逐漸占用主導地位,現在表結構圖已經成為架構設計的補充。
在DDD中常見二種設計模型,分别是貧血模型和充血模型。
-
貧血模型
貧血模型是指領域對象裡隻有get和set方法,僅包含狀态(屬性),不包含行為(方法),采用這種設計時,需要分離出DB層,專門用于資料庫操作。
從圖中可以看出領域層的職責很弱,領域對象隻是用來充當資料存儲的對象。但是這種模型整體架構清晰,自上而下單向連接配接。
遠端通路接口 -> Facade接口 -> Service服務 -> 領域層 -> DAO -> 資料庫
-
充血模型
充血模型是貧血模型的相對定義,在這個模型中領域層的作用較大,不再是get和set方法的集合,而是将部分業務邏輯以及持久化的操作內建在内,如下圖所示:
這種模型的調用關系則變成了:
應用層 -> Facade接口 -> 領域層 -> 基礎設施層
其實這樣的好處就是與領域對象相當的業務邏輯封裝在對象内部,biz或者service層隻需要調用對象進行簡單的業務組裝即可,不像貧血模型那樣所有業務都集中在biz層或者service層中造成非常沉重難以拆分,但充血模型比較難以設計,需要有一定經驗的設計師前期規劃好,後期工作才能事半功倍,不然則會造成項目混亂。
在分享中騰雲老師還做了實體和值對象的講解,下面我将這二者的差別以表格的方式列出來供參考:
實體 | 值對象 |
---|---|
具有生命周期 | 起描述作用 |
有唯一辨別 | 無唯一辨別 |
通過ID判斷相等性 | 實作equals方法 |
增删改查/持久化 | 即時建立用完就扔 |
可變 | 不可變 |
比如Order/Car | 比如Address/Color |
看到這裡讓我突然想起一個故事來:
有一對雙胞胎,他們出生的時候,長得一模一樣,以至于爸媽都分不清,不得已他們在雙胞胎的脖子上系個項鍊來标記:誰是老大?誰是老二?其實這個“标記”就可以看作是實體的辨別,隻不過是用項鍊來辨別的。
有一天小鎮要統計雙胞胎的分布情況,然後調查人員來到他們家,問他們爸媽:“你們家裡有沒有雙胞胎?幾對雙胞胎?龍鳳胎?還是。。。”,然後他們爸媽就報上:“一對雙胞胎-兩個小子”,然後調查人員就做了筆記走了。在這個過程中,他們絲毫沒有提及雙胞胎脖子上的“項鍊”。
這也就是實體和值對象的根本差別:實體不僅需要知道它是什麼?而且還需要知道它是哪個?而值對象隻需要知道它是什麼就可以了。
小結
夜已深,文章寫到這裡,我想也應該可以結束了,大會的内容非常豐富,在這裡隻是把我看到的、聽到的,結合我自己的一些想法看法總結出來,文章難免有些地方比較偏面還望大家海涵。
參考文章 http://raychase.iteye.com/blog/1328224 https://www.cnblogs.com/xishuai/p/ddd-entity-value-object.html