前端如何主導(dǎo)ddd架構(gòu)落地(下)
前文--前端如何主導(dǎo)ddd架構(gòu)落地(上) 提到ddd架構(gòu)已經(jīng)需要前端來救場了,此情此景,已經(jīng)不知道尷尬的應(yīng)該是后端、技術(shù)經(jīng)理還是前端了,反正程序員一定是很尷尬。標(biāo)題就是為了吸引眼球的,純前端如果不是特別閑,是無論如何也不會干這事的(微前端ddd架構(gòu)另說)。不管是誰,如果不去搞明白什么是ddd,哪怕是后端來了,給你三個月時間怕也搞不定。時間不多了,離季度考核目標(biāo)(還好是跨季度。。)越來越近,如果我這個“技術(shù)經(jīng)理”帶著他們還不能搞定,那責(zé)任最大的就是我了,不管你會不會java!
咱還是有策略的
在小公司,一般都是業(yè)務(wù)驅(qū)動的,我基本很少聽說過哪個小公司發(fā)明了一個架構(gòu),搞出一個框架然后在業(yè)內(nèi)進行了廣泛推廣。在IT行業(yè)利潤越來越少的時代,那些鼓吹自己是技術(shù)驅(qū)動的小公司都挺不自量力的,咱還是老老實實地搞業(yè)務(wù)吧。不管是誰,從老板到基層程序員,每一個人都要明白,把業(yè)務(wù)搞明白比什么都重要,這是生存法則。就拿這個事來說,ddd這個東西,20年前就有了,在中國是近幾年才火起來。你要真較真,國外的IT公司才真的叫技術(shù)驅(qū)動,互聯(lián)網(wǎng)就是國外發(fā)明的,阿里騰訊都還在跟隨學(xué)習(xí)然后在這基礎(chǔ)上再創(chuàng)新,你小公司敢說自己是技術(shù)驅(qū)動?所以ddd的落地肯定是要結(jié)合業(yè)務(wù),由業(yè)務(wù)來推動和驅(qū)動落地,而不是專心學(xué)習(xí)ddd的每一個演變細節(jié)后再去動手,那樣就是本末倒置了,人家早就是成熟的東西,你拿來主義照做就行,把精力花在架構(gòu)的細節(jié)是得不償失的。這就是為什么,兩后端搞一直沒找對方向的原因,我不會java卻能指導(dǎo)他們進行ddd落地,因為我抓住了關(guān)鍵,這個關(guān)鍵點是業(yè)務(wù),而非技術(shù)。只有抓住了業(yè)務(wù)這個關(guān)鍵點,技術(shù)的落地才能擲地有聲。
目前的后端就是一套單體服務(wù),中間的勾連我也沒精力去分析拆解,后端已經(jīng)在上面試了3個月了,已經(jīng)證明修改是無效的,那只有一條路--推翻重建!我的想法就很簡單,就直奔主題,首先明確需求,業(yè)務(wù)線的各個微服務(wù)需要獨立,屬于業(yè)務(wù)線又不僅僅只屬于業(yè)務(wù)線,其他的業(yè)務(wù)線如果有需要也可以用到我們的微服務(wù),這就是公司產(chǎn)品上云的意義。明確需求后再拿著需求去找ddd能幫到我什么,你就會發(fā)現(xiàn)這需求跟ddd真的是很般配。這時候再去確認ddd要成什么樣,我就有了一個很明確的目標(biāo),我找資料直接就看標(biāo)題切入而不是從頭開始看。有了必要的知識儲備后,我就有底氣來重構(gòu)了,而推倒目前的框架,前提是要重新進行設(shè)計,這個設(shè)計就得是按照ddd的設(shè)計思想來;設(shè)計好之后,再交由后端執(zhí)行開發(fā);當(dāng)然,這個過程最好是有開發(fā)計劃來護航,畢竟無計劃狀態(tài)的結(jié)果已經(jīng)失敗地太明顯了。
模型設(shè)計
ddd有一個代碼模型,它有四層架構(gòu)(基礎(chǔ)層、領(lǐng)域?qū)印?yīng)用層及用戶接口層),基礎(chǔ)層通過sql語句查表數(shù)據(jù),領(lǐng)域?qū)诱{(diào)用基礎(chǔ)層形成最基礎(chǔ)服務(wù)。領(lǐng)域?qū)訒O(shè)計多個微服務(wù),微服務(wù)之間不能相互調(diào)用,這里的微服務(wù)有一個概念叫聚合,你可以理解為一個小的領(lǐng)域。相比于ddd架構(gòu),普通的單體服務(wù),一般是沒有領(lǐng)域這塊的說法,直接在應(yīng)用層一個復(fù)雜sql搞定接口的全部邏輯,然后對外暴露一個接口出去就行了,基本普遍就是這個搞法。
基于以上對于ddd的理解,我首先想到的就是優(yōu)先設(shè)計這個業(yè)務(wù)線的領(lǐng)域模型。我其實就是畫了一個思維導(dǎo)圖,基于對此業(yè)務(wù)線的業(yè)務(wù)脈絡(luò)梳理,先簡單畫了一個系統(tǒng)的業(yè)務(wù)模塊分類,然后,交給后臺落實確認。因為后臺在返回一個接口的時候,肯定會有我不是很清楚的業(yè)務(wù)交叉細節(jié)。這樣幾個來回下來,我發(fā)現(xiàn)我粗略畫的領(lǐng)域模型,甚至還是過于細節(jié)了。結(jié)果,領(lǐng)域模型進一步被精簡了,直到各領(lǐng)域之間看起來已經(jīng)不再有任何的糾纏。整個過程可以用這張圖來表示:

為了便于理解與執(zhí)行,我讓后端在每個領(lǐng)域的后面加上相關(guān)的數(shù)據(jù)庫表名,這樣一來領(lǐng)域?qū)右呀?jīng)跟基礎(chǔ)層的直接關(guān)聯(lián)關(guān)系就已經(jīng)鎖定了。這一步非常重要,ddd架構(gòu)的設(shè)計一定要非常細節(jié),表本身的主外鍵關(guān)系一般就是微服務(wù)的邊界。因為我是先有項目,然后再做架構(gòu),所以我們是可以在有了領(lǐng)域?qū)雍螅瑥幕A(chǔ)層往上推上去,如果一開始沒有項目,我覺得需要從業(yè)務(wù)開始梳理,從上往下設(shè)計到領(lǐng)域?qū)幼詈笤龠M行表設(shè)計。不管是哪一種,其實最開始都應(yīng)該優(yōu)先完成領(lǐng)域?qū)拥脑O(shè)計。
接下來,基礎(chǔ)層就相對簡單點了,所有的sql最多就關(guān)聯(lián)2到3張表,大部分就是對一個表的增刪改查。基礎(chǔ)層還可以放一些其他的支撐組件及工具之類的,總之,全力支撐領(lǐng)域?qū)拥母鱾€微服務(wù)領(lǐng)域功能實現(xiàn)。基礎(chǔ)層不僅僅支撐領(lǐng)域?qū)樱瑫r也會支撐著應(yīng)用層、用戶接口層。
然后是應(yīng)用層,這又是一個非常重要的部分。由于領(lǐng)域?qū)右呀?jīng)通過業(yè)務(wù)層面被降維打平了,領(lǐng)域?qū)訉ν獗┞兜模皇亲罨A(chǔ)的接口。比如這里面包含了一個用戶領(lǐng)域的微服務(wù),如果我要查用戶的權(quán)限信息,不好意思,現(xiàn)在只有用戶基礎(chǔ)信息的接口,還要通過用戶找到他的角色,再通過角色找到權(quán)限,這只有三個獨立的接口,你需要在組合這三個接口再對外暴露出去,這就是應(yīng)用層要做的事情。不過像這個例子比較有代表性,一般情況下,如果領(lǐng)域足夠典型,像用戶權(quán)限這個接口,也是可以在領(lǐng)域?qū)觾?nèi)封裝好,然后應(yīng)用層就直接調(diào)用了。不然的話,應(yīng)用層會變得非常的重,領(lǐng)域?qū)右惨驗檫^于簡單而失去了應(yīng)用到其他項目上的價值。
最后,為了不影響前端開發(fā),原來的單體服務(wù)維持不變,從頭新搭一個ddd架構(gòu)服務(wù);另外一點就是應(yīng)用層最終需要與原來的單體服務(wù)相呼應(yīng),保證前端原先調(diào)用的接口不變,這樣就不會增加前端的額外工作。
堅決地執(zhí)行
領(lǐng)域?qū)印?yīng)用層和基礎(chǔ)層這些設(shè)計好了之后,后端已經(jīng)心里有數(shù)了,他們兩個一開始不信任的眼神已經(jīng)開始有光了,我覺得有必要趁熱打鐵,再提升點技術(shù)經(jīng)理的權(quán)威性
。我圍繞領(lǐng)域?qū)樱灶I(lǐng)域中每張表為最小粒度,一天6張表,以這個標(biāo)準(zhǔn)來列計劃,我用甘特圖花了整整一天才排好。中間執(zhí)行的過程就不再贅述了,畢竟文章主要還是講技術(shù)落地的,故事已經(jīng)足夠完整了。
完美的結(jié)果
最終,我?guī)е鴥蓚€后端每天加班加點,花了近一個月時間,趕在最后時刻把后端的ddd重構(gòu)完成了,最終的代碼檢查也順利通過。
是誰的問題,已經(jīng)不重要
事實證明,ddd架構(gòu)的落地,一定是需要從業(yè)務(wù)層面對領(lǐng)域?qū)舆M行細粒度設(shè)計,才能保證設(shè)計出來的微服務(wù)足夠低耦合高內(nèi)聚。結(jié)果最重要,過程同樣重要,做為一個菜鳥技術(shù)經(jīng)理,是誰的問題已經(jīng)不重要,重要是前端也能主導(dǎo)ddd架構(gòu)落地!不是嗎!?

- 參考資料:極客時間《DDD實戰(zhàn)課》
掃碼關(guān)注 字節(jié)逆旅 公眾號,為您提供更多技術(shù)干貨!
