摘要:的演進(jìn)按照上述的說明,在一個(gè)單體服務(wù)中,隨著業(yè)務(wù)的不斷迭代,可能會(huì)發(fā)生什么嚴(yán)重的問題。個(gè)人認(rèn)為造成這個(gè)原因的主要原因還是在于長期以來的這種模式只有縱向切分導(dǎo)致。
摘要mvc是一種軟件設(shè)計(jì)模式,最早由Trygve Reenskaug在1978年提出,他有效的解決了表示層,控制器層,邏輯層的代碼混合在一起的問題,很好的做到了職責(zé)分離。但是在實(shí)際的編碼實(shí)踐過程中,你會(huì)發(fā)現(xiàn)這個(gè)模式隨著業(yè)務(wù)的擴(kuò)展,變的邏輯混亂,代碼重合度很高。這里提出借鑒DDD思想的一種新的工程結(jié)構(gòu)
mvc的問題通常一個(gè)前后端分離的系統(tǒng),后端工程系統(tǒng)結(jié)構(gòu)圖通常下面這樣
1. 四層 controller/service/manager/mapper 2. 不可以同級(jí)調(diào)用 3. 上級(jí)可以知曉下級(jí),下級(jí)不可知曉上級(jí),也就是bean的轉(zhuǎn)化放在上級(jí)
這個(gè)分層結(jié)構(gòu)職責(zé)分離是按照縱向切分的
1. 資源服務(wù)層repository是面向DB編程 2. service層是面向前端頁面編程。
也就是說,對(duì)于某一塊的業(yè)務(wù),他沒有將邏輯抽象到一起,他只是將一次request按照縱向切分了。沒有進(jìn)行橫向的業(yè)務(wù)切分。 這樣將會(huì)導(dǎo)致的問題 職責(zé)分散,邏輯重復(fù)度高
bean的創(chuàng)建太隨意,基本就是一個(gè)需求對(duì)應(yīng)一些dto, vo,query bean
不同開發(fā)者對(duì)于同一個(gè)領(lǐng)域的東西有不同的bean,同一個(gè)開發(fā)者對(duì)于相同邏輯的bean,過了幾個(gè)月,又定義出一個(gè)差不多的bean
沒有邊界
根本沒有上下文/邊界的概念,比如說店鋪會(huì)和用戶有交互,訂單會(huì)和用戶有交互,通常在DB存儲(chǔ)時(shí)只會(huì)存關(guān)聯(lián)id,然后需要去取對(duì)應(yīng)的名稱,其他屬性信息。這些信息的獲取,有些開發(fā)在manager層操作,然后將屬性定義到了店鋪相關(guān)的DTO中;有些放在了service層做。controller/service/manager各個(gè)層次都可以調(diào)用,沒有任何約束。
mvc的演進(jìn)按照上述的說明,在一個(gè)單體服務(wù)中,隨著業(yè)務(wù)的不斷迭代,可能會(huì)發(fā)生什么嚴(yán)重的問題。
舉幾個(gè)真實(shí)鮮活的例子
分庫分表的例子 實(shí)體A是我們業(yè)務(wù)中的一個(gè)基礎(chǔ)的重要的實(shí)體,對(duì)應(yīng)的數(shù)據(jù)表tableA,一開始業(yè)務(wù)很簡單,只有1個(gè)服務(wù),在這個(gè)服務(wù)里面調(diào)用。后來業(yè)務(wù)擴(kuò)張了,有十幾個(gè)服務(wù)了,然后十幾個(gè)服務(wù)直接查這個(gè)tableA。tableA也擴(kuò)張成為了tableA,tableB,tableC。有些人覺得代碼重復(fù)度高了,將mapper/manager層拆成共通的部分打成一個(gè)jar包,然后各個(gè)微服務(wù)中引入這個(gè)jar。業(yè)務(wù)變得更加復(fù)雜了,服務(wù)擴(kuò)展到幾十個(gè)了,tableA數(shù)據(jù)也有幾千萬了,這時(shí)候要做分庫分表了,怎么整。
最后花了差不多1年,涉及十幾個(gè)團(tuán)隊(duì),才把這個(gè)mapper/manager調(diào)用改掉,然后做分庫分表。
有人可能覺得這個(gè)只要在服務(wù)拆分時(shí),避免直接調(diào)用就可以了,那再舉個(gè)其他類型的例子。
用戶等級(jí)的例子
用戶的等級(jí),用戶的分級(jí)是很復(fù)雜的,不同的業(yè)務(wù)階段有這個(gè)不同的定義。比如一開始定義一個(gè)字段叫g(shù)rade的代表用戶等級(jí)。 然后各個(gè)業(yè)務(wù)都在查這個(gè)表的字段grade進(jìn)行判斷,然后產(chǎn)品需要改了,增加了判斷必須同時(shí)要達(dá)到什么條件才能稱作等級(jí)x。這時(shí)候你又得滿世界的改了。
DDD的工程架構(gòu)那如何運(yùn)用DDD的思想進(jìn)行改造呢 核心思想:封裝領(lǐng)域內(nèi)的邏輯,統(tǒng)一對(duì)外暴露的入口,防止業(yè)務(wù)邏輯泄露。
在mvc縱向切分的基礎(chǔ)上,增加一層領(lǐng)域的橫向切分
同一個(gè)工程里面,領(lǐng)域之間的調(diào)用只能通過domainService,這樣可以屏蔽領(lǐng)域內(nèi)的數(shù)據(jù)庫是如何持久化的,業(yè)務(wù)邏輯是如何判斷的、算法是如何實(shí)現(xiàn)的。 service之間可以直接調(diào)用。
領(lǐng)域內(nèi)還是縱向切分,安裝mvc分層結(jié)構(gòu)。
上面的只是一個(gè)草圖,我們真實(shí)的結(jié)構(gòu)圖比這要稍微復(fù)雜些。領(lǐng)域內(nèi)會(huì)區(qū)分領(lǐng)域?qū)ο螅I(lǐng)域服務(wù),基礎(chǔ)設(shè)施層。這樣在領(lǐng)域內(nèi)進(jìn)行指責(zé)分離,不過從實(shí)際的執(zhí)行過程中領(lǐng)域內(nèi)的比較細(xì)節(jié),執(zhí)行起來ROI比較低,推薦大家可以先按這套執(zhí)行。
畫外音:估計(jì)有些程序員看到這個(gè)工程結(jié)構(gòu)變化呵呵一笑,覺得沒多大價(jià)值,沒什么改變必要。
這種工程的結(jié)構(gòu)劃分從提出來的到真正被我們團(tuán)隊(duì)成員接受的時(shí)間周期差不多是8個(gè)月。 原因大概是這么幾類
引入新的分層,太復(fù)雜了,增加了代碼復(fù)雜度
我這塊業(yè)務(wù)很簡單,CRUD就行了,沒涉及到服務(wù)之間的交互。直接mvc一條道走到黑就可以。
如果你看這篇文章也是這種感受,不妨花點(diǎn)時(shí)間看下你們業(yè)務(wù)的代碼,看看重復(fù)度有多高,看看邏輯有多散亂。你就會(huì)明白。
DDD工程的演進(jìn)DDD工程的演進(jìn)也就是服務(wù)的拆分了,放到下期講。
總結(jié)很多DDD的文章都在說傳統(tǒng)的編程方式是面試數(shù)據(jù)庫編程,導(dǎo)致對(duì)象中只有g(shù)etter,setter,也就是貧血模型,貧血模型是沒有業(yè)務(wù)邏輯,面向過程設(shè)計(jì),不符合面向?qū)ο笤O(shè)計(jì)原則。
對(duì)于這個(gè)結(jié)論我是同意的,但是對(duì)于造成的原因不是很同意。個(gè)人認(rèn)為造成這個(gè)原因的主要原因還是在于長期以來的MVC這種模式只有縱向切分導(dǎo)致。如果結(jié)合橫向切分,有沒有DDD也無所謂。這里再引用一下驅(qū)動(dòng)方法不能改變?nèi)魏问虑檫@段話,如果你能深入理解職責(zé)、封裝。并隨著業(yè)務(wù)的迭代,不斷的重構(gòu)你的代碼,那么你不需要什么DDD,或者其他方法論。
使用職責(zé)、封裝和組合; 以接口的視角思考,即“人們?nèi)绾问褂梦业慕M件?”; 使用相關(guān)技術(shù)寫好代碼,包括可讀性、信息性、簡潔、自描述,盡量避免顯式地使用模式; 有能力回答特定業(yè)務(wù)的“本質(zhì)”;“本質(zhì)”是一個(gè)模型,但不意味著類和方法,它意味著回答問題“這個(gè)業(yè)務(wù)如何真正地工作?”
因?yàn)檫@些約束,都是強(qiáng)迫你去思考,去做職責(zé)的思考,去做模塊的封裝。如果你/你團(tuán)隊(duì)成員已經(jīng)領(lǐng)會(huì)其中的道理并很好的運(yùn)用,還需要這些條條框框干嗎呢?
下一篇領(lǐng)域與微服務(wù)劃分,欲知后事如何,請(qǐng)聽下回分解。
相關(guān)閱讀
可落地的DDD(1)-目標(biāo)討論
關(guān)注【方丈的寺院】,第一時(shí)間收到文章的更新,與方丈一起開始技術(shù)修行之路
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/6882.html
摘要:中的事件的一個(gè),我暫且理解為一個(gè)中的和這兩個(gè)屬性已經(jīng)在框架中直接掛載在了對(duì)象上,歸功于曾老師。 CQRS是啥?DDD又是啥? 這兩個(gè)概念其實(shí)沒什么神秘的,當(dāng)然此文章中的這兩個(gè)概念以曾老師的課程為準(zhǔn)(關(guān)于CQRS和DDD的標(biāo)準(zhǔn)概念,google上已經(jīng)很多了,不再贅述。) DDD(Domain Driven Design),領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)開發(fā)。 DDD和OOP有什么同嗎?其實(shí)就我個(gè)人經(jīng)驗(yàn)來說...
摘要:最近發(fā)現(xiàn)文章老是被竊取,有些平臺(tái)舉報(bào)了還沒有用。最后不了了之,產(chǎn)品很配合,但是內(nèi)驅(qū)力不強(qiáng)。為什么內(nèi)驅(qū)力不強(qiáng),因?yàn)榻o他帶來的收益不夠。所以在千個(gè)團(tuán)隊(duì)中實(shí)行可能有千套不同的方案。最近發(fā)現(xiàn)文章老是被竊取,有些平臺(tái)舉報(bào)了還沒有用。請(qǐng)識(shí)別我的id方丈的寺院。 摘要 DDD領(lǐng)域驅(qū)動(dòng)設(shè)計(jì),起源于2004年著名建模專家Eric Evans發(fā)表的他最具影響力的著名書籍:Domain-Driven Design...
摘要:作者小傅哥博客沉淀分享成長,讓自己和他人都能有所收獲接下來還需要把我們創(chuàng)建的工程模板以及數(shù)據(jù)服務(wù)配置到中,這樣在插件啟動(dòng)的時(shí)候就可以把我們自己插件啟動(dòng)起來了。作者:小傅哥博客:https://bugstack.cn沉淀、分享、成長,讓自己和他人都能有所收獲!???? 接下來還需要把我們創(chuàng)建的工程模板以及數(shù)據(jù)服務(wù)配置到 plugin.xml 中,這樣在插件啟動(dòng)的時(shí)候就可以...
摘要:問題來了,我們到底還在用嗎答案是,不全用。后者是初始化的配置,主要是的配置。啟動(dòng)類測(cè)試啟動(dòng)項(xiàng)目后,在瀏覽器里面輸入。通過查詢已裝載的,并且支持該而獲取的。按照前面對(duì)的描述,對(duì)于而言,這個(gè)必定是。的核心在的方法中。 之前已經(jīng)分析過了Spring的IOC(《零基礎(chǔ)帶你看Spring源碼——IOC控制反轉(zhuǎn)》)與AOP(《從源碼入手,一文帶你讀懂Spring AOP面向切面編程》)的源碼,本次...
摘要:而程序員和醫(yī)生律師的不同點(diǎn)在于持續(xù)學(xué)習(xí)上。兩個(gè)小問題是需要收費(fèi),一年大概刀圖書都是英文的。的視頻基本都有英文字幕,配合作者的,英語不好的同學(xué)學(xué)習(xí)也沒有問題。英文好的有技術(shù)功底的同學(xué)多發(fā)表一些觀點(diǎn),其他的同學(xué)都 摘要: 行業(yè)發(fā)展得太快,你必須學(xué)習(xí),純靠經(jīng)驗(yàn)積累行不通,技術(shù)淘汰的速度遠(yuǎn)大于你經(jīng)驗(yàn)積累的速度。 非雞湯:不要和程序員談自己的編程歷史,很多的經(jīng)驗(yàn)在今天已經(jīng)不適用了。只要2-3年...
閱讀 2437·2021-10-09 09:59
閱讀 2191·2021-09-23 11:30
閱讀 2599·2019-08-30 15:56
閱讀 1155·2019-08-30 14:00
閱讀 2947·2019-08-29 12:37
閱讀 1265·2019-08-28 18:16
閱讀 1668·2019-08-27 10:56
閱讀 1033·2019-08-26 17:23