〇、一些閱讀的前提注意
本文僅僅是個人的理解游两,會隨著個人理解的逐步加深而修改一些先前的錯誤理解砾层。這里非常推薦閱讀《實現(xiàn)領域驅(qū)動設計 (美)弗農(nóng)著》,《領域驅(qū)動設計》贱案,《大數(shù)據(jù)之路》以及阿里技術專家的DDD文檔肛炮,這些都對于理解DDD大有裨益。
其次宝踪,切莫隨波逐流侨糟,適合自己的未必是所謂的潮流。
一瘩燥、回歸業(yè)務:再談SOA和微服務
1秕重、再聊聊SOA
在常見的開發(fā)場景中,我們基于SOA理論所構建的服務是精確定義厉膀、封裝完善溶耘、獨立于其他服務所處環(huán)境和狀態(tài)的函數(shù)。
SOA 本質(zhì)上是服務的集合服鹅,服務之間彼此通信凳兵,這種通信可能是簡單的數(shù)據(jù)傳送,也可能是兩個或更多的服務協(xié)調(diào)進行某些活動企软。服務之間需要某些方法進行連接(Restful或者RPC協(xié)議等)庐扫。
每一個服務并不一定是一個完整的業(yè)務,一個完整的業(yè)務包含角色仗哨、參與對象以及動作等信息形庭。一個完整的業(yè)務鏈可能會涉及到多個服務,但是每一個業(yè)務團都能構建可復用的服務藻治。
SOA的構建思路碘勉,在于充分的解耦,其要求包括了:明確接口桩卵、閉包封裝验靡、模塊化構建倍宾、粗粒度、松耦合胜嗓、互操作性高职、兼容和策略聲明。
2辞州、再聊下微服務
微服務其實是SOA思想的延伸怔锌,旨在能將服務進行有效的編排,如活字印刷排版一樣構建整個項目变过,每一個服務猶如每一個字塊埃元,是與其他字塊獨立的。想要構建出整體項目媚狰,需要像排版印刷板上的文字一樣岛杀,合理的排列組合服務。
微服務的核心特點為:服務足夠小,且專注崭孤,服務間可以構建輕量級的通信機制类嗤,保持松耦合、獨立部署辨宠。
微服務的思路可以說非常高效遗锣,它一定程度的降低了服務的復雜性,同時維持了服務的水平擴展和彈性擴容嗤形,降低了從開發(fā)到部署到維護的難度精偿。每一個服務僅僅需要專注于自身的業(yè)務邏輯,對開發(fā)周期的可并行化提供了理論基礎派殷。
當然还最,當服務逐漸的細化時,會出現(xiàn)一個業(yè)務需要調(diào)用好幾個服務毡惜,這就是服務爆炸拓轻。因此如何劃分服務,有效的將業(yè)務拆解但是又不能分到像把一碗米飯分成一個個米粒兒一樣細致经伙,再次降低服務間調(diào)用的復雜度扶叉,就是需要設計者投入足夠的思考。
3帕膜、聊聊業(yè)務
將業(yè)務團構建成可服務的出發(fā)點在于復用枣氧,再理解下該場景下的業(yè)務:即流程的流轉(zhuǎn)。例如下單業(yè)務垮刹,整個流程為一個業(yè)務达吞,包含用戶角色,客戶端角色以及訂單荒典、訂單發(fā)送酪劫、訂單接受并通知吞鸭。
在常見的構建過程中,我們會構建角色表覆糟、構建訂單表刻剥,完成MVC層。常見的場景中構建的角色如下:
@Lombok
public User( ){
private String userId;
private String userName;
private String address;
private String tel;
...
}
在這種常見的構建中滩字,完成一個訂單服務造虏,要執(zhí)行Mapper,然后構建一個Impl完成業(yè)務邏輯麦箍。當然漓藕,User的作用僅僅存在于接受一個用戶的信息或者提供getter、setter内列。
這是常見的貧血模式撵术,當服務的對象或者需要調(diào)用的方法發(fā)生改變時背率,對舊代碼的重構量是極大的话瞧,導致很多原有正確的邏輯無法有效的復用∏拮耍或者說在基于現(xiàn)有的功能進行擴展時交排,如果稍有變動,就需要重新構建一個User2饵筑,用于接收變更后的信息埃篓。
很明顯,這樣的過程根资,并不是十分合理架专,盡管在當前的場景下,這種書寫方式玄帕,更符合大多數(shù)開發(fā)者的邏輯部脚。
二、為什么選用DDD
1裤纹、緒論
軟件發(fā)展至今委刘,微服務是大型穩(wěn)定系統(tǒng)的首選架構方式。在常見的環(huán)境中鹰椒,我們所謂之業(yè)務锡移,大體分為兩類:ToC、ToB漆际。而無論是哪類業(yè)務淆珊,都存在著轉(zhuǎn)向微服務架構方式的可能。
而在面向于撈錢的項目開發(fā)中奸汇,軟件在步入生產(chǎn)環(huán)境后施符,會面臨著種類繁多钞支、花樣齊全的產(chǎn)品迭代,包括但不限于:功能升級操刀、后端優(yōu)化烁挟、功能添加、功能整合等等骨坑。那么一旦某項需求涉及到了多項服務撼嗓,那么該如何進行維護就成為了公司發(fā)展的重中之重。因此有些問題我們不得不丑話說在前頭欢唾,我們這里涉及的產(chǎn)品且警,需要有一定體量。簡單的單機系統(tǒng)不必如此麻煩礁遣,在選用技術時斑芜,切忌“殺雞焉用牛刀”,以避免沒有必要的效率浪費祟霍,小型的項目用DDD實為一種損失精力的做法杏头,這個問題在之后的建模時我們會看得到。而此中的體量大致是:已經(jīng)步入微服務架構且至少有數(shù)個深度縱向的業(yè)務沸呐,有數(shù)個切面業(yè)務貫穿系統(tǒng)醇王,系統(tǒng)復雜度很高,業(yè)務迭代速度適中且在業(yè)務中存在著部分耦合崭添。例如傳統(tǒng)的電商系統(tǒng)寓娩、咨詢平臺。
微服務和DDD似乎有著天然的相性呼渣,Martin Fowler的《重構》一書中提及到:每次對原有系統(tǒng)進行修改調(diào)整的時候是一個非常好的重構契機棘伴,這也就是說,DDD可以在微服務實施后屁置,逐步的在迭代中焊夸,通過一次次重構逐步實現(xiàn),不必大費周折的在初期就確立DDD影響基礎功能的開發(fā)速度缰犁,但是這里也要提一句的是淳地,如果能有效的預測出軟件復雜度很高,如果一開始就有能力選取DDD時選用DDD是十分明智的帅容。
作為微服務的提出人颇象,似乎對服務到底分多大沒有給出過于明確的建議。因此我們在DDD中的界限上下文并徘,更適合用于劃分微服務遣钳。在一般的分攤思維中,我們常常會陷入一種誤區(qū):一個業(yè)務即一個服務麦乞,但這是一種以偏概全的想法蕴茴。實際上的服務劃分劝评,要考慮諸多問題:如何部署,怎么進行具體實施倦淀,數(shù)據(jù)來源是否封裝蒋畜,在當前云原生的環(huán)境下,如何切合云原生的思想等等問題撞叽,因此用業(yè)務劃分屬實讓人覺得“吃相難看”姻成。
而根據(jù)實際場景中的問題愿棋,利用界限上下文的思想規(guī)劃出的微服務,能有效的解決至少兩個問題:服務到底多大糠雨,服務間如何解耦才睹。在單個服務的內(nèi)部甘邀,利用DDD也能有效的構建出極為優(yōu)質(zhì)的代碼,便于實施各種迭代和融合鹃答。至此,我們其實以及意識到了测摔,DDD是一種貫穿產(chǎn)品到開發(fā)的思想解恰,并非單獨面相開發(fā)的架構思想。在完成DDD時护盈,需要一定的管理能力和人員能力挟纱,這些都是實打?qū)嵉膶嵤┗A腐宋,切不可為了DDD而DDD的冒進紊服。
在本套文集中,我們主要面相的開發(fā)人員的一些技術和思想胸竞,因此如何操作DDD這個問題在本文中會更加的偏向開發(fā)實施過程中的“注意事項”欺嗤,因此我們不會涉及過多產(chǎn)品如何應用DDD去構建出業(yè)務域。
2卫枝、開發(fā)如何理解DDD
個人認為煎饼,DDD在開發(fā)中所應用的概念,如同利用各類細胞組成生物個體并生成個體間交互場景的過程校赤。這個理解似乎聽起來很麻煩吆玖,但是我的理解是:DDD就是森林狀的開發(fā)系統(tǒng)筒溃,每一個基礎實體都可以看做森林的葉子。
我們以“斧子砍樹”來舉例沾乘,在該場景中怜奖,設計到兩個交互實體:斧頭、樹翅阵。我們暫且吃相難看的用簡單的方式劃分這個場景烦周,那么就是分別構建出斧子、樹這兩個實體怎顾,然后進行實體間進行“友好交流”读慎。那么為了實施DDD,我該如何構建出這兩個實體呢槐雾?
對于一棵樹而言:從各類細胞開始夭委,逐漸會聚合成各種組織,然后聚合成樹募强。那么大致的結構圖應該如下
對于該圖像株灸,可以產(chǎn)出對于樹(一個服務)而言,我們沒有粗暴的通過根擎值、莖慌烧、葉、花的業(yè)務方式進行劃分鸠儿,而是通過不同特性的組織進行劃分屹蚊,而對應于實際的開發(fā)就是,數(shù)據(jù)服務进每、各類交互服務汹粤、認證服務等等。而對應的根部表皮也好田晚,原生分生組織也好嘱兼,都可以是作為一個個領域的聚合根(概念會在后續(xù)提及)。在各個領域的劃分后贤徒,我們可以將領域進行聚合芹壕,由此生成有效的界限上下文,也同時規(guī)定了:樹到底需要用那部分跟斧子進行“友好交流”接奈。
而對于斧子而言踢涌,是構建出兩個零件:手柄和斧頭。其結構圖如下
同樣的鲫趁,這里規(guī)定了用斧頭部跟樹進行交互斯嚎。
為了方便理解,我們需要構建一下樹內(nèi)部的界限上下文,如圖:
這里糠惫,我們額外畫出了三角形硼讽,即軀干,該處為樹的領域和斧頭的領域的交互地點固阁,而在實際開發(fā)中城菊,即對應防腐層。在實際的實施中并齐,為了防止軟件耦合帶來的服務間相互入侵的情況客税,我們必須構建出一定的防腐層來有效的減緩代碼腐敗的速度,留有足夠的時間方便代碼在不斷的重構中一次次新生测垛。因此軀干這個防腐層秧均,有效的保護了斧頭與樹交互時,對樹的過度侵害疙描,這一點在實施DDD開發(fā)時需要十分重視。
至此我們簡單的敘述了一下DDD以及DDD在開發(fā)實施中的一些簡單概念,當然久又,到此依舊會云里霧里,所以我們需要帶著一些疑惑與簡單理解再次從頭深入DDD炉峰。