DDD早在2004年就由埃里克·埃文斯提出,但一直處于不溫不火的狀態(tài),直到微服務盛行之后,DDD再次回到人們視野之中。京東、美團、華為等巨頭也都在自家架構中實踐了DDD。
DDD究竟有什么優(yōu)勢?它是如何落地的?實施難點又在哪里?結合惟客數(shù)據(jù)實踐DDD的經(jīng)驗,今天就來一起探討下。
咱們先從一個場景說起。
通常在研發(fā)流程中,需求評審完畢后就交由某個研發(fā)做設計,方案的設計完全取決于某個人的經(jīng)驗和對依賴模塊的熟悉程度,可能很難識別出模塊設計上的不合理。即使可以識別出,往往都會以技術的語言和產品經(jīng)理進行溝通,產品經(jīng)理可能很難理解,最終難達到預期的目的。
以惟客服務過的某地產集團案例為例??蛻舻脑V求是實現(xiàn)“轉贈功能”,比如用戶A下單5件商品,將其中2件轉贈給用戶B,此時用戶B的“我的訂單”欄會出現(xiàn)一筆含有2件商品的訂單,且不可退款的同時,用戶B還可以再次實行轉贈。
這意味著需要在訂單領域生成一種“特殊的訂單”和“特殊的拆單”,該訂單僅能使用且不能退款。
需求評審完后,產品、研發(fā)一起開始做“領域建模”,由于涉及訂單領域,也對照之前的“訂單模型圖”做了方案的設計,發(fā)現(xiàn)訂單域承載更多的是交易相關,把轉贈業(yè)務耦合進來,十分困難。
但研發(fā)在模型圖里發(fā)現(xiàn)了專門承載履約的“核銷聚合根”,只要核銷權限能轉出去,就可以滿足業(yè)務場景,產品經(jīng)理也十分認可,最終將產品做了修改,將原先的訂單轉送,變?yōu)榱寺募s權限的轉贈。
在上面的案例中,無論從產品設計角度,還是轉贈場景和交易場景,劃分都更清晰;從代碼設計角度,減少沖擊到訂單域,避免現(xiàn)實中獨立的兩塊業(yè)務在系統(tǒng)中耦合成一個模塊,從而造成訂單的核心代碼被沖擊,后續(xù)難維護的后果。最終實現(xiàn)了“多贏”的局面。
這種“多贏”的局面,就取決于DDD過程中帶給我們的幾點改變:
1、領域模型設計一定程度上拉齊了團隊的設計水平,不再取決于某幾個人的“經(jīng)驗”。
2、產品、研發(fā)建模的過程中,深究業(yè)務場景,推導出技術設計的同時也回補了需求漏洞。
3、團隊內統(tǒng)一語言,尤其是產品和研發(fā)之間,溝通成本低,減少了由于理解差異導致的風險。
4、原先依賴的模塊,也采用了DDD的設計,有完整的模型文檔,并且有效識別出來了“訂單聚合”、“核銷聚合”,才使得轉贈模塊在做設計有了很好的基礎。
基于對以上場景的了解,我們再回歸定義,從定義出發(fā),一步步拆解。
概念理解:DDD是什么?
DDD全稱是領域驅動設計,這里的“領域”可以理解為業(yè)務邊界,以及指定范圍內待解決的業(yè)務問題。因此DDD它不是一種架構,而是一套思想,是一種拆解業(yè)務、劃分業(yè)務、確定業(yè)務邊界的方法。
DDD可以通過合理運用面向對象的封裝、繼承、多態(tài)等設計要素,降低或隱藏整個系統(tǒng)的業(yè)務復雜性,幫助我們設計出清晰的領域和邊界,并使得系統(tǒng)具有更好的擴展性,很好的實現(xiàn)技術架構的演進,應對紛繁多變的現(xiàn)實業(yè)務問題。
DDD的優(yōu)勢在哪里?
程序員擅長從技術角度來解決項目問題。但一個軟件系統(tǒng)是否真正可用,需要通過其提供的業(yè)務價值來體現(xiàn)。因此在關注技術的同時,DDD更強調將關注點轉向軟件系統(tǒng)所提供的業(yè)務價值。
我們先回顧下產研團隊的協(xié)作模式,通常是將一個產品開發(fā)上線的各個過程拆出來,由市場/運營、產品、UI交互、前端、后端、測試等角色來做分工,每個過程專人負責。
這么做的好處是標準流水線作業(yè),個體生產效率比較高,但壞處是大家都盯著眼前的一畝三分地,自然很容易忽略整體,更難從整體業(yè)務價值出發(fā)。同時也容易出現(xiàn)信息不對稱的問題,比如產品在討論A時,前端以為是說B。
那么,根據(jù)惟客數(shù)據(jù)在核心產品“惟客云”中實踐DDD的經(jīng)驗總結,其優(yōu)勢可以包含以下幾點:
統(tǒng)一語言:領域專家、產品、技術、測試等人員都在一起進行事件風暴(整理出相關聯(lián)的業(yè)務指令和事件),在同一個場景下使用統(tǒng)一語言進行領域模型構建,信息傳遞不會丟失。
提高效率:設計就是代碼、代碼就是設計,可以根據(jù)領域模型圖對編輯進行翻譯,即使是新人接手也能快速理解整個業(yè)務和代碼,上手就能寫。
邊界清晰:戰(zhàn)略設計幫助產品決策人理解哪些投入是最重要的、哪些既有軟件資產是可以重新拿來使用的、哪些人應該被加入團隊中?戰(zhàn)術設計則幫助產品研發(fā)人員具體實施。
降低成本:先劃分業(yè)務邊界,確認核心業(yè)務,避免伴隨功能迭代后的代碼不斷疊加,導致代碼耦合,降低維護成本。
以降低成本為例,假設我們要做一個電商訂單下單需求,涉及到用戶選定商品,下訂單、支付訂單、對用戶下單時的訂單發(fā)貨:
常見做法是在分析好業(yè)務需求之后,開始設計表結構,訂單表、支付表、商品表等等,然后編寫業(yè)務邏輯當功能迭代,訂單支付后要支持取消,下單商品要支持退換貨,就又需要加表,并針對實現(xiàn)的邏輯不斷進行修改。這也意味著當功能不斷迭代,代碼也會層層上疊。
而DDD要求先劃分業(yè)務邊界。該場景下的核心是訂單,那么訂單就是業(yè)務領域里的聚合邏輯體現(xiàn)。支付、商品信息、地址等等都是圍繞訂單實體。訂單本身的屬性決定之后,類似于地址只是一個屬性的體現(xiàn)。當你將訂單的領域模型構建好之后,衍生了倉庫的上下文。
總結來說,DDD優(yōu)勢在質量、效率、成本3方面都得到了體現(xiàn)。
惟客是如何實踐DDD的?
從時間線來說,可以分為3個階段:
2020年7月,引入DDD,在小項目和模塊進行試點;
2021年6月,完成在大會員模塊進行實踐和應用;
2022年3月,完成公司交易、營銷、會員、家裝產品線的改造和重構。
重點以3月份的項目為例。惟客投入70人參與本次項目,目的是解決老舊項目之間耦合嚴重、業(yè)務邊界不清晰、代碼重復率高、維護成本高等問題。從落地步驟來拆,包括5個部分:
需求評審
1、過需求、了解相關聯(lián)業(yè)務的用戶故事
2、產品輸出用戶故事地圖、原型圖、流程圖,開發(fā)理解相關資料
拆用戶故事
1、對照用戶故事地圖將用戶故事進行細分
2、整理出相關聯(lián)的業(yè)務指令和事件(事件風暴)
3、用戶故事評審,確保需求沒遺漏、業(yè)務指令和事件劃分正確
領域模型圖設計
1、識別應用上下文,劃分領域界限(核心、通用、支領域),拆分成多個子域
2、根據(jù)用戶故事及業(yè)務指令區(qū)分出查詢模型和命令模型
3、在領域內繪制出相關聯(lián)業(yè)務的領域模型圖(包含查詢模型、聚合、聚合內聚合根、實體、值對象的關系、實體具有的能力、領域服務、領域事件)
4、領域模型圖評審
代碼實現(xiàn)
1、對照領域模型圖建業(yè)務指令、事件、實體、值對象、實體能力及領域服務
2、完成領域模塊開發(fā),建db入庫
3、代碼評審,對照領域模型圖
4、完成所有業(yè)務開發(fā)
單元測試
1、對于聚合能力的單元測試
2、領域服務,指令的單元測試
實踐過程中遇到哪些問題
為創(chuàng)建通用語言騰出來的時間和精力
通用語言是指非技術崗位也能很容易理解的語言,在目標拉齊的基礎上,需要拉齊各個角色對術語都使用統(tǒng)一名詞,對業(yè)務價值以及規(guī)則的描述使用統(tǒng)一的描述方式和規(guī)則,并且需要使得每一個人都能聽的懂。
以商品條形碼為例:
領域專家:從場景角度分析,它主要是供小程序掃描這個條形碼進行購買商品
產品:從規(guī)則角度分析,商品編碼,長度是多少位,組成規(guī)則是什么。
開發(fā):按照功能事項的角度去分析,barcode,商品的sku級別的唯一標識,存儲方式是什么。
很明顯,大家分析問題的角度不一樣,給出的語言不同,但本質上商品條形碼=商品編碼=barCode,因此需要花時間拉齊不同角色間的語言。
領域專家對于實踐DDD很重要,但這個角色通常是業(yè)務專家,他們工作繁忙、時間難約,較難持續(xù)在一個項目中消耗太多時間。
因此在落地中,建議盡可能一次性把業(yè)務相關的疑問和問題準備好,減少對接次數(shù)、提高效率。
由過程編碼 -> 面向對象編碼
由數(shù)據(jù)模型 -> 領域模型
領域模型關注的是領域本身,是業(yè)務領域的核心實體,體現(xiàn)在問題域關鍵概念和之間的聯(lián)系。構建領域模型的目標是看模型能否清晰表達業(yè)務語義、模型能否顯性化,擴展性是其次。
數(shù)據(jù)模型關注的是數(shù)據(jù)存儲,在我們所有的業(yè)務中都離不開數(shù)據(jù),離不開對數(shù)據(jù)的CRUD。構建數(shù)據(jù)模型目標是看擴展性、性能等非功能屬性,業(yè)務語義的表達則是其次。
人最難轉變的是思維慣性,而不是技術和策略本身。因此在實踐前,對以上3點有心理預期,并提前做好應對方案,可以更快地落地DDD。
總之,如果企業(yè)希望能更好地發(fā)揮軟件系統(tǒng)的業(yè)務價值,從長期價值主義出發(fā),提高代碼的可維護性、可擴展性,那么DDD絕對是一套值得嘗試的方法
(免責聲明:本網(wǎng)站內容主要來自原創(chuàng)、合作伙伴供稿和第三方自媒體作者投稿,凡在本網(wǎng)站出現(xiàn)的信息,均僅供參考。本網(wǎng)站將盡力確保所提供信息的準確性及可靠性,但不保證有關資料的準確性及可靠性,讀者在使用前請進一步核實,并對任何自主決定的行為負責。本網(wǎng)站對有關資料所引致的錯誤、不確或遺漏,概不負任何法律責任。
任何單位或個人認為本網(wǎng)站中的網(wǎng)頁或鏈接內容可能涉嫌侵犯其知識產權或存在不實內容時,應及時向本網(wǎng)站提出書面權利通知或不實情況說明,并提供身份證明、權屬證明及詳細侵權或不實情況證明。本網(wǎng)站在收到上述法律文件后,將會依法盡快聯(lián)系相關文章源頭核實,溝通刪除相關內容或斷開相關鏈接。 )