自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

DDD概念復(fù)雜難懂,實際落地如何設(shè)計代碼實現(xiàn)模型?

開發(fā)
在本文所展示的案例中,我們使用了Spring Boot、Spring Cloud Stream等Spring家族中的開發(fā)框架,來開發(fā)DDD應(yīng)用程序。

寫在前面:

今天我接著跟大家聊一聊,DDD概念復(fù)雜難懂,實際落地如何設(shè)計代碼實現(xiàn)模型?;蛟S你是剛看到關(guān)于這部分的內(nèi)容,想著這里我有必要多說一句,關(guān)于這個話題,框架上,分為這樣兩部分講的:方法篇 + 實踐篇。

前一部分,方法篇。旨在詳細(xì)介紹DDD所包含的幾個核心概念,以及圍繞這些概念所構(gòu)建的DDD代碼實現(xiàn)模型的組成結(jié)構(gòu)。至于為何有必要講,上一篇開頭我有明確告訴大家。

另外,考慮到有的朋友可能才剛點進(jìn)來,還沒看過上一篇,或者沒來得及看,故而這里也再點明說一下 我想分享這一話題的必要性,以便于幫你快速知曉可以或多或少有哪方面的收獲。

開門見山說,可惜的是,目前業(yè)界關(guān)于如何實施這些概念,并沒有一套統(tǒng)一的標(biāo)準(zhǔn)和規(guī)范,這就導(dǎo)致我們在具體的開發(fā)過程中,常常感到無從下手。

為此,本文專門提煉了一整套DDD代碼實現(xiàn)模型。

此外,關(guān)于看的方式,我多說一句?;谑欠譃榍昂髢刹糠指掳l(fā)布的,這就涉及到先后了。若上一篇你還未看,朋友,建議你可以先花上幾分鐘,或者結(jié)合文章中大小標(biāo)題的思路引導(dǎo),大致了解下行文框架。咱們可以過完上一篇,再進(jìn)入這篇的分享,結(jié)合著,效果更好。

?01 如何設(shè)計DDD代碼實現(xiàn)模型?

在分析DDD代碼實現(xiàn)模型時,對于上一篇提到的四個組成部分,我們需要梳理它們的代碼結(jié)構(gòu)和依賴關(guān)系。針對代碼結(jié)構(gòu),我們需要明確代碼包的組成,以及內(nèi)部所包含的技術(shù)組件。

在明確了包結(jié)構(gòu)之后,依賴關(guān)系指的是我們需要進(jìn)一步明確這些代碼包和技術(shù)組件之間的交互關(guān)系。基于這兩點,讓我們先來討論領(lǐng)域?qū)ο蟮拇a實現(xiàn)模型。

??  領(lǐng)域?qū)ο蟠a實現(xiàn)模型

針對領(lǐng)域?qū)ο?,我們通常用“domain”這個單詞,對代碼包結(jié)構(gòu)的頂層包進(jìn)行命名,在該包結(jié)構(gòu)下的所有技術(shù)組件,都屬于領(lǐng)域?qū)ο蟮姆懂牎?/p>

具體而言,在DDD中,領(lǐng)域?qū)ο蟀I(lǐng)域模型對象、領(lǐng)域事件、資源庫以及應(yīng)用服務(wù)所涉及到的命令和查詢對象,其中領(lǐng)域模型對象可以分為聚合、實體和值對象這三大類。

因此,在DDD所有的代碼實現(xiàn)模型中,領(lǐng)域?qū)ο笊婕暗拇a結(jié)構(gòu)最為復(fù)雜,可以分成兩個層次,如圖1所示。

圖片

圖1

可以看到,這里的“domain”代表整個領(lǐng)域?qū)ο?,而“model”則代表領(lǐng)域模型對象,請注意這兩者在命名上的區(qū)別,以及它們之間的從屬關(guān)系。領(lǐng)域?qū)ο笫荄DD代碼實現(xiàn)模型的基礎(chǔ),包含核心業(yè)務(wù)邏輯的實現(xiàn)。

??  應(yīng)用服務(wù)代碼實現(xiàn)模型

類似地,針對應(yīng)用服務(wù),我們通常使用“application”來命名頂層包結(jié)構(gòu)。應(yīng)用服務(wù)包含查詢服務(wù)和命令服務(wù)這兩大類,所以在子包的命名上,也會用“commandservice”和“queryservice”加以區(qū)分,如圖2所示。

圖片

圖2

顯然,命令服務(wù)和查詢服務(wù),分別依賴于領(lǐng)域?qū)ο蟠a實現(xiàn)模型中的命令對象和查詢對象,我們用虛線表示這層依賴關(guān)系。在DDD的代碼實現(xiàn)模型中,應(yīng)用服務(wù)可以說是交互關(guān)系最為復(fù)雜的一個代碼模型。

一方面,它需要將命令和查詢操作,分派給聚合對象等領(lǐng)域模型對象。

另一方面,它也需要分別和基礎(chǔ)設(shè)施,以及其他限界上下文進(jìn)行交互。

關(guān)于后者,我們在討論到案例分析時,還會做進(jìn)一步展開。

??  基礎(chǔ)設(shè)施代碼實現(xiàn)模型

其實,所謂的基礎(chǔ)設(shè)施,指的是DDD應(yīng)用程序中所使用到的各種具體技術(shù)、工具和框架。常見的基礎(chǔ)設(shè)施類組件主要包括這幾個方面:

  • 數(shù)據(jù)持久化(Persistence)
  • 消息通信(Messaging)
  • 系統(tǒng)配置(Config)
  • 安全控制(Security)

因此,基礎(chǔ)設(shè)施的包結(jié)構(gòu)并不是固定的,而是根據(jù)具體的技術(shù)開發(fā)要求進(jìn)行靈活的組織,這里給出一個常見的包結(jié)構(gòu),如圖3所示。針對基礎(chǔ)設(shè)施,我們使用了“infrastructure”,對這一包結(jié)構(gòu)進(jìn)行命名。

圖片

圖3

上圖中有一點需要注意,代表數(shù)據(jù)持久化的“persistence”包,和代表消息通信的“messaging”包,在基礎(chǔ)設(shè)施代碼實現(xiàn)模型中是最常見的,因為它們分別對應(yīng)著領(lǐng)域?qū)ο笾械馁Y源庫和領(lǐng)域事件。

在DDD中,資源庫和領(lǐng)域事件的定義位于領(lǐng)域?qū)ο蟠a實現(xiàn)模型中,它們與具體的實現(xiàn)技術(shù)無關(guān)。而與具體實現(xiàn)技術(shù)相關(guān)的持久化和消息通信,則位于基礎(chǔ)設(shè)施代碼實現(xiàn)模型中。這里體現(xiàn)了領(lǐng)域?qū)ο笈c實現(xiàn)技術(shù)相互分離的設(shè)計原則。

??  上下文集成代碼實現(xiàn)模型

最后,我們來討論上下文集成代碼實現(xiàn)模型。需要注意的是,這個模型實現(xiàn)起來難度最大,因為涉及到多種系統(tǒng)集成技術(shù)體系。

針對這一代碼實現(xiàn)模型,我們首先需要明確它是面向多個限界上下文的,所以我們需要考慮數(shù)據(jù)的流向,也就是所謂的內(nèi)向(Inbound)數(shù)據(jù)和外向(Outbound)數(shù)據(jù)。

一方面,限界上下文,需要暴露訪問入口供其他上下文進(jìn)行使用。站在當(dāng)前上下文角度看,這是一個Inbound操作。而當(dāng)某一個上下文向外部上下文發(fā)起請求時,這就是一個Outbound操作,如圖4所示。

圖片

圖4

在代碼實現(xiàn)模型的設(shè)計上,我們也將采用“inbound”和“outbound”來命名包結(jié)構(gòu)。那么這兩個包結(jié)構(gòu)下,應(yīng)該包含哪些技術(shù)組件呢?

我們先來討論“outbound”包結(jié)構(gòu),如圖5所示。 圖中,“rest”包中的REST API將外部請求,轉(zhuǎn)化為內(nèi)部的Command和Query對象,并交由應(yīng)用服務(wù)進(jìn)行處理。在這個轉(zhuǎn)化過程中,通常需要引入專門的DTO(Data Transfer Object,數(shù)據(jù)傳輸對象)對象,和組裝器(Assembler)對象。

圖片

圖5

同時,“eventpublisher”包中的事件發(fā)布器(Event Publisher),則用來面向外部限界上下文發(fā)布領(lǐng)域事件。

接著,我們討論“inbound”包結(jié)構(gòu)。在一個限界上下文中,數(shù)據(jù)的Inbound操作主要有兩類,一類是防腐層(Anti-Corruption Layer,ACL),用來向遠(yuǎn)程REST API發(fā)起請求并獲取結(jié)果。另一類是用來完成對領(lǐng)域事件進(jìn)行響應(yīng)的事件處理器(Event Handler),如圖6所示。

圖片

圖6

基于上下文集成過程,兩個上下文中的“inbound”和“outbound”包結(jié)構(gòu)中所包含的技術(shù)組件,實際上是一一對應(yīng)的,如圖7所示。

可以看到,一個限界上下文“inbound”中的“acl”和“eventhandler”,分別對應(yīng)著另一個限界上下文“outbound”中的“rest”和“eventpublisher”。

圖片

圖7

至此,關(guān)于DDD中四大類代碼實現(xiàn)模型,已介紹完。在接下來的內(nèi)容中,我們將基于一個具體的應(yīng)用場景,通過案例分析,將這些代碼實現(xiàn)模型付諸于實踐?;谶@個案例,你可以將本文前面介紹的所有內(nèi)容,和日常開發(fā)過程聯(lián)系起來,進(jìn)一步掌握將模型轉(zhuǎn)化為具體代碼的實現(xiàn)方法和技巧。

02 DDD代碼實現(xiàn)模型案例分析

在現(xiàn)實世界中,工單處理是一個非常常見的業(yè)務(wù)需求。而工單的發(fā)起,通常都是因為用戶需要對訂單進(jìn)行咨詢或投訴。

在這個場景中,基于DDD的設(shè)計方法,我們可以分別拆分出工單(Ticket)、客服(Staff),以及訂單(Order)這三個限界上下文。在這三個上下文中,Ticket上下文,會分別與Staff和Order這兩個上下文進(jìn)行集成,從而創(chuàng)建工單申請,如圖8所示。

請注意,圖中展示了Ticket上下文,所具備的兩種不同的上下文集成方式。

針對Staff上下文,Ticket上下文將使用REST API,完成對工單中客服數(shù)據(jù)的獲取。

而針對Order上下文,則使用了領(lǐng)域事件,即一旦Order的狀態(tài)發(fā)生變化,Order上下文會發(fā)送對應(yīng)的領(lǐng)域事件到Ticket上下文中。

圖片

圖8

??  Ticket上下文代碼實現(xiàn)模型示例

顯然,針對這一場景,Ticket上下文同時具備了Inbound和Outbound操作。因此,它的代碼實現(xiàn)模型是最完整的,如圖9所示。

圖片

圖9

上圖中,我們使用IDEA這款開發(fā)工具和Spring Boot這一特定的開發(fā)框架,構(gòu)建了Ticket限界上下文的代碼實現(xiàn)模型。我們可以很清晰地看到,DDD四種代碼實現(xiàn)模型的表現(xiàn)形式,就是五個頂層的代碼包結(jié)構(gòu)。其中,上下文集成代碼實現(xiàn)模型同時包含了“inbound”和“outbound”這兩個代碼包。

我們再對這些頂層代碼包結(jié)構(gòu)做展開,可以得到如圖10所示的子代碼包結(jié)構(gòu)。

圖片

圖10(上下滑動查看)

上圖所示的所有子代碼包結(jié)構(gòu),在前面的內(nèi)容中也都已經(jīng)給出了相應(yīng)的描述,這里便不再贅述。

Ticket上下文中,命令服務(wù)TicketCommandService完成了對Staff服務(wù)的上下文集成,這時候采用的是防腐層ACL組件,示例代碼如下所示。

可以看到,這里使用AclStaffService這個ACL組件,對Staff服務(wù)發(fā)起了遠(yuǎn)程調(diào)用,然后把返回結(jié)果填充到命令對象,并創(chuàng)建Ticket聚合。最終,我們通過TicketRepository完成了對聚合對象的持久化操作。

圖片

圖11

上述AclStaffService,就完成了對Staff上下文所提供的REST API的調(diào)用,示例代碼如下所示。這里用到了Spring自帶的RestTemplate模板工具類,完成對遠(yuǎn)程HTTP端點的訪問操作。

圖片

圖12

??  Staff上下文代碼實現(xiàn)模型示例

在Staff上下文,我們需要完成對上述REST API的構(gòu)建,它的代碼工程結(jié)構(gòu)如下圖所示。

可以看到,相較Ticket上下文,Staff上下文的代碼結(jié)構(gòu)比較簡單,因為該上下文只需要提供對外的“outbound”包,而基礎(chǔ)設(shè)施部分也只需要完成對領(lǐng)域?qū)ο蟮某志没僮骷纯伞?/p>

圖片

圖13

??  Order上下文代碼實現(xiàn)模型示例

最后,我們來到Order限界上下文,它的代碼實現(xiàn)模型是這樣的,可以一同看下。

圖片

圖14

我們知道Order上下文,提供了針對Order數(shù)據(jù)的領(lǐng)域事件發(fā)布機制,所以它的“outbound”包中包含了用于發(fā)布領(lǐng)域事件的“eventpublisher”子包,并提供了一個OrderEventPublisherService,如下所示。 

圖片

圖15

這里通過Spring Cloud Stream,實現(xiàn)了領(lǐng)域事件的發(fā)布。而在Ticket上下文中,我們同樣可以基于Spring Cloud Stream,實現(xiàn)對該領(lǐng)域事件的監(jiān)聽和消費,示例代碼如下所示。

圖片

圖16

請注意,上述OrderUpdatedEventHandler,位于Ticket上下文“inbound”包的”eventhandler”子包中。

關(guān)于這些具體實現(xiàn)代碼的講解不是本文的重點,你可以參考筆者在Github上的案例代碼進(jìn)行系統(tǒng)學(xué)習(xí):https://github.com/tianminzheng/customer-service。

03 總結(jié)和延伸思考

今天的分享到這里就結(jié)束了。本文內(nèi)容詳細(xì)回答了開發(fā)人員,在實現(xiàn)DDD應(yīng)用程序中所碰到的一個核心問題,即如何構(gòu)建DDD的代碼實現(xiàn)模型。之所以要討論這個話題,原因在于DDD中的很多概念都比較晦澀難懂,而業(yè)界也沒有為如何實現(xiàn)這些概念,提供統(tǒng)一的開發(fā)規(guī)范和標(biāo)準(zhǔn)。

而通過將DDD中的各種復(fù)雜概念與具體代碼實現(xiàn)模型進(jìn)行映射,在幫我們更好地理解這些概念的同時,也能夠?qū)⑺鼈冎苯討?yīng)用到日常開發(fā)過程中。

通過本文內(nèi)容的介紹,開發(fā)人員可以結(jié)合自身的業(yè)務(wù)開發(fā)需求,設(shè)計一套完整的DDD代碼實現(xiàn)模型。這里也附上全文思維導(dǎo)圖,助你回顧、梳理思路等。

圖片

圖17 全文思維框架導(dǎo)圖-幫助你快速回顧、梳理、總結(jié)

??  最后,我覺得還是有必要強調(diào)一點

本文中給出的DDD代碼實現(xiàn)模型,也只是一個參考模型。而代碼實現(xiàn)模型的設(shè)計,也與具體所采用的技術(shù)體系有一定關(guān)聯(lián)。在本文所展示的案例中,我們使用了Spring Boot、Spring Cloud Stream等Spring家族中的開發(fā)框架,來開發(fā)DDD應(yīng)用程序。

而如果你使用Axon這種基于事件溯源模式的DDD開發(fā)框架,那么在代碼實現(xiàn)模型中,就需要引入用于事件分發(fā)和存儲的Gateway、EventStore等組件,而位于基礎(chǔ)設(shè)施中的傳統(tǒng)數(shù)據(jù)持久化組件,可能就不一定會被使用到。

當(dāng)然,基于我們今天介紹的內(nèi)容,相信你并不難對這套DDD代碼實現(xiàn)模型進(jìn)行擴展。DDD作為一種系統(tǒng)建模方法論,也存在一些諸如分層架構(gòu)、整潔架構(gòu)、六邊形架構(gòu)等多種架構(gòu)風(fēng)格。

針對每種架構(gòu)風(fēng)格,我們都需要設(shè)計對應(yīng)的代碼實現(xiàn)模型。

而基于本文中介紹的內(nèi)容,通過對DDD中各個核心概念與實現(xiàn)模型之間進(jìn)行合理的映射,我在文中提供了一套設(shè)計代碼實現(xiàn)模型的系統(tǒng)方法,從而幫助你可以應(yīng)對不同架構(gòu)風(fēng)格的實現(xiàn)要求。

這也是本文的核心價值所在。?


責(zé)任編輯:張燕妮 來源: 君哥聊技術(shù)
相關(guān)推薦

2023-08-28 07:28:41

項目領(lǐng)域?qū)?/a>充血模型

2021-11-18 13:14:08

DDD聚合代碼

2022-07-17 07:37:29

微服務(wù)DDD工程化落地

2020-09-02 08:12:05

CodeDDD代碼

2025-01-26 10:10:30

2024-11-27 15:33:17

軟件架構(gòu)DDD

2023-02-20 14:44:22

DDD領(lǐng)域模型

2022-10-08 09:18:19

架構(gòu)模型

2022-02-10 10:28:34

數(shù)據(jù)庫方案實踐

2023-02-15 13:50:58

DDD戰(zhàn)略設(shè)計

2021-05-20 08:51:33

設(shè)計驅(qū)動數(shù)據(jù)庫

2015-06-30 11:41:23

物聯(lián)網(wǎng)

2022-08-29 09:14:01

戰(zhàn)略設(shè)計核心域支撐域

2022-03-10 13:11:11

DDD領(lǐng)域驅(qū)動設(shè)計

2021-09-08 09:22:23

領(lǐng)域驅(qū)動設(shè)計

2022-09-06 07:00:35

CR代碼

2023-09-01 07:25:39

領(lǐng)域驅(qū)動設(shè)計DDD

2017-01-13 10:51:13

RPC模型解析

2024-11-08 08:37:25

2014-09-26 10:00:25

驅(qū)動設(shè)計DDD領(lǐng)域
點贊
收藏

51CTO技術(shù)棧公眾號