阿里高级技术专家张建飞:深度剖析领域模型vs数据模型的用法
張建飛 frank
讀完需要
21
分鐘速讀僅需 7 分鐘
阿里巴巴高級技術專家,著有圖書《代碼精進之路 從碼農到工匠》,維護公眾號《從碼農到工匠》 ID:craftsman_frank
阿里妹導讀:什么是領域模型?什么又是數據模型?兩者可以等同嗎?在實際應用中,怎么樣才能用好它們?本文介紹領域模型和數據模型的概念定義,并舉例說明兩者相互混淆的錯誤用法,分享如何正確地應用它們。
依稀記得我第一次設計一個系統的時候,畫了一堆UML(Unified Modeling Language,統一建模語言)圖,面對Class Diagram(其實就是領域模型),糾結了好久,不知道如何落地。因為,如果按照這個類圖去落數據庫的話,看起來很奇怪,有點繁瑣。可是不按照這個類圖落庫的話,又不知道這個類圖畫了有什么用。
現在回想起來,我當時的糾結源自于我對領域模型和數據模型這兩個重要概念的不清楚。最近,我發現對這兩個概念的混淆不是個例,而是非常普遍的現象。其結果就是,小到會影響一些模塊設計的不合理性,大到會影響像業務中臺這樣重大技術決策,因為如果底層的邏輯、概念、理論基礎沒搞清楚的話,其構建在其上的系統也會出現問題,非常嚴重的問題。
鑒于很少看到有人對這個話題進行比較深入的研究和探討,我覺得有必要花時間認真明晰這兩個概念,幫助大家在工作中,更好的做設計決策。
一? 領域模型和數據模型的概念定義
領域模型關注的是領域知識,是業務領域的核心實體,體現了問題域里面的關鍵概念,以及概念之間的聯系。領域模型建模的關鍵是看模型能否顯性化、清晰的表達業務語義,擴展性是其次。
數據模型關注的是數據存儲,所有的業務都離不開數據,都離不開對數據的CRUD,數據模型建模的決策因素主要是擴展性、性能等非功能屬性,無需過分考慮業務語義的表征能力。
按照Robert在《整潔架構》里面的觀點,領域模型是核心,數據模型是技術細節。然而現實情況是,二者都很重要。
這兩個模型之所以容易被混淆,是因為兩者都強調實體(Entity),都強調關系(Relationship),這可不,我們傳統的數據庫的數據模型建模就是用的ER圖啊。
是的,二者的確有一些共同點,有時候領域模型和數據模型會長的很像,甚至會趨同,這很正常。但更多的時候,二者是有區別的。正確的做法應該是有意識地把這兩個模型區別開來,分別設計,因為他們建模的目標會有所不同。如下圖所示,數據模型負責的是數據存儲,其要義是擴展性、靈活性、性能。而領域模型負責業務邏輯的實現,其要義是業務語義顯性化的表達,以及充分利用OO的特性增加代碼的業務表征能力。
然而,現實情況是,我們很多的業務系統設計,并沒有很好的區分二者的關系。經常會犯兩個錯誤,一個是把領域模型當數據模型,另一個是把數據模型當領域模型。
二? 錯把領域模型當數據模型
這幾天我在做一個報價優化的項目,里面涉及到報價規則的問題,這塊的業務邏輯大意是說,對于不同的商品(通過類目、品牌、供應商類型等維度區分),我們會給出不同的價格區間,然后來判斷商家的報價是否應該被自動審核(autoApprove)通過,還是應該被自動攔截(autoBlock)。
對于這個規則,領域模型很簡單,就是提供了價格管控需要的配置數據,如下圖所示:
如果按照這個領域模型去設計我們的存儲的話,自然是需要兩張表:price_rule和price_range,一張用來存價格規則,一張是用來存價格區間。
如果這樣去設計數據模型,我們就犯了把領域模型當數據模型的錯誤。這里,更合適的做法是一張表就夠了,把price_range作為一個字段在price_rule中用一個字段存儲,如下圖所示,里面的多個價格區間信息用一個JSON字段去存取就好了。
這樣做的好處很明顯:
首先,維護一張數據庫表肯定比兩張的成本要小。
其次,其數據的擴展性更好。比如,新需求來了,需要增加一個建議價格(suggest price)區間,如果是兩張表的話,我需要在price_range中加兩個新字段,而如果是JSON存儲的話,數據模型可以保持不變。
可是,在業務代碼里面,如果是基于JSON在做事情可不那么美好。我們需要把JSON的數據對象,轉換成有業務語義的領域對象,這樣,我們既可以享受數據模型擴展性帶來的便捷性,又不失領域模型對業務語義顯性化帶來的代碼可讀性。
三? 錯把數據模型當領域模型
的確,數據模型最好盡量可擴展,畢竟,改動數據庫可是個大工程,不管是加字段、減字段,還是加表、刪表,都涉及到不少的工作量。
說到數據模型的擴展設計經典之作,非阿里的業務中臺莫屬,核心的商品、訂單、支付、物流4張表,得益于良好的擴展性設計,就支撐了阿里幾十個業務的成千上萬的業務場景。
拿商品中臺來說,它用一張auction_extend垂直表,就解決了所有業務商品數據存儲擴展性的需求。理論上來說,這種數據模型可以滿足無限的業務擴展。
JSON字段也好,垂直表也好,雖然可以很好的解決數據存儲擴展的問題,但是,我們最好不要把這些擴展(features)當成領域對象來處理,否則,你的代碼根本就不是在面向對象編程,而是在面向擴展字段(features)編程,從而犯了把數據模型當領域模型的錯誤。更好的做法,應該是把數據對象(Data Object)轉換成領域對象來處理。
如下所示,這種代碼里面到處是getFeature、addFeature的寫法,是一種典型的把數據模型當領域模型的錯誤示范。
四? 領域模型和數據模型各司其職
上面展示了因為混淆領域模型和數據模型,帶來的問題。正確的做法應該是把領域模型、數據模型區別開來,讓他們各司其職,從而更合理的架構我們的應用系統。
其中,領域模型是面向領域對象的,要盡量具體,盡量語義明確,顯性化的表達業務語義是其首要任務,擴展性是其次。而數據模型是面向數據存儲的,要盡量可擴展。
在具體落地的時候,我們可以采用COLA[1]的架構思想,使用gateway作為數據對象(Data Object)和領域對象(Entity)之間的轉義網關,其中,gateway除了轉義的作用,還起到了防腐解耦的作用,解除了業務代碼對底層數據(DO、DTO等)的直接依賴,從而提升系統的可維護性。
此外,教科書上教導我們在做關系數據庫設計的時候,要滿足3NF(三范式),然而,在實際工作中,我們經常會因為性能、擴展性的原因故意打破這個原則,比如我們會通過數據冗余提升訪問性能,我們會通過元數據、垂直表、擴展字段提升表的擴展性。
業務場景不一樣,對數據擴展的訴求也不一樣,像price_rule這種簡單的配置數據擴展,JSON就能勝任。復雜一點的,像auction_extend這種垂直表也是不錯的選擇。
wait,有同學說,你這樣做,數據是可擴展了,可數據查詢怎么解決呢?總不能用join表,或者用like吧。實際上,對一些配置類的數據,或者數據量不大的數據,完全可以like。然而,對于像阿里商品、交易這樣的海量數據,當然不能like,不過這個問題,很容易通過讀寫分離,構建search的辦法解決。
五? 關于擴展的更多思考
最后,再給一個思考題吧。
前面提到的數據擴展,還都是領域內的有限擴展。如果我連業務領域是什么還不知道,能不能做數據擴展呢?可以的,Salesforce的force.com就是這么做的,其底層數據存儲完全是元數據驅動的(metadata-driven[2]),他用一張有500個匿名字段的表,去支撐所有的SaaS業務,每個字段的實際表意是通過元數據去描述的。如下圖所示,value0到value500都是預留的業務字段,具體代表什么意思,由metadata去定義。
說實話,這種實現方式的確是一個很有想法,很大膽的設計,也的確支撐了上面數以千計的SaaS應用和Salesforce千億美金的市值。
只是,我不清楚從元數據到領域對象的映射,Salesforce具體是怎么做的,是通過他們的語法糖Apex?如果沒有領域對象,他們的業務代碼要怎么寫呢?反正據在Salesforce里面做vendor的同學說,他們所謂的Low-Code,里面還是有很多用Apex寫的代碼,而且可維護性一般。
anyway,我們絕大部分的應用都是面向確定問題域的,不需要像Salesforce那樣提供“無邊際”的擴展能力。在這種情況下,我認為,領域對象是最好的連接數據模型和業務邏輯的橋梁。
相關鏈接
[1]https://github.com/alibaba/COLA
[2]https://developer.salesforce.com/wiki/multi_tenant_architecture
- EOF -
想要加入中生代架構群的小伙伴,請添加群合伙人大白的微信
申請備注(姓名+公司+技術方向)才能通過哦!
阿里技術精彩文章推薦
往期推薦
深度:揭秘阿里巴巴的客群畫像
多隆:從工程師到阿里巴巴合伙人
阿里技術專家楚衡:架構制圖的工具與方法論
螞蟻集團技術專家山丘:性能優化常見壓測模型及優缺點
阿里文娛技術專家戰獒: 領域驅動設計詳解之What, Why, How?
阿里專家馬飛翔:一文讀懂架構整潔之道
阿里專家常昊:新人如何上手項目管理?
螞蟻集團沈凋墨:Kubernetes-微內核的分布式操作系統
阿里合伙人范禹:常掛在阿里技術人嘴邊的四句土話
阿里技術專家都鐸:一文搞懂技術債
支付寶研究員兼OceanBase總架構師楊傳輝:我在數據庫夢之隊的十年成長路
阿里技術專家麒燁:修煉測試基本功
阿里計算平臺掌門人賈揚清:我對人工智能方向的一點淺見
螞蟻資深算法專家周俊:從原理到落地,支付寶如何打造保護隱私的共享智能?
阿里高級技術專家簫逸:如何畫好一張架構圖?
阿里高級技術專家張建飛:應用架構分離業務邏輯和技術細節之道
螞蟻科技 Service Mesh 落地實踐與挑戰 | GIAC 實錄
阿里6年,我的技術蛻變之路!
螞蟻集團涵暢:再啟程,Service Mesh 前路雖長,尤可期許
阿里P9專家右軍:大話軟件質量穩定性
阿里合伙人程立:阿里15年,我撕掉了身上兩個標簽
阿里高工流生 | 云原生時代的 DevOps 之道
阿里高級技術專家邱小俠:微服務架構的理論基礎 - 康威定律
阿里P9專家右軍:以終為始的架構設計
阿里P8架構師:淘寶技術架構從1.0到4.0的架構變遷!12頁PPT詳解
阿里技術:如何畫出一張合格的技術架構圖?
螞蟻資深技術專家王旭:開源項目是如何讓這個世界更安全的?
阿里資深技術專家崮德:8 個影響我職業生涯的重要技能
儒梟:我看技術人的成長路徑
阿里高級技術專家宋意:平凡人在阿里十年的成長之旅
阿里技術專家甘盤:淺談雙十一背后的支付寶LDC架構和其CAP分析
阿里技術專家光錐:億級長連網關的云原生演進之路
阿里云原生張羽辰:服務發現技術選型那點事兒
螞蟻研究員玉伯:做一個簡單自由有愛的技術人
阿里高級技術專家至簡: Service Mesh 在超大規模場景下的落地挑戰
阿里巴巴山獵:手把手教你玩轉全鏈路監控
阿里涉江:你真的會學習嗎?從結構化思維說起
螞蟻金服資深技術專家經國:云原生時代微服務的高可用架構設計
深入分布式緩存之EVCache探秘開局篇
? ?END ? ?? #架構師必備#總結
以上是生活随笔為你收集整理的阿里高级技术专家张建飞:深度剖析领域模型vs数据模型的用法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: NYOJ 664 数字整除
- 下一篇: 我苦心搭建的技术架构,终于把公司干没了…