領(lǐng)域?qū)ο螅―omain Object)
- 領(lǐng)域模型對(duì)象(Domain Model Object)
- 資源庫(kù)(Repository)
- 領(lǐng)域事件(Domain Event)
- 應(yīng)用服務(wù)所涉及到的命令(Command)
- 查詢(xún)(Query)對(duì)象
角色
- 數(shù)據(jù)模型:面向持久化,數(shù)據(jù)的載體。
- 領(lǐng)域模型:面向業(yè)務(wù),行為的載體。
- 視圖模型:面向UI(向外),數(shù)據(jù)的載體。
- 命令模型:面向UI(向內(nèi)),數(shù)據(jù)的載體。
領(lǐng)域模型
- 實(shí)體:包含數(shù)據(jù),可對(duì)數(shù)據(jù)進(jìn)行賦值
- 值對(duì)象:包含數(shù)據(jù),只能new,不可更改其值
- 聚合根:聚合根也是實(shí)體,但包含其它實(shí)體和值對(duì)象,并有對(duì)應(yīng)的業(yè)務(wù)邏輯。在聚合根里,不能和其它系統(tǒng)(DB、RPC等)有交互
名詞解釋
- ACL:防腐層(Anticorruption Layer,ACL)
- UP:統(tǒng)一協(xié)議(Unified Protocol,UP)
- EDA:事件驅(qū)動(dòng)架構(gòu)(Event-Driven Architecture,EDA)
- CQRS:的全稱(chēng)是 Command Query Responsibility Segregation,也就是命令和查詢(xún)職責(zé)分離
- CRUD:增加(Create)、檢索(Retrieve)、更新(Update)和刪除(Delete)
- DMO:領(lǐng)域模型對(duì)象(Domain Model Object)
- AOP:切面
- DMO:領(lǐng)域模型對(duì)象(Domain Model Object),聚合根、實(shí)體、值對(duì)象
- DO:領(lǐng)域?qū)ο螅―omain Object),包含領(lǐng)域模型對(duì)象(Domain Model Object)、資源庫(kù)(Repository)、領(lǐng)域事件(Domain Event)以及應(yīng)用服務(wù)所涉及到的命令(Command)和查詢(xún)(Query)對(duì)象
- PO:資源庫(kù)實(shí)現(xiàn)部分所對(duì)應(yīng)的數(shù)據(jù)對(duì)象稱(chēng)為是一種持久化對(duì)象(Persistence Object,PO)
- DM:數(shù)據(jù)映射器(Data Mapper) 的概念。映射(Mapping)思想在軟件設(shè)計(jì)過(guò)程中非常常用,主要用于分離不同層次之間的數(shù)據(jù)耦合。對(duì)于數(shù)據(jù)訪(fǎng)問(wèn)而言,數(shù)據(jù)映射器的作用在于分離領(lǐng)域?qū)ο蠛统志没浇椤?/li>
- VO(View Object)視圖對(duì)象:和視圖打交道的,那么經(jīng)歷了視圖的都?xì)w屬于這個(gè)類(lèi),所以我們的輸入輸出類(lèi)都是屬于VO
- DTO(Data Transfer Object)數(shù)據(jù)傳輸對(duì)象:我們sql查詢(xún)的時(shí)候是通過(guò)Id查詢(xún)的,但是查詢(xún)是可以查詢(xún)出很多條信息的,但是我們給前端的數(shù)據(jù)只要某一部分,比如上例有4個(gè)屬性,但是只要求輸出3個(gè)。
- DAO:Data Access Object,數(shù)據(jù)訪(fǎng)問(wèn)對(duì)象1.用來(lái)封裝對(duì)數(shù)據(jù)庫(kù)的訪(fǎng)問(wèn)(CRUD)2.通過(guò)接收Business層的數(shù)據(jù),將POJO持久化為PO
- BO( Business Object):業(yè)務(wù)對(duì)象。由Service層輸出的封裝業(yè)務(wù)邏輯的對(duì)象。
CQRS
將 command 與 query 分離的一種模式
https://martinfowler.com/bliki/CommandOrientedInterface.html
CQRS 將系統(tǒng)中的操作分為兩類(lèi),即命令(Command) 與查詢(xún)(Query)。命令則是對(duì)會(huì)引起數(shù)據(jù)發(fā)生變化操作的總稱(chēng),即我們常說(shuō)的新增,更新,刪除這些操作,都是命令。而查詢(xún)則和字面意思一樣,即不會(huì)對(duì)數(shù)據(jù)產(chǎn)生變化的操作,只是按照某些條件查找數(shù)據(jù)
當(dāng) command 系統(tǒng)完成數(shù)據(jù)更新的操作后,會(huì)通過(guò)「領(lǐng)域事件」的方式通知 query 系統(tǒng)。query 系統(tǒng)在接受到事件之后更新自己的數(shù)據(jù)源。所有的查詢(xún)操作都通過(guò) query 系統(tǒng)暴露的接口完成。
ACL
一個(gè)上下文通過(guò)一些適配和轉(zhuǎn)換與另一個(gè)上下文交互

防腐層是一種在不同應(yīng)用間轉(zhuǎn)換的機(jī)制。創(chuàng)建一個(gè)防腐層,以根據(jù)客戶(hù)端自己的領(lǐng)域模型為客戶(hù)提供功能。該層通過(guò)其現(xiàn)有接口與另一個(gè)系統(tǒng)進(jìn)行通信,幾乎不需要對(duì)其進(jìn)行任何修改。
在不共享相同領(lǐng)域模型的不同子系統(tǒng)之間實(shí)施防腐層(或外觀(guān)或適配器層),此層轉(zhuǎn)換一個(gè)子系統(tǒng)向另一個(gè)子系統(tǒng)發(fā)出的請(qǐng)求。 使用防腐層(Anti-corruption layer)模式可確保應(yīng)用程序的設(shè)計(jì)不受限于對(duì)外部子系統(tǒng)的依賴(lài)。 防腐層(Anti-corruption layer)模式最先由 Eric Evans 在 Domain-Driven Design(領(lǐng)域驅(qū)動(dòng)的設(shè)計(jì))中描述。
因此,防腐層隔離不僅是為了保護(hù)自身領(lǐng)域模型免受其他領(lǐng)域模型的代碼的侵害,還在于分離不同的域并確保它們?cè)趯?lái)保持分離。
EDA
- 當(dāng)類(lèi)或組件之間內(nèi)聚性很高,它們的耦合度應(yīng)該很低,也就是說(shuō)當(dāng)組件需要相互協(xié)作調(diào)用時(shí),比如我們假設(shè)一個(gè)組件“A”需要觸發(fā)組件“B”中的一些邏輯,自然的方式是直接讓組件A調(diào)用組件B中的一個(gè)方法。但前提是A必須知道B的存在,這樣它們之間就是耦合的,A必須依賴(lài)于B了,這會(huì)使得系統(tǒng)更難以改變和維護(hù)。因此,這里可以使用事件來(lái)防止這種直接調(diào)用的耦合。
- 此外,使用事件實(shí)現(xiàn)組件解耦也有其另外的,如果我們有一個(gè)只負(fù)責(zé)組件B的工作團(tuán)隊(duì),那么他們則可能不需要與負(fù)責(zé)組件A的團(tuán)隊(duì)進(jìn)行交流,直接針對(duì)組件A中的邏輯改變?cè)诮M件B中做出相對(duì)反應(yīng)。兩個(gè)組件團(tuán)隊(duì)可以獨(dú)立發(fā)展, 我們的應(yīng)用系統(tǒng)變得更靈活。
-
去耦組件
當(dāng)組件A執(zhí)行的邏輯需要觸發(fā)組件B的邏輯時(shí),不要直接調(diào)用它,我們可以將觸發(fā)事件發(fā)送到事件分派器。組件B將偵聽(tīng)調(diào)度程序中的特定事件,并在事件發(fā)生時(shí)執(zhí)行操作。
這意味著A和B都將取決于調(diào)度器和事件,但他們之間將不會(huì)知道對(duì)方存在,它們將被解耦。
理想情況下,調(diào)度員和事件都不應(yīng)該在兩個(gè)組件之間存在:
(1)調(diào)度員應(yīng)該是完全獨(dú)立于我們應(yīng)用程序的庫(kù),因此使用依賴(lài)管理系統(tǒng)安裝在通用位置。
(2) 事件是我們的應(yīng)用程序的一部分,應(yīng)該在兩個(gè)組件之間生存,組件之間通過(guò)事件進(jìn)行通訊(結(jié)構(gòu)上解耦,行為上耦合)。事件在組件之間共享,它是應(yīng)用程序的核心部分。事件在DDD中屬于共享內(nèi)核Shared Kernel的一部分。這樣,兩個(gè)組件都將依賴(lài)于共享內(nèi)核,但彼此不會(huì)意識(shí)到。然而在單體Monolithic應(yīng)用程序中,為方便起見(jiàn),可以將其放在觸發(fā)事件的組件中。
DDD共享內(nèi)核- 明確界定指定團(tuán)隊(duì)同意分享的領(lǐng)域模型的一些子集。保持這個(gè)內(nèi)核很小。
- 這個(gè)明確共享的東西有特殊的地位,如果沒(méi)有與其他團(tuán)隊(duì)協(xié)商,不應(yīng)該改變。
執(zhí)行異步任務(wù)
有時(shí)候我們有一個(gè)我們想要執(zhí)行的邏輯,但它可能需要相當(dāng)長(zhǎng)的時(shí)間來(lái)執(zhí)行,我們不想讓用戶(hù)等待它完成。在這種情況下,希望將其作為異步工作運(yùn)行,并立即返回給用戶(hù)的消息,通知他請(qǐng)求將在以后異步執(zhí)行。
例如,在網(wǎng)上商店下訂單可以同步完成,但發(fā)送通知用戶(hù)的電子郵件可以進(jìn)行異步。
在這種情況下,我們可以做的是觸發(fā)一個(gè)將被排隊(duì)的事件,直到一個(gè)工作任務(wù)可以獲得這個(gè)事件并執(zhí)行它,只要系統(tǒng)有資源。
在這些情況下,相關(guān)聯(lián)的邏輯是否在相同的有界環(huán)境中并不重要,無(wú)論哪種方式,邏輯都是去耦的。-
跟蹤狀態(tài)變化(審計(jì)日志)
以傳統(tǒng)的數(shù)據(jù)存儲(chǔ)方式,我們擁有一些數(shù)據(jù)的實(shí)體。當(dāng)這些實(shí)體中的數(shù)據(jù)發(fā)生變化時(shí),我們只需更新數(shù)據(jù)庫(kù)表行以反映新值。
這里的問(wèn)題是,我們并不存儲(chǔ)這些值為什么改變且什么時(shí)候改變。
我們可以將這些改變的事件存儲(chǔ)在審計(jì)日志中。
更多關(guān)于這個(gè)進(jìn)一步的前景,在關(guān)于事件溯源的解釋。
Martin Fowler確定了三種不同類(lèi)型的事件模式:- 事件通知
- 事件執(zhí)行狀態(tài)轉(zhuǎn)移
- 事件溯源Event Sourcing
所有這些模式共享相同的關(guān)鍵概念:
- 事件是代表發(fā)生了一些事情(發(fā)生在某事之后)
- 事件被廣播到正在監(jiān)聽(tīng)的任何代碼(代碼可以對(duì)事件做出反應(yīng))
DMO
和數(shù)據(jù)模型區(qū)分開(kāi)即可
參考
- 《實(shí)現(xiàn)領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)》- 沃恩·弗農(nóng)
- 《領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)——軟件核心復(fù)雜性應(yīng)對(duì)之道》- Eric Evans