DDD之領(lǐng)域事件與領(lǐng)域服務(wù)
領(lǐng)域服務(wù)
領(lǐng)域中的服務(wù)表示一個(gè)無(wú)狀態(tài)的操作,它用于實(shí)現(xiàn)特定于某個(gè)領(lǐng)域的任務(wù)。當(dāng)某個(gè)操作不適合放在聚合和值對(duì)象上時(shí),最好的方式便是使用領(lǐng)域服務(wù)。具體的使用場(chǎng)景可參考以下幾大特點(diǎn):
執(zhí)行一個(gè)顯著的業(yè)務(wù)操作過(guò)程(值對(duì)象就不具備業(yè)務(wù)操作行為)
對(duì)領(lǐng)域?qū)ο筮M(jìn)行轉(zhuǎn)換
以多個(gè)領(lǐng)域?qū)ο笞鳛檩斎脒M(jìn)行計(jì)算,結(jié)果產(chǎn)生一個(gè)值對(duì)象。(實(shí)體對(duì)象無(wú)論到什么時(shí)候都具備業(yè)務(wù)行為,而領(lǐng)域服務(wù)的產(chǎn)出結(jié)果是一個(gè)不具備業(yè)務(wù)行為的值對(duì)象)
領(lǐng)域事件業(yè)務(wù)邏輯的處理還是要盡量的放在實(shí)體對(duì)象和值對(duì)象中體現(xiàn),盡量不要過(guò)度的依賴領(lǐng)域服務(wù),過(guò)度地使用領(lǐng)域服務(wù)將導(dǎo)致貧血領(lǐng)域模型。
領(lǐng)域事件是在領(lǐng)域內(nèi)發(fā)生時(shí)需要有進(jìn)一步業(yè)務(wù)操作的事件,比如訂單支付完成后,需要發(fā)送一條結(jié)果通知信息就屬于一個(gè)領(lǐng)域事件。在進(jìn)行事件風(fēng)暴時(shí),當(dāng)我們聽(tīng)到“如果發(fā)生……,則……”“當(dāng)做完……的時(shí)候,請(qǐng)通知……”“發(fā)生……時(shí),則……”等這些關(guān)鍵詞時(shí),我們要意識(shí)到在這些場(chǎng)景中,如果發(fā)生某種事件后,會(huì)觸發(fā)進(jìn)一步的操作,那么這個(gè)事件很可能就是領(lǐng)域事件。
在分布式架構(gòu)下,領(lǐng)域事件有助于業(yè)務(wù)解耦和形成完整的業(yè)務(wù)閉環(huán)。領(lǐng)域事件發(fā)生在微服務(wù)之間的場(chǎng)景比較多,事件處理的機(jī)制也更加復(fù)雜??缥⒎?wù)的事件可以推動(dòng)業(yè)務(wù)流程或者數(shù)據(jù)在不同的子域或微服務(wù)間直接流轉(zhuǎn)??缥⒎?wù)的事件機(jī)制要總體考慮事件構(gòu)建、發(fā)布和訂閱、事件數(shù)據(jù)持久化、消息中間件,甚至事件數(shù)據(jù)持久化時(shí)還可能需要考慮引入分布式事務(wù)機(jī)制等。
1、這里其實(shí)可以將領(lǐng)域事件簡(jiǎn)單的理解成一個(gè)微服務(wù)的通信事件,按照流行技術(shù)架構(gòu)的設(shè)計(jì)應(yīng)該采用的是MQ,雖然也可以通過(guò)RPC實(shí)現(xiàn)事件通信,但是為了系統(tǒng)解耦、業(yè)務(wù)行為更具有獨(dú)立性,通常還是通過(guò)消息中間件的方式。雖然這樣理解領(lǐng)域事件過(guò)于狹隘,但是也比較直觀。
2、不建議在微服務(wù)的內(nèi)部聚合之間使用領(lǐng)域事件,這種場(chǎng)景的實(shí)現(xiàn)成本過(guò)高收益過(guò)小,通常這種場(chǎng)景都有其他更好的替換方式。
一個(gè)標(biāo)準(zhǔn)的領(lǐng)域事件處理包括:事件構(gòu)建和發(fā)布、事件數(shù)據(jù)持久化、事件總線、消息中間件、事件接收和處理等幾大環(huán)節(jié)。

(不建議在微服務(wù)內(nèi)部使用領(lǐng)域事件通信)
領(lǐng)域事件是 DDD 的一個(gè)重要概念,在設(shè)計(jì)時(shí)我們要重點(diǎn)關(guān)注領(lǐng)域事件,用領(lǐng)域事件來(lái)驅(qū)動(dòng)業(yè)務(wù)的流轉(zhuǎn),盡量采用基于事件的最終一致,降低微服務(wù)之間直接訪問(wèn)的壓力,實(shí)現(xiàn)微服務(wù)之間的解耦,維護(hù)領(lǐng)域模型的獨(dú)立性和數(shù)據(jù)一致性。
