領域驅(qū)動設計統(tǒng)一過程交付物
一、全局分析階段
1.業(yè)務流程
梳理問題空間的業(yè)務需求,獲得用泳道圖表現(xiàn)的業(yè)務流程:
2.業(yè)務服務
根據(jù)業(yè)務服務的定義分析業(yè)務流程,識別出業(yè)務服務,并以業(yè)務服務圖(參考用例圖)形式表示:
說明:如果采用敏捷方式管理需求,可以將業(yè)務服務作為用戶故事的子任務,它不包括前端的交互設計和開發(fā)內(nèi)容。
如果需要進一步細化業(yè)務服務,則需要按照如下格式編寫業(yè)務服務規(guī)約:
編寫業(yè)務服務規(guī)約時,需要遵循統(tǒng)一語言。
以上內(nèi)容,可以構成目標系統(tǒng)的需求規(guī)格說明書。
二、架構映射階段
1.系統(tǒng)上下文
系統(tǒng)上下文用于呈現(xiàn)目標系統(tǒng)的系統(tǒng)邊界,明確目標系統(tǒng)與角色、伴生系統(tǒng)之間的關系??梢酝ㄟ^改進的系統(tǒng)上下文圖來表示:
改進的系統(tǒng)上下文有效地利用了四個方位:
- 上方:代表北向,即調(diào)用目標系統(tǒng)的伴生系統(tǒng)或模塊
- 下方:代表南向,即目標系統(tǒng)調(diào)用的伴生系統(tǒng)或模塊
- 左方:代表使用目標系統(tǒng)的所有角色
- 右方:代表互相調(diào)用的伴生系統(tǒng)或模塊
2.限界上下文
識別限界上下文
運用服務風暴法,識別限界上下文,建立業(yè)務服務與限界上下文的映射關系,并以下圖形式呈現(xiàn)出來:
圖中的菱形代表限界上下文,橢圓形代表業(yè)務服務。
確定上下文映射
針對每一個業(yè)務服務,通過業(yè)務服務規(guī)約繪制服務序列圖,以確定限界上下文之間的協(xié)作關系,并驅(qū)動出每個限界上下文的服務契約。繪制服務序列圖時,根據(jù)業(yè)務服務規(guī)約“成功場景”部分的流程,確定每個流程步驟需要的領域知識和領域職責應該由哪一個限界上下文負責。服務序列圖如下所示:
通過服務序列圖,既可以明確限界上下文之間的關系,又可以驅(qū)動出每個限界上下文包括伴生系統(tǒng)的服務契約(API),同時還能夠確定協(xié)作模式,包括客戶方-供應方模式和發(fā)布者-訂閱者模式。其中,查詢和命令方式屬于客戶方-供應方模式,事件方式屬于發(fā)布者-訂閱者模式。服務契約可以通過下表格式表示:
服務契約的API定義也可以在Swagger中維護。
最后,可以通過如下圖示表示限界上下文:
與改進的系統(tǒng)上下文圖相似,限界上下文圖也有效地利用了四個方位:
- 上方:代表北向服務,為當前限界上下文對外公開的服務接口
- 下方:代表南向服務,為當前限界上下文調(diào)用上游限界上下文或伴生系統(tǒng)的服務接口
- 左方:當前限界上下文訂閱的事件
- 右方:當前限界上下文發(fā)布的事件
限界上下文內(nèi)部可以呈現(xiàn)屬于當前限界上下文領域模型的聚合,如果還未開展領域建模,可以為空。
菱形對稱架構
限界上下文的內(nèi)部應遵循如下圖所示的菱形對稱架構:
菱形對稱架構的核心思想:
- 內(nèi)外分離:內(nèi)部的領域?qū)优c外部的網(wǎng)關層分離,保證業(yè)務和技術的正交性
- 南北對稱:南向網(wǎng)關采用抽象思想,隔離外部資源變化對內(nèi)部領域?qū)訋淼挠绊?;北向網(wǎng)關采用封裝思想,通過定義遠程服務和本地服務隔離內(nèi)部領域邏輯對外部調(diào)用者的影響
系統(tǒng)分層架構
在目標系統(tǒng)層面上,需要將各個限界上下文組織在如下圖所示的系統(tǒng)分層架構中:
代碼模型
遵循菱形對稱架構,一個完整的代碼模型如下所示:
- valueaddedlayer
boundedcontext
- north
- remote
resource
controller
provider
subscriber
- local
- message
- domain
- aggregate
entity
valueobject
domainservice
- south
- port
repository
client
publisher
- adapter
repository
client
publisher
以上內(nèi)容構成了目標系統(tǒng)的架構設計文檔。
三、領域建模階段
1.領域分析建模
領域建模階段是通過對業(yè)務服務規(guī)約進行領域分析建模開始的。領域分析建模與具體的建模技術和設計方法沒有任何關系,只是從業(yè)務的角度通過提取領域概念獲得最終的領域分析模型。該方法為快速建模法,得到的模型如下圖所示:
圖中的灰色領域概念是通過動詞建模法獲得的。整個領域分析模型需要分配給對應的限界上下文。
2.領域設計建模
靜態(tài)設計模型
領域設計建模從下圖所示的領域分析模型開始:
識別實體和值對象:
確定實體之間的關系:
根據(jù)實體關系的強弱劃定聚合的邊界,獲得以聚合為中心的領域設計模型:
動態(tài)設計模型
獲得動態(tài)設計模型的過程如下圖所示:
分析業(yè)務服務,獲得如下所示的業(yè)務服務規(guī)約:
服務編號:033
服務名:報名活動
服務描述:
作為報名人
我想要報名活動
以便于預留活動報名資格
觸發(fā)事件:
報名人選擇自己想要報名的活動,點擊“報名”按鈕
基本流程:
- 檢查報名人是否有效
- 檢查報名通道是否已關閉
- 檢查該報名人是否已報名
- 完成報名預約
- 發(fā)送報名預約成功的通知
替換流程:
- a 若報名人無效,給出提示信息
- a 如果報名通道已關閉,給出提示信息
- a 如果已報名,給出提示信息
- a 如報名失敗,給出失敗原因
驗收標準:
- 報名人必須是活動所屬部落的會員
- 報名達到截止日期或者報名人數(shù)已到達上限,則視為報名通道已關閉
- 報名人不能重復報名
- 完成報名后,報名狀態(tài)設置為“已預訂”
- 報名人接收到預約成功的通知
根據(jù)業(yè)務服務規(guī)約獲得如下所示的任務樹:
- 報名活動
- 驗證報名
- 驗證報名人是否會員 --- 訪問部落上下文
- 確定報名通道是否已關閉
- 獲取報名通道
- 確定是否已關閉
- 驗證報名單 ---- Repository
- 生成報名單 --- Repository
- 更新報名通道
- 加載報名通道
- 更新
- 保存報名通道
- 發(fā)送報名預約成功的通知 --- 通知上下文
分配職責給對應的角色構造型,形成序列圖腳本:
TicketController.enrollActivity(EnrollingRequest) {
TicketAppService.enrollActivity(EnrollingRequest) {
Ticket ticket = EnrollingRequest.to()
TicketService.enrollActivity(ticket) {
TicketService.validate(ticket) {
MemberClient.isMember(enrollerId, tribeId)
EnrollingChannelService.isClosed(activityId) {
EnrollingChannel channel = EnrollingChannelRepository.channelOf(activityId)
channel.isClosed()
}
TicketRepository.isExists(enrollerId, activityId, TicketStatus)
}
TicketRepository.add(ticket)
EnrollingChannelService.occupiedBy(activityId) {
EnrollingChannel channel = EnrollingChannelRepository.channelOf(activityId)
channel.occupiedWith(1)
EnrollingChannelRepository.save(channel)
}
}
ActivitySubscribedPublisher.publish(ActivitySubscribed)
}
}
領域建模階段輸出的靜態(tài)領域設計模型與動態(tài)領域設計模型共同組成限界上下文的設計文檔。