周六參加了ThoughtWorks組織的DDD領(lǐng)域驅(qū)動設(shè)計的分享和Workshop,算是對DDD有了第一次學(xué)習(xí)和體會。
在參加分享之前,對于DDD只是聽過幾次這個名字而已,其背后的具體細(xì)節(jié)完全不了解。由于自己知道一些TDD測試驅(qū)動開發(fā)的知識,所以本能的認(rèn)為DDD也是一種分析需求最終得到好代碼的手段。也就是說我所想象的DDD其目的是側(cè)重于得到好代碼。不過聽了演講者的分享后,我覺得之前的認(rèn)知是錯誤的。DDD的側(cè)重點似乎更偏向于業(yè)務(wù)層面的梳理,它強調(diào)的是首先從業(yè)務(wù)架構(gòu)的視角入手來分析用戶的需求,并以這個活動為中心,連接其他兩個重要的設(shè)計活動 -- 系統(tǒng)架構(gòu)設(shè)計和技術(shù)架構(gòu)設(shè)計。演講者舉了一些例子,比如曾經(jīng)他們參與過一個IBM的項目,當(dāng)時每次與客戶溝通時,都是通過一個數(shù)據(jù)庫ER關(guān)系圖來進(jìn)行溝通。結(jié)果在項目進(jìn)行了N年之后宣告失敗,原因是不滿足客戶的業(yè)務(wù)需求。如果從這個例子來理解DDD的目標(biāo),我覺得可以這樣看,當(dāng)軟件系統(tǒng)的實現(xiàn)者拿到客戶的需求后,首先就開始考慮ER關(guān)系圖、spring-struts-hibernate、MVC、微服務(wù)這種技術(shù)手段的話,其方式是在讓業(yè)務(wù)來適配技術(shù),而且開發(fā)與客戶溝通、開發(fā)人員內(nèi)部自己溝通時,也是以技術(shù)作為承載各自意圖傳遞的工具的話,就容易出現(xiàn)需求溝通上的困難,大家很容易對需求的理解造成偏差,最終導(dǎo)致在代碼實現(xiàn)上出現(xiàn)錯誤。而這正是DDD認(rèn)為的問題所在,DDD認(rèn)為這個應(yīng)該反過來,即應(yīng)該技術(shù)來適配業(yè)務(wù),業(yè)務(wù)是核心,是出發(fā)點。
具體的辦法上,DDD的手段是通過分析用戶的需求,來建立業(yè)務(wù)的模型。業(yè)務(wù)模型是對用戶業(yè)務(wù)的一種描述,這里不涉及到任何技術(shù)上的元素,在構(gòu)建這個模型過程中,我們不會考慮要選什么編程語言,要用什么數(shù)據(jù)庫,我們的數(shù)據(jù)庫表字段有哪些,我們是用微服務(wù)還是不用,我們的模塊應(yīng)該怎么劃分等等這些實現(xiàn)上的問題。建立業(yè)務(wù)模型的目標(biāo)在于勾勒出用戶業(yè)務(wù)的全景,充分的通過與用戶的溝通來了解用戶的核心問題域,也就是用戶最想解決哪些問題,什么對他是最有價值的。并且,通過業(yè)務(wù)模型,用戶和開發(fā)之間、開發(fā)人員內(nèi)部有了一種共同的溝通語言,而不是像前面的例子那樣用技術(shù)的語言進(jìn)行信息傳遞。所有人都可以更好的理解和傳達(dá)業(yè)務(wù)領(lǐng)域的各種概念,盡量的做到客戶的需求、意圖、業(yè)務(wù)知識被正確的理解,沒有遺漏。
具體怎么建模,DDD提出了一套方法論。這次的活動中對這些方法有了一個初步的體驗。
1、注重從用戶那里溝通了解其需求。
2、梳理用戶業(yè)務(wù)的流程、規(guī)則。
3、從需求、流程中找到用戶的核心問題域(演講中以京東的物流,淘寶的多商品種類為例進(jìn)行了大致比喻)
4、從核心問題域中識別子領(lǐng)域。子領(lǐng)域的識別實際上是對復(fù)雜問題的分治法。各個子領(lǐng)域之間會存在相連接的邊界,邊界兩側(cè)會出現(xiàn)各自子領(lǐng)域中同名業(yè)務(wù)對象的連接,這種連接我理解為各個子領(lǐng)域之間的業(yè)務(wù)轉(zhuǎn)換橋梁。例如,在一個電商系統(tǒng)例子中,如果存在訂單管理子領(lǐng)域和物流管理子領(lǐng)域,那么兩個領(lǐng)域中都會有訂單這個對象,這時業(yè)務(wù)上來說訂單是訂單子領(lǐng)域向物流子領(lǐng)域流轉(zhuǎn)的載體。我想這種跨領(lǐng)域存在的同名對象的關(guān)系和作用應(yīng)該不止我想的這一種,后續(xù)再慢慢學(xué)習(xí)體會。另外,也可以從子領(lǐng)域中識別出公共領(lǐng)域的情況,例如訂單和物流子領(lǐng)域中可能就會抽取出商品領(lǐng)域這個公共領(lǐng)域。我想這些子領(lǐng)域的識別,就是后續(xù)在技術(shù)實現(xiàn)層面上對模塊、服務(wù)的一種劃分參考。例如商品領(lǐng)域可以作為核心服務(wù),訂單領(lǐng)域和物流領(lǐng)域作為composite服務(wù)。
5、上面的過程反復(fù)迭代
至于有了業(yè)務(wù)模型之后,如何將它轉(zhuǎn)化到代碼上,又如何與系統(tǒng)架構(gòu)、技術(shù)架構(gòu)結(jié)合,目前還沒有太多體會,后續(xù)再深入了解下DDD看看它是如何來解決這個問題的。
通過這次活動,個人體會是如果將業(yè)務(wù)與代碼之間的關(guān)系做一個比喻的話,那么業(yè)務(wù)是因,代碼是果。在未來引起變化的主要原因是業(yè)務(wù),然后才是代碼隨之變化。那么我們建立解決問題的模型,一開始從代碼這個果來出發(fā)的話,就是本末倒置了,這種角度出發(fā)得到的技術(shù)模型也必然很難適應(yīng)真正引起其變化的原因 - 業(yè)務(wù)。也許反過來從業(yè)務(wù)這個原因出發(fā)對問題進(jìn)行建模,并且讓這個業(yè)務(wù)模型具有可擴展性,對變化是開放的,那么代碼這個對業(yè)務(wù)模型的實現(xiàn)者和表象也應(yīng)該可以具有相差不多的可擴展性吧。