一文講清領域模型和數據模型

一文講清領域模型和數據模型

前言

清晰的記得我第一次接到需求開始設計一個系統時候,開始抓腦怎么清晰的表達這個系統是干什么的,擁有什么服務能力,技術架構,業務模型是怎樣的,底層支撐具備什么能力等等。

你可能會想通過畫UML圖,利用Class Diagram模型,但是你會發現如果按照這個類圖去設計數據庫的畫,看起來非常繁瑣,也很奇怪,可是如果不按照這個類圖去設計的話,又不知道這個類圖畫了有什么用。

其實有這個疑問的最終糾結源是對數據模型和領域模型這兩個重要概念的不清楚。對這兩個概念很容易混淆,其結果就是,可能會影響一些模塊設計的不合理性,甚至影響像業務中臺這種技術上的局限性。因為如果底層的核心邏輯、理論概念基礎沒搞清楚的話,其構建在它之上的系統也會出現問題,一般還是非常嚴重的問題。

說了這么多,可能還是對上面說的存在疑問,下面我們進行比較深入的探討這個問題

什么是領域模型和數據模型

這兩者關注的重點或者說維度不太一樣。

領域模型關注的是領域本身,是業務領域的核心實體,體現在問題域關鍵概念和之間的聯系。構建領域模型的目標是看模型能否清晰表達業務語義、模型能否顯性化,擴展性是其次。

數據模型關注的是數據存儲,在我們所有的業務中都離不開數據,離不開對數據的CRUD。構建數據模型目標是看擴展性、性能等非功能屬性,業務語義的表達則是其次。

換一句話說,領域模型關注的是業務核心,數據模型關注的是技術細節,然而在我們開發中,二者都缺一不可,都很重要。之所以容易被混淆,是因為這兩個模型都在強調實體(Entity)和關系(Relationship),二者的確有一些共同點,在某些情況下數據模型和領域模型會長的很像,甚至會趨同,但是在大多數的情況下還是有區別的。所以應該在需求設計時候有意識將這兩個模型區分開,基于他們建模關注的目標不同分別設計。

在這里插入圖片描述

上圖清晰描述了領域和數據模型所承擔的職責。數據模型負責數據存儲,核心關注靈活性、擴展性,領域模型核心關注業務邏輯的實現,清晰顯性表達業務語言,利用面向對象的特性增強代碼的表達能力。

然而,我們如果不注意的話經常容易犯錯,一是將領域模型當做數據模型,或者是將數據模型當領域模型。

錯把領域模型當數據模型

舉個例子,過去做的一個商品價格區間項目,這里面涉及到不同商品類型、不同類目、品牌、時間季度等維度,商家會給出不同的價格區間設置,在不超過平臺的限制的前提下,商品審核通過即可設置完成價格。
思考這個需求,抽象出來就是針對不同商品我們會有一套規則,針對這個規則進行商品發布價格審核,領域模型很簡單,如下圖所示:


在這里插入圖片描述

如果這個按照領域模型來設計存儲的話,那么需要兩張表:價格規則表和價格區間表,一張表用來存儲具體的價格規則,另一張表用來存儲規則價格區間。

在這里插入圖片描述

如果是這樣的設計的話,那么擴展性將很差,設想后續新需求需要增加一個活動商品的活動價格區間,如果是兩張表的話,那么則需要在價格區間表中新增兩個Field,如果上線了則會涉及到表的變更會比較繁瑣,這就錯把領域模型當數據模型導致變麻煩了。

而如果按照數據模型來設計存儲的話,只需要一張表就夠了,把價格區間作為一個json字段在規則表中存儲,如下圖所示:


在這里插入圖片描述

如果這樣設計的很明顯好處就是首先維護一張數據庫表比兩張表的成本要小,其次數據的擴展性期更好,如果需要在價格區間中增加字段,則Json存儲,則數據模型可以不變。

您可能會問,這樣在業務代碼基于json操作會不會不太方便?確實,所以一般會將json數據對象轉成成業務語義表達的領域對象,這樣的話,既滿足了數據模型帶來的擴展便捷性,同時又不會丟棄領域模型對業務語義顯性化可讀性, 豈不美哉。

在這里插入圖片描述

錯把數據模型當領域模型

上面講到數據模型通過擴展來滿足業務需求,畢竟改動數據庫不管是加減字段,還是加表刪表都會涉及到不少的工作量。

像阿里的業務中臺這種底層數據模型設計的一定是非常合理的,可以支撐幾十個業務的成千上萬的不同場景,核心的商品、訂單、支付、物流等。

拿商品中臺IC來說,垂直類型商品類型、不同渠道類型、各種規則互斥,如何快速支撐業務迭代,就需要做到高度數據存儲擴展性,比如可以采用垂直表或者fetaure字段方式。但是這種雖然可以很好的解決存儲擴展問題,但是我們不能過度依賴,還是需要梳理出業務領域模型涉及,否則的話,你的代碼不是在面向對象編程,而是面向擴展編程,也就是錯把數據模型當領域模型。 帶來的后果就是代碼可讀性無法看,不可維護,更好的做法應該是將**數據對象(Data Object) 轉換成領域對象(Domain Object) **處理。

在具體落地的時候,這里有個方法可以借鑒,一般數據對象和領域對象之間是需要通過gateway來進行轉義, 一方面可以適配兩種模型過渡,另一方面還起到了解耦防腐作用,既解除了業務代碼對底層數據的直接依賴,也不失對業務語言的表達準確性。從而更好的提升系統的可維護性。

什么?你可能會說這TM不對吧,我記得之前大學課本上說過在設計關系型數據庫要滿足3NF(三范式)

同學,該醒醒了,其實在實際工作中,我們由于各種原因就是要打破這個規則,出于對性能考慮、對擴展性考慮,查詢鏈路可能由于為了少走訪問磁盤db冗余字段處理提升訪問性能。

業務場景不同,對他們的擴展粘性強度也不一樣,比如數據擴展性做到了,可是查詢怎么處理,總不能在json里做like查詢吧,其實大可不必,倘若說數據量預估不會大的數據,完全可以處理,而像阿里商品,訂單這種海量數據,當然不能,一般就需要考慮讀寫分離、構建搜索來處理。

領域對象是連接數據模型和領域模型之間的橋梁。 不管怎樣,在面向問題域,都需要帶著這兩種模型來均衡思考,設計出更好的模型更好支撐業務。

最后

  1. 覺得有收獲,幫忙關注轉發下哈,感謝感謝。
  2. 本文以獲得原作者授權,出處。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 第8章 大數據領域建模綜述第9章 數據整合及管理體系第10章 維度設計(重點!)第11章 事實表設計 第8章 大數...
    天線嘟嘟茄閱讀 3,059評論 0 1
  • 加一個導航,關于如何設計聚合的詳細思考,見這篇文章。 2004年Eric Evans 發表Domain-Drive...
    天堂鳥6閱讀 1,213評論 0 1
  • 本文的內容來自數據之路閱讀并記錄一些知識點和流程 1.為什么需要數據建模 數據爆發帶來的挑戰:數據進行有序 有結構...
    冰菓_閱讀 1,042評論 1 9
  • 表情是什么,我認為表情就是表現出來的情緒。表情可以傳達很多信息。高興了當然就笑了,難過就哭了。兩者是相互影響密不可...
    Persistenc_6aea閱讀 125,919評論 2 7
  • 16宿命:用概率思維提高你的勝算 以前的我是風險厭惡者,不喜歡去冒險,但是人生放棄了冒險,也就放棄了無數的可能。 ...
    yichen大刀閱讀 6,098評論 0 4