成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

如何在DDD中建立領(lǐng)域模型

開發(fā)
前面我們討論了DDD的戰(zhàn)略設(shè)計(jì)和戰(zhàn)術(shù)設(shè)計(jì)。在本文中我們將繼續(xù)探討領(lǐng)域模型。

作者 | TWInsights

在前文《??當(dāng)我們談?wù)揇DD時(shí)我們?cè)谡務(wù)撌裁??》中我們討論了DDD的戰(zhàn)略設(shè)計(jì)和戰(zhàn)術(shù)設(shè)計(jì)。在本文中我們將繼續(xù)探討領(lǐng)域模型。

用領(lǐng)域模型表達(dá)領(lǐng)域概念

在實(shí)際項(xiàng)目中,模型設(shè)計(jì)者往往過早陷入具體構(gòu)造塊類型的識(shí)別,比如實(shí)體、聚合、領(lǐng)域服務(wù),而忽略了領(lǐng)域模型表達(dá)領(lǐng)域概念的目的。我們應(yīng)該基于領(lǐng)域概念設(shè)計(jì)領(lǐng)域模型,然后再采用合適的模式降低領(lǐng)域模型的復(fù)雜度,進(jìn)一步增加領(lǐng)域模型的表達(dá)能力。

領(lǐng)域模型的作用,一方面是關(guān)聯(lián)代碼實(shí)現(xiàn),一方面是關(guān)聯(lián)通用語言。我們對(duì)于模型和實(shí)現(xiàn)的關(guān)聯(lián)輕車熟路,但是對(duì)于語言和模型關(guān)聯(lián)往往有待提升。在溝通中刻意使用通用語言可以幫助我們驗(yàn)證模型的合理性。

我們以一個(gè)題目為例,方便后續(xù)討論。

活動(dòng)平臺(tái)提供用戶參與活動(dòng)得到獎(jiǎng)品的功能,吸引用戶及潛在用戶參與,以達(dá)到拉新、促活、引流的目的。

運(yùn)營(yíng)人員可以創(chuàng)建和修改活動(dòng),活動(dòng)的配置內(nèi)容包括活動(dòng)名稱、活動(dòng)介紹、活動(dòng)開放的開始時(shí)間和結(jié)束時(shí)間、參與資格、權(quán)益。

用戶可以看到活動(dòng)列表,在活動(dòng)開放的時(shí)間段內(nèi)進(jìn)入活動(dòng)頁(yè)面看到活動(dòng)介紹。用戶在活動(dòng)頁(yè)面領(lǐng)取權(quán)益,經(jīng)判斷符合資格的用戶就會(huì)獲得一份獎(jiǎng)品。權(quán)益可能是信用卡積分,也可能是優(yōu)惠券。

參與資格可能是:一天內(nèi)注冊(cè)的用戶、VIP用戶、當(dāng)月生日的用戶等。客戶希望系統(tǒng)可以方便擴(kuò)展支持靈活的資格類型,以支持多樣的活動(dòng)形式。

對(duì)于一個(gè)活動(dòng),一個(gè)用戶只能參加一次。

建立模型

第一步是根據(jù)需求分析模型。

我們可以找到以下概念:活動(dòng)、參與資格、權(quán)益。其中參與資格是擴(kuò)展點(diǎn)。

對(duì)于需求「一個(gè)用戶只能參加一次活動(dòng)的」,需要記錄用戶是否參與過活動(dòng),所以需要「活動(dòng)參與記錄」的概念。

參與活動(dòng)的結(jié)果可能有2種:符合參與資格則返回權(quán)益,不符合則返回「不符合」。所以我們用了Optional<權(quán)益>類型。

我們到這里只識(shí)別了各種名詞,需要走查用例,尋找缺失的概念:

  • 用例1,運(yùn)營(yíng)人員可以創(chuàng)建并修改活動(dòng)
  • 用例2,用戶可以參與活動(dòng)并獲得權(quán)益

對(duì)于用例1,創(chuàng)建和修改活動(dòng),目前模型已經(jīng)滿足了需求。

對(duì)于用例2,這里有一個(gè)模型之外的規(guī)則:「一個(gè)用戶只能參加一次活動(dòng)」。這是所有活動(dòng)都需要遵守的規(guī)則,我們將其稱為「活動(dòng)通用規(guī)則」。

雖然只是一個(gè)很簡(jiǎn)單的邏輯,但是提取「活動(dòng)通用規(guī)則」這個(gè)概念非常有用。如果沒有這個(gè)概念,那么每次去描述這個(gè)概念,只能用「一個(gè)用戶只能參加一次活動(dòng)的規(guī)則」去表示,非常繁瑣;也讓概念沒有安身之地,容易被隨便放到萬能的Service中。

我們將其加入領(lǐng)域模型。

PS:這里故意省略了參與資格的實(shí)現(xiàn)。

我們沒有把「活動(dòng)通用規(guī)則」放到活動(dòng)概念里,一部分原因是這個(gè)判斷邏輯不需要具體活動(dòng)的信息。

使用通用語言驗(yàn)證模型

有了領(lǐng)域模型,就有了通用語言。使用通用語言重新描述需求,并盡量在溝通中使用通用語言。

運(yùn)營(yíng)人員可以創(chuàng)建和修改活動(dòng),活動(dòng)的配置內(nèi)容包括活動(dòng)名稱、活動(dòng)介紹、活動(dòng)開放的開始時(shí)間和結(jié)束時(shí)間時(shí)間段、參與資格、權(quán)益。

用戶可以看到活動(dòng)列表,在活動(dòng)開放的時(shí)間段內(nèi)進(jìn)入活動(dòng)頁(yè)面看到活動(dòng)介紹。用戶在活動(dòng)頁(yè)面領(lǐng)取權(quán)益,經(jīng)判斷符合資格參與資格的用戶就會(huì)獲得一份獎(jiǎng)品權(quán)益。權(quán)益可能是信用卡積分,也可能是優(yōu)惠券。

參與資格可能是:一天內(nèi)注冊(cè)的用戶、VIP用戶、當(dāng)月生日的用戶等。客戶希望系統(tǒng)可以方便擴(kuò)展支持靈活的資格類型,以支持多樣的活動(dòng)形式。

同時(shí)有「活動(dòng)通用規(guī)則」:對(duì)于一個(gè)活動(dòng),一個(gè)用戶只能參加一次。

這里去掉了「開始時(shí)間」、「資格」、「獎(jiǎng)品」等模糊不清晰的描述。使用基于領(lǐng)域模型的語言,讓需求描述清晰沒有歧義。

到目前為止,主要的領(lǐng)域模型都已經(jīng)分析出來。所有的模型都對(duì)應(yīng)明確的領(lǐng)域概念,不多也不少。

識(shí)別構(gòu)造塊類型

在分析了領(lǐng)域模型后,我們?cè)賮矸治鰳?gòu)造塊類型。

我們通過是否有狀態(tài)來做區(qū)分。

首先識(shí)別有狀態(tài)的對(duì)象:活動(dòng)、各種參與資格、權(quán)益、活動(dòng)參與記錄、用戶。一般有狀態(tài)的對(duì)象都是事物,對(duì)應(yīng)的構(gòu)造塊類型也就是實(shí)體或者值對(duì)象。

其次判斷其狀態(tài)是否會(huì)改變:

  • 活動(dòng)會(huì)被修改,所以狀態(tài)會(huì)被改變;
  • 參與資格會(huì)被修改,但是參與資格從屬于活動(dòng),修改后可以直接使用新的對(duì)象替換舊的,所以可以設(shè)計(jì)成狀態(tài)不變;
  • 權(quán)益和參與資格一樣,也可以設(shè)計(jì)成狀態(tài)不變;
  • 活動(dòng)參與記錄,狀態(tài)可能發(fā)生變化;
  • 用戶在這個(gè)模型中只是臨時(shí)存在,狀態(tài)不會(huì)變化。

狀態(tài)會(huì)改變的是實(shí)體,包括活動(dòng)和活動(dòng)參與記錄;狀態(tài)不變的就是值對(duì)象,包括參與資格、權(quán)益和用戶。

最后剩下的就是無狀態(tài)的對(duì)象:活動(dòng)通用規(guī)則。對(duì)應(yīng)的構(gòu)造塊類型是領(lǐng)域服務(wù)。

這里的無狀態(tài)對(duì)象大都可以轉(zhuǎn)化成有狀態(tài)的對(duì)象,例如活動(dòng)通用規(guī)則,可以將方法參數(shù)的Optional<活動(dòng)參與記錄>變成成員變量。只是這里我們選擇了無狀態(tài)的設(shè)計(jì)方法。

由于領(lǐng)域服務(wù)沒有狀態(tài),所以可以在應(yīng)用啟動(dòng)時(shí)就創(chuàng)建出來,也可以在使用時(shí)才創(chuàng)建。

經(jīng)過分析,我們的領(lǐng)域模型都有了類型。

設(shè)計(jì)聚合

首先識(shí)別生命周期長(zhǎng)的領(lǐng)域?qū)ο螅涸谝粋€(gè)操作中被創(chuàng)建出來,操作結(jié)束后仍會(huì)被其他操作使用的對(duì)象。活動(dòng)、參與資格、權(quán)益和活動(dòng)參與記錄都是生命周期長(zhǎng)的對(duì)象。

其他有狀態(tài)的對(duì)象都是臨時(shí)對(duì)象:在一個(gè)操作中被創(chuàng)建出來,操作結(jié)束后就不會(huì)再被使用。模型中的用戶,在一次操作中從其他服務(wù)獲取,使用后即被丟棄。

這里我們總結(jié)下各構(gòu)造塊類型的特點(diǎn):

實(shí)體

值對(duì)象

領(lǐng)域服務(wù)

是否有狀態(tài)

有且狀態(tài)可變

有且狀態(tài)不可變


生命周期

長(zhǎng)

長(zhǎng)或者短

長(zhǎng)短均可

在生命周期的長(zhǎng)的對(duì)象中,我們要設(shè)計(jì)聚合。聚合作為操作單元,主要解決以下幾個(gè)問題:

  • 整個(gè)模型往往龐大復(fù)雜,為了降低知識(shí)負(fù)載,需要將其分解成多個(gè)小且簡(jiǎn)單的模型,劃分清晰的邊界
  • 部分模型對(duì)象之間存在一致性規(guī)則,例如需要被一起刪除,所以需要放在一個(gè)操作中
  • 多個(gè)用戶可能會(huì)并發(fā)操作模型,為了避免相互干擾,需要讓操作單元盡可能小
  • 對(duì)于操作單元,需要將其頻繁加載到內(nèi)存中,如果單元過大,往往不能滿足性能要求

根據(jù)對(duì)業(yè)務(wù)的了解,活動(dòng)及參與資格、權(quán)益都是一起被創(chuàng)建和修改,可以放在一個(gè)聚合里;活動(dòng)和活動(dòng)參與記錄之間沒有一致性規(guī)則,可以分開;因?yàn)榛顒?dòng)參與記錄數(shù)量會(huì)很多,如果和活動(dòng)在一個(gè)聚合中,會(huì)降低性能。

所以我們將活動(dòng)、參與資格、權(quán)益設(shè)計(jì)成一個(gè)聚合,而活動(dòng)參與記錄作為一個(gè)單獨(dú)的聚合。而活動(dòng)和活動(dòng)參與記錄分別作為這兩個(gè)聚合的聚合根。對(duì)應(yīng)的,聚合都會(huì)配備其專屬的Repository。

同時(shí)加上遍歷方向箭頭。由于活動(dòng)是聚合根,從活動(dòng)可以遍歷到聚合內(nèi)部的參與資格和權(quán)益。另外查詢活動(dòng)參與記錄,可以通過其Repository,所以沒有活動(dòng)到活動(dòng)參與記錄的箭頭。

由于我們將活動(dòng)和活動(dòng)參與記錄之間劃分成不同聚合,那他們之間的關(guān)聯(lián)將使用聚合的ID來關(guān)聯(lián),而不是聚合本身。

PS:如果使用了關(guān)聯(lián)對(duì)象,遍歷方向也可以是從活動(dòng)到活動(dòng)參與記錄。

如何使用領(lǐng)域模型

領(lǐng)域模型已經(jīng)建立完畢,我們來看如何使用領(lǐng)域模型以滿足用例。

運(yùn)營(yíng)人員創(chuàng)建活動(dòng)基本信息及其關(guān)聯(lián)的參與資格和權(quán)益。領(lǐng)域模型的客戶(一般來說是應(yīng)用服務(wù)),使用運(yùn)營(yíng)人員輸入的參數(shù)構(gòu)造出活動(dòng)對(duì)象,再利用Repository將其保存。

運(yùn)營(yíng)人員修改活動(dòng)。應(yīng)用服務(wù)利用Repository獲取需要修改的活動(dòng),再根據(jù)運(yùn)營(yíng)人員提供的參數(shù)修改活動(dòng),最后利用Repository保存活動(dòng)對(duì)象。

用戶參與活動(dòng)。應(yīng)用服務(wù):

  1. 使用活動(dòng)通用規(guī)則判斷用戶是否可以參加。由于活動(dòng)通用規(guī)則需要用到活動(dòng)參與記錄,因此應(yīng)用服務(wù)會(huì)使用Repository獲取活動(dòng)參與記錄;
  2. 如果可以參加,則執(zhí)行活動(dòng)的參與活動(dòng)方法獲得結(jié)果。這需要利用Repository獲取用戶參與的活動(dòng),并構(gòu)造用戶對(duì)象(可能需要調(diào)用用戶服務(wù)獲取用戶信息,但是領(lǐng)域?qū)硬⒉魂P(guān)心這些邏輯);
  3. 如果結(jié)果是獲得權(quán)益,則創(chuàng)建活動(dòng)參與記錄,并利用Repository保存。

考慮到并發(fā)情況,應(yīng)用服務(wù)可以在第1步前加鎖,并在第3步后釋放鎖。

再次思考

(1) 配置和參與活動(dòng)可否是兩個(gè)模型?

在實(shí)現(xiàn)運(yùn)營(yíng)人員配置活動(dòng)的用例過程中,我們會(huì)發(fā)現(xiàn)可能找到了一個(gè)隱藏的領(lǐng)域概念,將輸入的參數(shù)轉(zhuǎn)換成領(lǐng)域模型的邏輯有些枯燥和復(fù)雜,同樣將領(lǐng)域模型和數(shù)據(jù)庫(kù)的數(shù)據(jù)模型之間轉(zhuǎn)換也如此。輸入?yún)?shù)和數(shù)據(jù)模型都是只是扁平的數(shù)據(jù)數(shù)據(jù),沒有繼承結(jié)構(gòu)。如果使用另外一種面向數(shù)據(jù)的模型,也許這些用例實(shí)現(xiàn)起來會(huì)簡(jiǎn)單得多。

每個(gè)模型都是為了解決某個(gè)問題。這里運(yùn)營(yíng)人員配置和用戶參與活動(dòng)是不同的問題,如果用一個(gè)模型來解決這兩個(gè)問題,可能會(huì)有些吃力。那么干脆設(shè)計(jì)成兩個(gè)模型,使用限界上下文的概念將這兩個(gè)模型限定在各自的上下文中,也許更加合理。兩個(gè)模型可以共享同一份數(shù)據(jù)庫(kù)數(shù)據(jù),并加上一段(非領(lǐng)域?qū)拥模┻壿嬘糜谀P椭g的轉(zhuǎn)換。

這實(shí)際上是一種配置-使用模式。在配置階段,注重配置類型和參數(shù)、審批等;在使用階段,注重邏輯計(jì)算和性能。

(2) 活動(dòng)參與記錄是否可以建模成領(lǐng)域事件?

活動(dòng)參與記錄實(shí)際上是不可變的,可以將其設(shè)計(jì)為領(lǐng)域事件。

(3) 用戶參與活動(dòng)的用例里,邏輯復(fù)雜,有泄漏領(lǐng)域概念的嫌疑?

如果發(fā)現(xiàn)應(yīng)用服務(wù)里邏輯變得復(fù)雜,可能意味著我們找到了一個(gè)隱藏的領(lǐng)域概念。我們可以定義一個(gè)「用戶參與活動(dòng)邏輯」的概念:如果用戶通過了活動(dòng)通用規(guī)則的判斷,則可以參與活動(dòng)。將其加入模型和通用語言中,在溝通中驗(yàn)證此概念是否合理。

總結(jié)

很多項(xiàng)目雖然也使用了以領(lǐng)域模型為中心的架構(gòu),但是設(shè)計(jì)者仍然是數(shù)據(jù)模型/貧血領(lǐng)域模型的思考方式,把大量領(lǐng)域邏輯放置在了萬能的Service中,讓領(lǐng)域概念隱藏在了冗長(zhǎng)的過程代碼中,無法享受到DDD帶來的收益。

最后總結(jié)下本文想要強(qiáng)調(diào)的要點(diǎn):

  • 領(lǐng)域模型和領(lǐng)域概念一一對(duì)應(yīng)
  • 領(lǐng)域模型和實(shí)現(xiàn)關(guān)聯(lián),也和通用語言關(guān)聯(lián)。刻意使用通用語言溝通以驗(yàn)證模型是否合理
  • 演示了一種設(shè)計(jì)領(lǐng)域模型的步驟
  • 構(gòu)造塊類型不是最重要的,領(lǐng)域模型本身更加重要
  • 更多的使用可以表達(dá)業(yè)務(wù)含義的值對(duì)象和臨時(shí)值對(duì)象
  • 聚合是一種設(shè)計(jì),需要方法權(quán)衡
  • 使用Repository、Factory獲取和創(chuàng)建領(lǐng)域模型是應(yīng)用層的職責(zé),領(lǐng)域?qū)討?yīng)該關(guān)注在表達(dá)領(lǐng)域概念
責(zé)任編輯:趙寧寧 來源: Thoughtworks洞見
相關(guān)推薦

2017-11-17 05:39:27

DDD建模模型

2025-01-26 10:10:30

2021-08-11 10:38:08

云計(jì)算云計(jì)算環(huán)境云應(yīng)用

2019-08-07 11:15:04

安全 IT部門技術(shù)

2020-10-28 08:08:39

DevOps

2021-09-17 16:28:22

零信任網(wǎng)絡(luò)防御

2021-09-08 09:22:23

領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)

2011-03-03 10:00:14

ProFTPD建立MySQL

2020-09-02 08:12:05

CodeDDD代碼

2024-09-24 16:27:57

2023-02-19 12:44:07

領(lǐng)域事件DDD

2023-02-26 10:59:51

2014-09-26 10:00:25

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

2017-10-13 15:59:24

iPhone機(jī)器學(xué)習(xí)iOS

2023-02-15 13:50:58

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

2023-04-13 14:53:45

2020-04-06 13:52:45

數(shù)據(jù)倉(cāng)庫(kù)大數(shù)據(jù)平臺(tái)Hadoop

2022-07-17 07:37:29

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

2020-10-27 09:37:43

PyTorchTensorFlow機(jī)器學(xué)習(xí)

2021-05-20 08:51:33

設(shè)計(jì)驅(qū)動(dòng)數(shù)據(jù)庫(kù)
點(diǎn)贊
收藏

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

主站蜘蛛池模板: 三级国产三级在线 | 草草草久久久 | 久久成人精品一区二区三区 | 免费久久精品 | 国产视频第一页 | 国产欧美精品一区二区色综合朱莉 | 视频一区二区在线观看 | 成人天堂噜噜噜 | 欧美一区| 中文字幕在线一区二区三区 | 99久久久99久久国产片鸭王 | 亚洲黄色在线免费观看 | 人人爽人人草 | 最新av在线网址 | 91人人看 | 伊人国产精品 | 亚洲一区二区三区乱码aⅴ 四虎在线视频 | 国产精品久久一区二区三区 | 欧美日韩一区精品 | avhd101在线成人播放 | 久久亚洲国产精品 | 成年人视频在线免费观看 | 成人精品一区二区三区 | 精品国产鲁一鲁一区二区张丽 | 国产精品国产 | 亚洲午夜视频在线观看 | 男人久久天堂 | 久久99国产精一区二区三区 | 国产精品性做久久久久久 | 久久精品免费观看 | 国产精品久久久 | 久久精品一区 | 精品国产一区二区三区日日嗨 | 91亚洲欧美| 日韩av在线免费 | 亚洲天堂中文字幕 | 日本一二三区在线观看 | 欧美三级在线 | 久久精品一 | 综合精品久久久 | 高清人人天天夜夜曰狠狠狠狠 |