中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

app網(wǎng)站如何做推廣在百度怎么發(fā)布作品

app網(wǎng)站如何做推廣,在百度怎么發(fā)布作品,關(guān)于服裝的商務(wù)網(wǎng)站建設(shè)策劃書(shū),做網(wǎng)站的公司有哪些崗位Eric Evans 為運(yùn)用領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的系統(tǒng)架構(gòu)劃定了層次,在領(lǐng)域?qū)雍驼宫F(xiàn)層之間引入了應(yīng)用層(Application Layer):“應(yīng)用層要盡量簡(jiǎn)單,不包含業(yè)務(wù)規(guī)則或者知識(shí),而只為下一層(指領(lǐng)域?qū)?amp;#xff09;中…

Eric Evans 為運(yùn)用領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的系統(tǒng)架構(gòu)劃定了層次,在領(lǐng)域?qū)雍驼宫F(xiàn)層之間引入了應(yīng)用層(Application Layer):“應(yīng)用層要盡量簡(jiǎn)單,不包含業(yè)務(wù)規(guī)則或者知識(shí),而只為下一層(指領(lǐng)域?qū)?#xff09;中的領(lǐng)域?qū)ο髤f(xié)調(diào)任務(wù),分配工作,使它們互相協(xié)作?!蔽以谥v解領(lǐng)域驅(qū)動(dòng)架構(gòu)的演進(jìn)時(shí),則認(rèn)為領(lǐng)域?qū)犹峁┝思?xì)粒度的領(lǐng)域模型對(duì)象,不利于它的客戶端調(diào)用。因此,“基于 KISS(Keep It Simple and Stupid)原則或最小知識(shí)原則,我們希望調(diào)用者了解的知識(shí)越少越好,調(diào)用變得越簡(jiǎn)單越好,這就需要引入一個(gè)間接的層來(lái)封裝。這就是應(yīng)用層存在的主要意義?!?/p>

應(yīng)用服務(wù)的本質(zhì)

應(yīng)用服務(wù)是外觀模式(Facade Pattern)的體現(xiàn)。經(jīng)典著作《設(shè)計(jì)模式》定義了外觀模式的意圖:“為子系統(tǒng)中的一組接口提供一個(gè)一致的界面,外觀模式定義了一個(gè)高層接口,這個(gè)接口使得這一子系統(tǒng)更加容易使用。”這恰與引入應(yīng)用服務(wù)的作用不謀而合。使用外觀模式的場(chǎng)景主要包括:

  • 當(dāng)你要為一個(gè)復(fù)雜子系統(tǒng)提供一個(gè)簡(jiǎn)單接口時(shí)
  • 客戶程序與抽象類的實(shí)現(xiàn)部分之間存在著很大的依賴性
  • 當(dāng)你需要構(gòu)建一個(gè)層次結(jié)構(gòu)的子系統(tǒng)時(shí),使用外觀模式定義子系統(tǒng)中每層的入口點(diǎn)

這三個(gè)場(chǎng)景恰好說(shuō)明了應(yīng)用服務(wù)的本質(zhì)。對(duì)外,應(yīng)用服務(wù)為外部調(diào)用者提供了一個(gè)簡(jiǎn)單統(tǒng)一的接口,該接口為一個(gè)完整的用例場(chǎng)景提供了自給自足的功能,使得調(diào)用者無(wú)需求助于別的接口就能滿足業(yè)務(wù)需求。對(duì)內(nèi),應(yīng)用服務(wù)自身并不包含任何領(lǐng)域邏輯,僅負(fù)責(zé)協(xié)調(diào)領(lǐng)域模型對(duì)象,通過(guò)它們的領(lǐng)域能力來(lái)組合完成一個(gè)完整的應(yīng)用目標(biāo)。應(yīng)用服務(wù)作為應(yīng)用外觀,僅僅是領(lǐng)域?qū)拥囊粋€(gè)入口點(diǎn),通過(guò)它可以降低客戶程序與領(lǐng)域?qū)訉?shí)現(xiàn)之間的依賴。作為領(lǐng)域模型對(duì)象的包裝,它自身不應(yīng)該包含任何領(lǐng)域邏輯。由此可得到應(yīng)用服務(wù)設(shè)計(jì)的第一條準(zhǔn)則:不包含領(lǐng)域邏輯的業(yè)務(wù)服務(wù)應(yīng)被定義為應(yīng)用服務(wù)。

如果參考 Robert Martin 提出的整潔架構(gòu)思想,領(lǐng)域驅(qū)動(dòng)分層架構(gòu)的應(yīng)用層可對(duì)應(yīng)整潔架構(gòu)內(nèi)核中的用例(Use Case)層。不過(guò),領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)強(qiáng)調(diào)應(yīng)用服務(wù)雖然對(duì)外表現(xiàn)了應(yīng)用業(yè)務(wù)邏輯(Application Business Rule),但達(dá)成應(yīng)用目標(biāo)的實(shí)現(xiàn)邏輯需要分配給領(lǐng)域?qū)拥念I(lǐng)域模型對(duì)象。

無(wú)論六邊形架構(gòu)還是整潔架構(gòu),都認(rèn)為是網(wǎng)關(guān)(即六邊形架構(gòu)中的適配器)打通了內(nèi)部領(lǐng)域核心與外部資源和框架的通道。網(wǎng)關(guān)封裝了外部資源訪問(wèn)與框架依賴的實(shí)現(xiàn)邏輯,屬于外部的基礎(chǔ)設(shè)施層。北向網(wǎng)關(guān)屬于外部依賴內(nèi)部,南向網(wǎng)關(guān)則相反,屬于內(nèi)部依賴外部。因此,要讓南向網(wǎng)關(guān)滿足整潔架構(gòu)思想,避免內(nèi)部的領(lǐng)域邏輯依賴于外部的基礎(chǔ)設(shè)施,就需要為南向網(wǎng)關(guān)引入抽象和依賴注入。

在領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)中,屬于南向網(wǎng)關(guān)的資源庫(kù),其抽象常被視為領(lǐng)域?qū)拥囊徊糠?#xff1b;不止于此,整個(gè)“南向網(wǎng)關(guān)”的抽象其實(shí)亦可視為組成領(lǐng)域?qū)拥囊徊糠?#xff0c;例如訪問(wèn)第三方服務(wù)的 HttpClient,發(fā)送通知的抽象服務(wù)接口??紤]到分層與模塊之間的關(guān)系,我在《領(lǐng)域驅(qū)動(dòng)戰(zhàn)略設(shè)計(jì)》中,給出了與領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)思想對(duì)應(yīng)的代碼模型。在這個(gè)代碼模型中,我將網(wǎng)關(guān)分為了 interfaces 與 gateways 兩個(gè)包,前者僅定義了網(wǎng)關(guān)的抽象,后者則提供對(duì)應(yīng)的實(shí)現(xiàn)。對(duì)應(yīng)到分層架構(gòu),網(wǎng)關(guān)的抽象歸屬于領(lǐng)域?qū)?#xff0c;網(wǎng)關(guān)的實(shí)現(xiàn)歸屬于基礎(chǔ)設(shè)施層。

在考慮業(yè)務(wù)邏輯與具體技術(shù)實(shí)現(xiàn)之間的協(xié)作時(shí),可以將南向網(wǎng)關(guān)的抽象既注入到領(lǐng)域服務(wù)或應(yīng)用服務(wù)。領(lǐng)域服務(wù)與南向網(wǎng)關(guān)抽象之間的協(xié)作關(guān)系屬于同層之間的依賴,應(yīng)用服務(wù)與南向網(wǎng)關(guān)抽象之間的協(xié)作屬于外層調(diào)用內(nèi)層,二者都沒(méi)有違背整潔架構(gòu)思想。這意味著,領(lǐng)域邏輯與技術(shù)實(shí)現(xiàn)的隔離和結(jié)合既可以在領(lǐng)域?qū)油瓿?#xff0c;也可以在應(yīng)用層完成;那么,應(yīng)用服務(wù)除了能對(duì)細(xì)粒度的領(lǐng)域邏輯進(jìn)行包裝之外,它還能提供其余什么價(jià)值呢?

一個(gè)完整的業(yè)務(wù)用例場(chǎng)景,多數(shù)時(shí)候不僅限于領(lǐng)域邏輯,也不僅限于訪問(wèn)數(shù)據(jù)庫(kù)或者其他第三方服務(wù),往往還需要和如下邏輯進(jìn)行協(xié)作:

  • 消息驗(yàn)證
  • 錯(cuò)誤處理
  • 監(jiān)控
  • 事務(wù)
  • 認(rèn)證與授權(quán)
  • ……

《領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)模式、原理與實(shí)踐》一書(shū)將以上內(nèi)容視為基礎(chǔ)架構(gòu)問(wèn)題。這些關(guān)注點(diǎn)與具體的領(lǐng)域邏輯無(wú)關(guān),且在整個(gè)系統(tǒng)中,會(huì)作為重用模塊被諸多服務(wù)調(diào)用。調(diào)用時(shí),這些關(guān)注點(diǎn)是與領(lǐng)域邏輯交織在一起的,因此這些關(guān)注點(diǎn)都屬于橫切關(guān)注點(diǎn)。

從面向切面編程(Aspect-Oriented Programming,AOP)的角度看,所謂“橫切關(guān)注點(diǎn)”就是那些在職責(zé)上是內(nèi)聚的,但在使用上又會(huì)散布在所有對(duì)象層次中,且與所散布到的對(duì)象的核心功能毫無(wú)關(guān)系的關(guān)注點(diǎn)。與“橫切關(guān)注點(diǎn)”對(duì)應(yīng)的是“核心關(guān)注點(diǎn)”,就是與系統(tǒng)業(yè)務(wù)有關(guān)的領(lǐng)域邏輯。例如,訂單業(yè)務(wù)是核心關(guān)注點(diǎn),提交訂單時(shí)的事務(wù)管理以及日志記錄則是橫切關(guān)注點(diǎn):

public class OrderAppService {@Serviceprivate PlacingOrderService placingOrderService;// 事務(wù)為橫切關(guān)注點(diǎn)@Transactional(propagation=Propagation.REQUIRED) public void placeOrder(Order order) { try {orderService.execute(order);} catch (InvalidOrderException ex | Exception ex) {// 日志為橫切關(guān)注點(diǎn)logger.error(ex.getMessage());// ApplicationException 派生自 RuntimeException,事務(wù)會(huì)在拋出該異常時(shí)回滾throw new ApplicationException("failed to place order", ex);}}
}

橫切關(guān)注點(diǎn)與具體的業(yè)務(wù)無(wú)關(guān),它與核心關(guān)注點(diǎn)在邏輯上應(yīng)該是分離的。為保證領(lǐng)域邏輯的純粹性,應(yīng)盡量避免將橫切關(guān)注點(diǎn)放在領(lǐng)域模型對(duì)象中。于是,應(yīng)用服務(wù)就成了與橫切關(guān)注點(diǎn)協(xié)作的最佳位置。由此,可以得到應(yīng)用服務(wù)設(shè)計(jì)的第二條原則:與橫切關(guān)注點(diǎn)協(xié)作的服務(wù)應(yīng)被定義為應(yīng)用服務(wù)。

應(yīng)用服務(wù)與領(lǐng)域服務(wù)的選擇

如前所述,應(yīng)用服務(wù)不應(yīng)該包含任何領(lǐng)域邏輯,同時(shí),它又將作為一個(gè)外觀服務(wù),負(fù)責(zé)封裝多個(gè)領(lǐng)域模型對(duì)象之間的協(xié)作。那么,將多個(gè)領(lǐng)域行為組合起來(lái)的協(xié)調(diào)行為,究竟算不算是領(lǐng)域邏輯呢?例如,對(duì)于“下訂單”用例而言,如果我們?cè)诟髯缘念I(lǐng)域?qū)ο笾卸x了如下行為:

  • 驗(yàn)證訂單是否有效
  • 提交訂單
  • 移除購(gòu)物車(chē)中已購(gòu)商品
  • 發(fā)送郵件通知買(mǎi)家

這些行為的組合正好滿足了“下訂單”這個(gè)完整用例的需求,同時(shí)也為了保證客戶調(diào)用的簡(jiǎn)便性,我們需要協(xié)調(diào)這四個(gè)領(lǐng)域行為。這一協(xié)調(diào)行為牽涉到不同的領(lǐng)域?qū)ο?#xff0c;因此只能定義為服務(wù)。那么,這個(gè)服務(wù)應(yīng)該是應(yīng)用服務(wù),還是領(lǐng)域服務(wù)?

《領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)模式、原理與實(shí)踐》一書(shū)將這種封裝認(rèn)為是與領(lǐng)域的交互。該書(shū)作者給出了一個(gè)判斷標(biāo)準(zhǔn):

決定一系列交互是否屬于領(lǐng)域的一種方式是,提出“這種情況總是會(huì)出現(xiàn)嗎?”或者“這些步驟無(wú)法分開(kāi)嗎?”的問(wèn)題。如果答案是肯定的,那么這看起來(lái)就是一個(gè)領(lǐng)域策略,因?yàn)槟切┎襟E總是必須一起發(fā)生。然而,如果那些步驟可以用若干方式重新組合,那么可能它就不是一個(gè)領(lǐng)域概念。

我想,這一判斷標(biāo)準(zhǔn)是基于“任務(wù)編制”得出的結(jié)論。如果領(lǐng)域邏輯的步驟必須一起發(fā)生,就說(shuō)明這些邏輯不存在“任務(wù)編制”的可能,因?yàn)樗鼈冊(cè)诒举|(zhì)上是一個(gè)整體,只是基于單一職責(zé)原則與分治原則,需要進(jìn)行分解,做到對(duì)象的各司其職而已。如果領(lǐng)域步驟可以用若干方式重新組合,就意味著可以有多種方式進(jìn)行“任務(wù)編制”。因此,任務(wù)編制邏輯就屬于應(yīng)用邏輯的范疇,編制的每個(gè)任務(wù)則屬于領(lǐng)域邏輯的范疇,前者由應(yīng)用服務(wù)來(lái)承擔(dān),后者由領(lǐng)域模型對(duì)象來(lái)承擔(dān)。

Eric Evans 用另一種玄而又玄的說(shuō)法印證了該判斷標(biāo)準(zhǔn):“應(yīng)用服務(wù)是協(xié)調(diào)者,它們只是負(fù)責(zé)提問(wèn),而不負(fù)責(zé)回答,回答是領(lǐng)域?qū)拥墓ぷ??!?/strong>注意,對(duì)所謂“提問(wèn)”和“回答”的理解,要站在一個(gè)完整用例場(chǎng)景的高度來(lái)闡釋。當(dāng)客戶端發(fā)來(lái)請(qǐng)求要執(zhí)行一個(gè)完整的用例場(chǎng)景時(shí),作為協(xié)調(diào)者的應(yīng)用服務(wù)只負(fù)責(zé)安排任務(wù),至于任務(wù)該怎么做,就是領(lǐng)域模型對(duì)象要完成的工作。這實(shí)際上是業(yè)務(wù)價(jià)值(Why)與業(yè)務(wù)功能(What)之間的關(guān)系。對(duì)于一個(gè)用例場(chǎng)景,需要為參與者提供業(yè)務(wù)價(jià)值,該價(jià)值由應(yīng)用服務(wù)提供;要實(shí)現(xiàn)這一業(yè)務(wù)價(jià)值,需要若干業(yè)務(wù)功能按照某種順序進(jìn)行組合,組合的順序就是編制,編制的業(yè)務(wù)功能就是回答問(wèn)題的領(lǐng)域模型對(duì)象。

要基于這一標(biāo)準(zhǔn)對(duì)應(yīng)用服務(wù)與領(lǐng)域服務(wù)做出正確判斷,更多地還是依靠你對(duì)設(shè)計(jì)的感覺(jué)。因?yàn)閮r(jià)值與功能在不同的層次會(huì)產(chǎn)生一種層層遞進(jìn)的遞歸關(guān)系。例如下訂單是業(yè)務(wù)價(jià)值,驗(yàn)證訂單就是實(shí)現(xiàn)該業(yè)務(wù)價(jià)值的業(yè)務(wù)功能;然而再進(jìn)一層,又可以將驗(yàn)證訂單視為業(yè)務(wù)價(jià)值,而將驗(yàn)證訂單的配送地址有效性作為實(shí)現(xiàn)該業(yè)務(wù)價(jià)值的業(yè)務(wù)功能。至于前面提到的“任務(wù)編制”,其實(shí)也存在歧義,即使在領(lǐng)域服務(wù)中,也存在任務(wù)編制的可能,這實(shí)際取決于你對(duì)任務(wù)層次的定位。這還真是剪不斷理還亂了。

讓我們回歸本質(zhì),回到對(duì)“領(lǐng)域”這個(gè)詞的理解。在領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)這個(gè)大背景下,領(lǐng)域其實(shí)與軟件系統(tǒng)服務(wù)的行業(yè)有關(guān),如金融行業(yè)、制造行業(yè)、醫(yī)療行業(yè)、教育行業(yè)等。在領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的戰(zhàn)略階段,又將整個(gè)系統(tǒng)的領(lǐng)域分解為核心領(lǐng)域與子領(lǐng)域,它們解決的是不同的問(wèn)題域。在解決方案域,應(yīng)用服務(wù)和領(lǐng)域服務(wù)都屬于一個(gè)具體的限界上下文,它們又必然映射到問(wèn)題域中某一個(gè)子領(lǐng)域上。由此可得到一個(gè)推論:領(lǐng)域邏輯就是對(duì)應(yīng)子領(lǐng)域包含的業(yè)務(wù)知識(shí)和業(yè)務(wù)規(guī)則,應(yīng)用邏輯則是為了完成完整用例而包含的除領(lǐng)域邏輯之外的其他業(yè)務(wù)邏輯,包括作為基礎(chǔ)架構(gòu)問(wèn)題的橫切關(guān)注點(diǎn),也可能包含對(duì)非領(lǐng)域知識(shí)相關(guān)的處理邏輯,如對(duì)輸入、輸出格式的轉(zhuǎn)換等。

Eric Evans 用銀行轉(zhuǎn)賬的案例來(lái)講解應(yīng)用邏輯與領(lǐng)域邏輯的差異。他說(shuō):“資金轉(zhuǎn)賬在銀行領(lǐng)域語(yǔ)言中是一項(xiàng)有意義的操作,而且它涉及基本的業(yè)務(wù)邏輯?!边@就說(shuō)明資金轉(zhuǎn)賬屬于領(lǐng)域邏輯。至于應(yīng)用服務(wù)該做什么,他又說(shuō)道:“如果銀行應(yīng)用程序可以把我們的交易進(jìn)行轉(zhuǎn)換并導(dǎo)出到一個(gè)電子表格文件中,以便進(jìn)行分析,那么這個(gè)導(dǎo)出操作就是應(yīng)用服務(wù)。‘文件格式’在銀行領(lǐng)域中是沒(méi)有意義的,它也不涉及業(yè)務(wù)規(guī)則?!?/p>

因此,到底選擇應(yīng)用服務(wù)還是領(lǐng)域服務(wù),就看它的實(shí)現(xiàn)中到底是應(yīng)用邏輯的范疇,還是領(lǐng)域邏輯的范疇。一個(gè)簡(jiǎn)單的判斷標(biāo)準(zhǔn)在于這段代碼蘊(yùn)含的知識(shí)是否與它所處的限界上下文要解決的問(wèn)題域直接有關(guān)?如此說(shuō)來(lái),針對(duì)“下訂單”用例而言,在前面列出的四個(gè)領(lǐng)域行為中,只有“發(fā)送郵件”與購(gòu)買(mǎi)子領(lǐng)域沒(méi)有關(guān)系,因此可考慮將其作為要編制的任務(wù)放到應(yīng)用服務(wù)中。如此推導(dǎo)出來(lái)的訂單應(yīng)用服務(wù)實(shí)現(xiàn)為:

public class OrderAppService {@Serviceprivate PlacingOrderService placingOrderService;// 此時(shí)將 NotificationService 視為基礎(chǔ)設(shè)施服務(wù)@Serviceprivate NotificationService notificationService;// 事務(wù)為橫切關(guān)注點(diǎn)@Transactional(propagation=Propagation.REQUIRED) public void placeOrder(Order order) { try {orderService.execute(order);notificationService.send(notificationComposer.compose(order));} catch (InvalidOrderException ex | Exception ex) {// 日志為橫切關(guān)注點(diǎn)logger.error(ex.getMessage());// ApplicationException 派生自 RuntimeException,事務(wù)會(huì)在拋出該異常時(shí)回滾throw new ApplicationException("failed to place order", ex);}}
}

即使如此,應(yīng)用邏輯與領(lǐng)域邏輯的邊界線依舊微妙難分。

我注意到《領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)》中的兩段描述。其一:

很多領(lǐng)域服務(wù)或應(yīng)用服務(wù)是在實(shí)體和值對(duì)象的基礎(chǔ)上建立起來(lái)的,它們的行為類似于將領(lǐng)域的一些潛在功能組織起來(lái)以執(zhí)行某種任務(wù)的腳本。實(shí)體和值對(duì)象往往由于粒度過(guò)細(xì)而無(wú)法提供對(duì)領(lǐng)域?qū)庸δ艿谋憬菰L問(wèn)。

其二:

在大型系統(tǒng)中,中等粒度的、無(wú)狀態(tài)的服務(wù)更容易被復(fù)用,因?yàn)樗鼈冊(cè)诤?jiǎn)單的接口背后封裝了重要的功能?!捎趹?yīng)用層負(fù)責(zé)對(duì)領(lǐng)域?qū)ο蟮男袨檫M(jìn)行協(xié)調(diào),因此細(xì)粒度的領(lǐng)域?qū)ο罂赡軙?huì)把領(lǐng)域?qū)拥闹R(shí)泄露到應(yīng)用層中。這產(chǎn)生的結(jié)果是應(yīng)用層不得不處理復(fù)雜的、細(xì)致的交互,從而使得領(lǐng)域知識(shí)蔓延到應(yīng)用層或用戶界面代碼當(dāng)中,而領(lǐng)域?qū)訒?huì)丟失這些知識(shí)。明智地引入領(lǐng)域服務(wù)有助于在應(yīng)用層和領(lǐng)域?qū)又g保持一條明確的界限。

綜合這兩段話,我們可以隱約探索到分辨應(yīng)用服務(wù)與領(lǐng)域服務(wù)的真相。第一段提到“實(shí)體和值對(duì)象往往由于粒度過(guò)細(xì)而無(wú)法提供對(duì)領(lǐng)域?qū)庸δ艿谋憬菰L問(wèn)”,第二段又提到“細(xì)粒度的領(lǐng)域?qū)ο罂赡軙?huì)把領(lǐng)域?qū)拥闹R(shí)泄露到應(yīng)用層中”,無(wú)論從隱藏細(xì)節(jié)的角度,還是從便捷訪問(wèn)的角度,在領(lǐng)域?qū)?#xff0c;領(lǐng)域服務(wù)都成了當(dāng)仁不讓的最佳選擇。

而在第一段中,Eric Evans 又說(shuō)應(yīng)用服務(wù)和領(lǐng)域服務(wù)都是“執(zhí)行某種任務(wù)的腳本”。任務(wù)腳本可以理解為對(duì)任務(wù)的編制,只是應(yīng)用服務(wù)和領(lǐng)域服務(wù)處理的任務(wù)層級(jí)并不相同罷了。再結(jié)合第二段的最后一句“明智地引入領(lǐng)域服務(wù)有助于在應(yīng)用層和領(lǐng)域?qū)又g保持一條明確的界限”,我們有理由得到如下結(jié)論:

  • 細(xì)粒度的領(lǐng)域?qū)ο蟀▽?shí)體、值對(duì)象以及領(lǐng)域服務(wù),但為了避免領(lǐng)域?qū)又R(shí)泄漏到應(yīng)用層中,應(yīng)在領(lǐng)域?qū)佣x中等粒度的領(lǐng)域服務(wù),它的實(shí)現(xiàn)可以認(rèn)為是對(duì)細(xì)粒度領(lǐng)域服務(wù)、聚合的任務(wù)編制
  • 理想狀態(tài)下,應(yīng)用服務(wù)應(yīng)該只與中等粒度的領(lǐng)域服務(wù)協(xié)作,它對(duì)任務(wù)的編制,實(shí)則就是對(duì)領(lǐng)域服務(wù)的編制

若同意這一結(jié)論,說(shuō)明應(yīng)用服務(wù)中只能包含兩部分內(nèi)容:領(lǐng)域服務(wù)、橫切關(guān)注點(diǎn)。如此設(shè)計(jì)自然逃脫不了僵化的嫌疑,但殊不知我是在為設(shè)計(jì)做減法。若設(shè)計(jì)者能夠充分辨別應(yīng)用邏輯與領(lǐng)域邏輯之間的差別,突破這一約束也未嘗不可。一旦你擁有了足夠豐富的設(shè)計(jì)知識(shí)和設(shè)計(jì)經(jīng)驗(yàn),就意味著你可以正確地做出適合當(dāng)前場(chǎng)景的設(shè)計(jì)決策與判斷。若無(wú)法做到,不妨從一些相對(duì)固化的簡(jiǎn)單原則開(kāi)始做起,這算是從新手到專家所必須經(jīng)歷的成長(zhǎng)過(guò)程。

影響應(yīng)用服務(wù)的因素

一旦對(duì)應(yīng)用服務(wù)的設(shè)計(jì)進(jìn)行了約束,要分辨應(yīng)用服務(wù)和領(lǐng)域服務(wù)的區(qū)別就變得容易了許多。然而,軟件設(shè)計(jì)就是這樣,當(dāng)你因?yàn)槟撤N干擾因素而做出一種設(shè)計(jì)決策時(shí),在消除了這一干擾因素的同時(shí),另外一些原來(lái)不曾顯現(xiàn)的干擾因素又可能浮現(xiàn)出來(lái)。既然應(yīng)用服務(wù)的實(shí)現(xiàn)代碼只能包含橫切關(guān)注點(diǎn),也只能與領(lǐng)域?qū)拥念I(lǐng)域服務(wù)協(xié)作,那就需要我們對(duì)橫切關(guān)注點(diǎn)做出正確判斷,同時(shí)還需要明確領(lǐng)域服務(wù)的設(shè)計(jì)粒度。

橫切關(guān)注點(diǎn)的判斷

要判斷一個(gè)服務(wù)是否為應(yīng)用服務(wù),需要明確什么是“橫切關(guān)注點(diǎn)”。前面已經(jīng)明確給出了“橫切關(guān)注點(diǎn)”的定義,但是,在判斷橫切關(guān)注點(diǎn)以及整合橫切關(guān)注點(diǎn)時(shí),除了前面提到的事務(wù)、監(jiān)控、身份驗(yàn)證與授權(quán)沒(méi)有爭(zhēng)議之外,社區(qū)對(duì)如下關(guān)注點(diǎn)普遍存在困惑與糾結(jié)。

日志

毫無(wú)疑問(wèn),日志屬于橫切關(guān)注點(diǎn)的范疇。然而,倘若將日志功能僅僅放在應(yīng)用層,又可能無(wú)法準(zhǔn)確詳細(xì)地記錄操作行為與錯(cuò)誤信息。很多語(yǔ)言都提供了基礎(chǔ)的日志框架,將日志混雜在領(lǐng)域?qū)ο笾?#xff0c;會(huì)影響領(lǐng)域的純粹性,也帶來(lái)了系統(tǒng)與日志框架的耦合,除非采用 AOP 的方式。目前看來(lái),這是一種編碼取舍,即傾向于代碼的純粹性,還是代碼的高質(zhì)量。我個(gè)人更看重代碼的質(zhì)量,尤其是豐富的日志內(nèi)容有助于運(yùn)維排錯(cuò),因此可考慮將作為橫切關(guān)注點(diǎn)之一的日志功能放在領(lǐng)域服務(wù)中,算是上述應(yīng)用服務(wù)邊界定義的特例。

當(dāng)然,這個(gè)劃分并非排他性的。在應(yīng)用服務(wù)中,同樣需要調(diào)用日志功能,只是記錄的信息與粒度和領(lǐng)域服務(wù)不盡相同罷了。

驗(yàn)證

如果是驗(yàn)證外部客戶傳遞過(guò)來(lái)的消息,例如對(duì) RESTful 服務(wù)的 Request 請(qǐng)求的驗(yàn)證,則該驗(yàn)證功能屬于橫切關(guān)注點(diǎn),對(duì)它的調(diào)用就應(yīng)該放在應(yīng)用服務(wù)(亦可考慮由遠(yuǎn)程服務(wù)自己承擔(dān))。如果驗(yàn)證邏輯屬于一種業(yè)務(wù)規(guī)則,例如驗(yàn)證訂單有效性,就應(yīng)該將驗(yàn)證邏輯放在領(lǐng)域?qū)?#xff0c;以便于領(lǐng)域模型對(duì)象調(diào)用。

異常處理

與領(lǐng)域邏輯有關(guān)的錯(cuò)誤與異常,應(yīng)該以自定義異常形式表達(dá)業(yè)務(wù)含義,并被定義在領(lǐng)域?qū)?。此?#xff0c;如果該異常表達(dá)了業(yè)務(wù)含義,為了保證業(yè)務(wù)的健壯性,可在領(lǐng)域?qū)又袑惓6x為受控異常(Checked Exception)。由于該異常與業(yè)務(wù)有關(guān),即使被定義在方法接口中,也不存在異常對(duì)接口的污染,即可以將異常視為接口契約的一部分。但是,在領(lǐng)域服務(wù)中,不應(yīng)該將與業(yè)務(wù)無(wú)關(guān)的受控異常定義在領(lǐng)域服務(wù)的方法中,否則就會(huì)導(dǎo)致業(yè)務(wù)邏輯與技術(shù)實(shí)現(xiàn)的混合。

在應(yīng)用層,應(yīng)盡可能保證應(yīng)用服務(wù)的通用性,因而需要在應(yīng)用服務(wù)中捕獲與業(yè)務(wù)有關(guān)的自定義異常,然后將其轉(zhuǎn)換為標(biāo)準(zhǔn)格式的異常之后再拋出。例如,可統(tǒng)一定義為應(yīng)用層的標(biāo)準(zhǔn)異常 ApplicationException,然后在 message 或 cause 中包含具體的業(yè)務(wù)含義。因此,針對(duì)異常處理,只有這部分與業(yè)務(wù)無(wú)關(guān)的處理與轉(zhuǎn)換功能,才屬于橫切關(guān)注點(diǎn)的范疇,并放在應(yīng)用層,其余異常處理邏輯都屬于領(lǐng)域?qū)印?/p>

基礎(chǔ)設(shè)施服務(wù)

除了上述糾結(jié)的橫切關(guān)注點(diǎn)之外,我們還要注意基礎(chǔ)設(shè)施服務(wù)與橫切關(guān)注點(diǎn)之間的區(qū)別。在領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)中,基礎(chǔ)設(shè)施服務(wù)作為技術(shù)服務(wù),被定義為網(wǎng)關(guān)。從代碼實(shí)現(xiàn)的角度考慮,南向網(wǎng)關(guān)代表了一個(gè)內(nèi)聚的技術(shù)實(shí)現(xiàn),可以被抽象為接口;橫切關(guān)注點(diǎn)則是一些鉤子方法,會(huì)在領(lǐng)域行為方法的前后被執(zhí)行,因此難以抽象為接口。顯然,基礎(chǔ)設(shè)施服務(wù)就像提供的其他基礎(chǔ)功能一般,可以很容易被重用,而橫切關(guān)注點(diǎn)由于會(huì)和領(lǐng)域邏輯糾纏在一起,很難剝離出單獨(dú)的橫切關(guān)注點(diǎn)代碼,除非采用面向切面編程。

遵循應(yīng)用服務(wù)的設(shè)計(jì)原則,它除了和領(lǐng)域服務(wù)進(jìn)行協(xié)作之外,就只是包含了橫切關(guān)注點(diǎn),這就說(shuō)明應(yīng)用服務(wù)甚至都不應(yīng)該依賴于提供基礎(chǔ)設(shè)施服務(wù)的南向網(wǎng)關(guān)。這樣的設(shè)計(jì)約束充分保證了應(yīng)用服務(wù)的簡(jiǎn)單性。因此,只要判斷某個(gè)邏輯屬于基礎(chǔ)設(shè)施服務(wù),就應(yīng)該首先考慮與領(lǐng)域服務(wù)協(xié)作,而非應(yīng)用服務(wù)。例如,郵件通知服務(wù)就屬于典型的基礎(chǔ)設(shè)施服務(wù)。既然如此,針對(duì)訂單應(yīng)用服務(wù)的實(shí)現(xiàn),就應(yīng)該將通知服務(wù)轉(zhuǎn)移到 PlacingOrderService 領(lǐng)域服務(wù)中。事實(shí)上,在前面修改后的訂單應(yīng)用服務(wù)代碼中,代碼 notificationComposer.compose(order) 放在應(yīng)用服務(wù)中本身也不太合適,因?yàn)閷⒂唵蝺?nèi)容轉(zhuǎn)換為郵件通知內(nèi)容,更像是領(lǐng)域邏輯,而非應(yīng)用邏輯。

領(lǐng)域服務(wù)的設(shè)計(jì)粒度

在領(lǐng)域?qū)又?#xff0c;為了保證聚合內(nèi)部實(shí)體與值對(duì)象的純粹性,我們將與外部資源抽象之間的協(xié)作推給了領(lǐng)域服務(wù);為了避免出現(xiàn)貧血模型和過(guò)程式的事務(wù)腳本,我們要求定義帶有動(dòng)詞的領(lǐng)域服務(wù),使得領(lǐng)域服務(wù)在正確表達(dá)領(lǐng)域行為特征的同時(shí),粒度也變得更細(xì)。這時(shí)的領(lǐng)域服務(wù)其本質(zhì)更像是一個(gè)函數(shù),沒(méi)有狀態(tài),單一職責(zé),體現(xiàn)的是領(lǐng)域邏輯的行為特征。

但是,在面向?qū)ο笤O(shè)計(jì)中,粒度大小與簡(jiǎn)單設(shè)計(jì)需要平衡。若要二者兼得,需要在細(xì)粒度對(duì)象之上再引入一層封裝:一邊是紛繁的實(shí)現(xiàn)細(xì)節(jié),一邊是干凈利落的接口。這正是引入中等粒度領(lǐng)域服務(wù)的由來(lái)。中等粒度的領(lǐng)域服務(wù)實(shí)質(zhì)上是對(duì)更細(xì)粒度的領(lǐng)域模型對(duì)象之間的流程編制,它的主要作用在于協(xié)調(diào)多個(gè)領(lǐng)域?qū)ο?#xff0c;尤其是多個(gè)細(xì)粒度領(lǐng)域服務(wù)之間的協(xié)作。

還記得《理解領(lǐng)域模型》一節(jié)給出的“訂閱課程”業(yè)務(wù)場(chǎng)景的案例嗎?當(dāng)時(shí)我以可視化的時(shí)序圖方式給出了各個(gè)對(duì)象角色之間的協(xié)作關(guān)系:

79fc89bc-2ae8-4074-b9b5-4c09f2046b6c.jpg

顯然,圖中藍(lán)色的應(yīng)用服務(wù) CouseAppService 劃定了一條遠(yuǎn)程服務(wù)與領(lǐng)域?qū)又g的界限,使得遠(yuǎn)程服務(wù)無(wú)需了解課程訂閱領(lǐng)域邏輯的實(shí)現(xiàn)細(xì)節(jié)。課程與期望列表屬于兩個(gè)不同的限界上下文,但它們又都處于同一個(gè)進(jìn)程邊界內(nèi),因此它們之間的協(xié)作通過(guò)應(yīng)用服務(wù)來(lái)完成。領(lǐng)域服務(wù) SubscriptionValidation 僅僅實(shí)現(xiàn)了對(duì)訂閱的驗(yàn)證功能。它是一個(gè)細(xì)粒度服務(wù),部分驗(yàn)證的邏輯委派給了 Course 聚合,避免了貧血模型。持久化與郵件通知都屬于基礎(chǔ)設(shè)施服務(wù),分別由資源庫(kù)和郵件通知南向網(wǎng)關(guān)完成。

領(lǐng)域服務(wù) SubscribeCourseService 并沒(méi)有履行具體的業(yè)務(wù)職責(zé),它只是將多個(gè)領(lǐng)域?qū)ο蠼M合起來(lái),進(jìn)行業(yè)務(wù)流程的編制。觀察時(shí)序圖,你會(huì)發(fā)現(xiàn)由該服務(wù)發(fā)出的方法調(diào)用是最多的。這就是所謂的中等粒度領(lǐng)域服務(wù)。它在應(yīng)用層和領(lǐng)域?qū)又g劃定了一條明確的界限,也使得應(yīng)用服務(wù) CouseAppService 得償所愿,成為一個(gè)沒(méi)有領(lǐng)域邏輯的外觀服務(wù)。采用時(shí)序圖的可視化方式,可以觀察應(yīng)用服務(wù)發(fā)起的調(diào)用,即圖中涂為深藍(lán)色的地方。很明顯,應(yīng)用服務(wù)發(fā)起的調(diào)用越少,包含領(lǐng)域邏輯的可能性就越小。

http://www.risenshineclean.com/news/49602.html

相關(guān)文章:

  • 中國(guó)建設(shè)廳網(wǎng)站如何做電商
  • 網(wǎng)站改域名如何做百度優(yōu)化網(wǎng)頁(yè)優(yōu)化seo廣州
  • 浙江建設(shè)銀行官網(wǎng)站紀(jì)念幣seo和sem推廣
  • h5網(wǎng)站程序北京seo技術(shù)
  • 全國(guó)企業(yè)信用信息公示系統(tǒng)年報(bào)seo服務(wù)是什么意思
  • 購(gòu)物網(wǎng)站建設(shè)seo網(wǎng)絡(luò)營(yíng)銷(xiāo)案例分析
  • 政府網(wǎng)站建設(shè)招標(biāo)文件網(wǎng)頁(yè)制作與網(wǎng)站建設(shè)實(shí)戰(zhàn)教程
  • 手機(jī)微網(wǎng)站模板下載seo和sem推廣
  • 上海做家紡的公司網(wǎng)站成都百度推廣電話號(hào)碼是多少
  • 做暖暖XO網(wǎng)站網(wǎng)絡(luò)廣告的形式有哪些?
  • 深圳網(wǎng)站制作服務(wù)公網(wǎng)絡(luò)seo優(yōu)化平臺(tái)
  • dede網(wǎng)站seoseo難不難學(xué)
  • sm wordpress東莞關(guān)鍵詞seo
  • 電視臺(tái)網(wǎng)站建設(shè)今日最新新聞?wù)?/a>
  • 聯(lián)合易網(wǎng)北京網(wǎng)站建設(shè)公司怎么樣百度手機(jī)管家
  • 做網(wǎng)站公司漢獅團(tuán)隊(duì)金花站長(zhǎng)工具
  • 做se要明白網(wǎng)站站長(zhǎng)工具在線免費(fèi)
  • 達(dá)州北京網(wǎng)站建設(shè)seog
  • h5自適應(yīng)網(wǎng)站源碼seo的重要性
  • 企業(yè)網(wǎng)站怎樣做免費(fèi)公司軟文代寫(xiě)
  • 哪個(gè)企業(yè)的網(wǎng)站做的比較好無(wú)錫百姓網(wǎng)推廣
  • 免費(fèi)空間 個(gè)人網(wǎng)站 google廣告聯(lián)盟營(yíng)銷(xiāo)管理
  • 家紡 網(wǎng)站建設(shè) 中企動(dòng)力百度旗下有哪些app
  • 北京網(wǎng)站建設(shè)q479185700棒寧波seo外包服務(wù)商
  • 徐州英文網(wǎng)站優(yōu)化google海外版入口
  • 網(wǎng)站建設(shè)使用的技術(shù)搜索歷史記錄
  • WordPress批量定時(shí)發(fā)布文章seo美式
  • 游戲網(wǎng)站建設(shè)方案書(shū)百度seo關(guān)鍵詞點(diǎn)擊軟件
  • 做石材外貿(mào)用什么網(wǎng)站宣傳推廣圖片
  • 如何做網(wǎng)站頁(yè)面免費(fèi)的人民日?qǐng)?bào)官網(wǎng)