日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

《实现领域驱动设计》读书笔记

發(fā)布時(shí)間:2023/12/10 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《实现领域驱动设计》读书笔记 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

大家好,我是烤鴨:
????《實(shí)現(xiàn)領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)》,讀書筆記,貼個(gè)封面,要不不知道是哪本。

了解概念

剛開始接觸DDD,肯定懵逼,很多名詞,一點(diǎn)點(diǎn)看下。

領(lǐng)域:帶有業(yè)務(wù)屬性的范圍,比如搞直播業(yè)務(wù),那直播就是一個(gè)領(lǐng)域。領(lǐng)域里又分核心域和子域。

可以看個(gè)電商系統(tǒng)的領(lǐng)域圖。

限界上下文:用于承接不同子域。

上下文映射圖:限界上下文關(guān)系圖。

六邊形架構(gòu):又稱端口適配器,水平的分層架構(gòu),犧牲一部分性能,更好的防止邏輯層外漏。

CQRS:Command Query Responsibility Segregation,讀寫分離。這個(gè)讀寫分離跟我們想的還有點(diǎn)不一樣,

領(lǐng)域事件內(nèi)的讀庫(kù)和寫庫(kù)的數(shù)據(jù)同步是基于領(lǐng)域事件的,比如寫mysql,讀的時(shí)候讀es,這時(shí)候就需要領(lǐng)域事件觸發(fā)mysql到es的同步。

章節(jié)回顧

當(dāng)我們開始一個(gè)業(yè)務(wù),需要考慮領(lǐng)域邊界,不只是業(yè)務(wù)層面的,還有技術(shù)層面的。核心域的創(chuàng)建,子域的分類,實(shí)體和值對(duì)象的建立等等。

限界上下文的建模需要考慮不同子域,比如不同流程,需要的對(duì)象屬性不同,上下文建模的對(duì)象就可能意義不同。(比如上面的電商系統(tǒng),訂單子域和發(fā)票子域、庫(kù)存子域的限界上下文對(duì)象肯定是不同的)

幾種架構(gòu)設(shè)計(jì):

  • 分層架構(gòu):用戶接口層—>應(yīng)用層—>領(lǐng)域?qū)印?gt;基礎(chǔ)設(shè)施層。依賴倒置原則,高、低層模塊都依賴于抽象。

  • 六邊形架構(gòu):外界通過適配器和內(nèi)部交互。

  • SOA:Service-Oriented Architecture,面向服務(wù)架構(gòu)。這個(gè)服務(wù)可能是根據(jù)業(yè)務(wù)或者技術(shù)來拆分的,并不是服務(wù)越多越好,需要考慮限界上下文。技術(shù)架構(gòu)不能影響業(yè)務(wù)領(lǐng)域模型。

  • REST: URI決定訪問的資源,是無狀態(tài)通信。利于解耦,需要單獨(dú)涉及上下文。

  • CQRS:讀寫分離。查詢模型和DTO的建立。寫模型執(zhí)行業(yè)務(wù)行為發(fā)布領(lǐng)域事件,事件訂閱器更新查詢模型。
    (比如查詢?cè)趀s或者redis,在收到寫事件時(shí),同時(shí)更新es或者redis)

  • 事件驅(qū)動(dòng):類似linux中的管道和過濾器,采用分治的方式解決大型問題。定義實(shí)體和領(lǐng)域事件(業(yè)務(wù)維度的操作),跟蹤器監(jiān)聽長(zhǎng)時(shí)處理過程(分布式的并行處理模式),考慮冪等,監(jiān)聽超時(shí)可以主動(dòng)定時(shí)查詢。事件源(記錄領(lǐng)域模型的操作)和快照(對(duì)一系列事件后生成的,類似redis的AOF恢復(fù)時(shí)對(duì)命令整合)

  • 數(shù)據(jù)網(wǎng)織,緩存的建立和層級(jí)維護(hù),通過客戶端監(jiān)聽保證緩存中的查詢模型更新,長(zhǎng)時(shí)處理過程不一定是事件驅(qū)動(dòng)。

實(shí)體

實(shí)體的建立,實(shí)體具有唯一標(biāo)識(shí)和可變性,值對(duì)象沒有。普通的數(shù)據(jù)模型(CURD模型)是不會(huì)創(chuàng)建出好的業(yè)務(wù)模型,數(shù)據(jù)模型需要轉(zhuǎn)換為實(shí)體模型。

值對(duì)象可以用于存放實(shí)體的唯一標(biāo)識(shí)。唯一標(biāo)識(shí)可以由用戶傳遞、應(yīng)用生成、持久化生成或者上下文傳遞。

委派標(biāo)識(shí),可以做唯一索引。層超類型(通過繼承的方式,隱藏主鍵)在聚合層可以做樂觀鎖。

值對(duì)象

值對(duì)象的常見例子,比如 數(shù)字、文本、日期,或者復(fù)雜的對(duì)象。

在值對(duì)象中引用實(shí)體,應(yīng)該考慮不變性、表達(dá)性和方便性。否則,一旦實(shí)體改變屬性,會(huì)破壞值對(duì)象的不變性。

使用值對(duì)象可以縮小集成化,簡(jiǎn)化職責(zé)假設(shè)。協(xié)作上下文中的防腐層(身份校驗(yàn)和參數(shù)轉(zhuǎn)化)、開放主機(jī)服務(wù)(三方調(diào)用)使用相同的值對(duì)象會(huì)簡(jiǎn)單很多。

測(cè)試用例也可以使用值對(duì)象,使用斷言。

值對(duì)象的備份和相等性驗(yàn)證。(通過copy的方式,生成新的值對(duì)象,并且驗(yàn)證兩個(gè)相等性)。

ORM和值對(duì)象,數(shù)據(jù)庫(kù)直接保存值對(duì)象,值對(duì)象的每一個(gè)屬性對(duì)應(yīng)一列。多個(gè)值對(duì)象ORM的情況不考慮。

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

領(lǐng)域服務(wù)主要是處理業(yè)務(wù)邏輯的,將領(lǐng)域?qū)ο筠D(zhuǎn)換成值對(duì)象。只有在必要時(shí)建模領(lǐng)域服務(wù)。(遵循單一職責(zé)原則)

創(chuàng)建獨(dú)立接口,如果使用依賴倒置或者六邊形架構(gòu),有些實(shí)現(xiàn)類可能在領(lǐng)域模型之外。

領(lǐng)域事件

無論是外部還是內(nèi)部系統(tǒng),通過領(lǐng)域事件維護(hù)事件的一致性,可以消除兩段式事務(wù),還可以支持聚合。(最常見的就是mq)

通過領(lǐng)域服務(wù)創(chuàng)建事件,添加到資源庫(kù),通過消息設(shè)施進(jìn)行發(fā)布,需要有唯一標(biāo)識(shí),可以做冪等。

基于 發(fā)布-訂閱,可以解耦,允許短暫的數(shù)據(jù)不一致,最終一致。同時(shí)作為消費(fèi)方,在單個(gè)事務(wù)中只修改單個(gè)聚合實(shí)例。

事件可以用隊(duì)列存儲(chǔ),利于檢查歷史記錄,聚合操作。(需要關(guān)注事件順序)

以rest方式發(fā)布事件(多個(gè)消費(fèi)方拉取同一個(gè)URI時(shí)),需要考慮順序和對(duì)發(fā)布事件的跟蹤(存檔日志)。

消息的重復(fù)發(fā)送需要做冪等處理。

模塊

maven項(xiàng)目中的module,設(shè)計(jì)的要和領(lǐng)域概念保持一致,松耦合,杜絕循環(huán)依賴。

模塊名的命名規(guī)范,比如 com.saasovation.agilepm.domain.service/model

優(yōu)先考慮組織結(jié)構(gòu),而不是松耦合性。先考慮模塊,后考慮限界上下文。

聚合

實(shí)體和值對(duì)象在邊界內(nèi)組成聚合。CQS查詢將大聚合分為幾個(gè)小聚合。

聚合邊界內(nèi)一套不變的業(yè)務(wù)規(guī)則維持一致性,類似持久化機(jī)制中的事務(wù)。

小聚合在性能和可伸縮性上有好處,還能減少事務(wù)的提交沖突。

通過唯一標(biāo)識(shí)引用其他聚合。不能在同一事務(wù)中修改多個(gè)聚合,需要考慮事務(wù)失敗的情況。

如果聚合特別多,在web層處理復(fù)雜,需要考慮聚合中的標(biāo)識(shí)引用或者實(shí)體引用。

發(fā)布-訂閱或者觀察者模式,事務(wù)非原子性,通過聚合達(dá)到一致性。(分布式場(chǎng)景需要考慮并發(fā))

創(chuàng)建具有唯一標(biāo)識(shí)的根實(shí)體,優(yōu)先使用值對(duì)象。

使用"迪米特法則"(強(qiáng)調(diào)"最小知識(shí)"原則)和"告訴而非詢問法則(一個(gè)對(duì)象不應(yīng)該被告知如何執(zhí)行操作)。

數(shù)據(jù)庫(kù)層面加版本號(hào)的樂觀鎖方式限制并發(fā)。

避免將資源庫(kù)和領(lǐng)域服務(wù)注入到聚合層。

工廠

工廠相關(guān)的設(shè)計(jì)模式有抽象工廠、工廠方法、建造者。

領(lǐng)域模型中的工廠只負(fù)責(zé)創(chuàng)建對(duì)象,沒有其他權(quán)責(zé)。

聚合根中的工廠方法用于創(chuàng)建聚合對(duì)象,減輕客戶端創(chuàng)建聚合實(shí)例時(shí)的負(fù)擔(dān),確保所有實(shí)例都在正確的狀態(tài)。

領(lǐng)域服務(wù)中的工廠主要集中在防腐層、發(fā)布語(yǔ)言和開放主機(jī)服務(wù)的集成上。限界上下文的交互中,將領(lǐng)域內(nèi)的對(duì)象轉(zhuǎn)換為上下文中的對(duì)象。這里的領(lǐng)域服務(wù)其實(shí)扮演的是工廠的角色。

資源庫(kù)

資源庫(kù)是對(duì)聚合實(shí)例的一種持久化,代替DTO。

以集合資源庫(kù)為例,需要考慮順序和冪等。資源庫(kù)和數(shù)據(jù)庫(kù)層面數(shù)據(jù)一致性,采用雙寫保險(xiǎn)。

資源庫(kù)的正確用法,要么只讀,要么讀取是為了修改。

使用Nosql對(duì)資源庫(kù)進(jìn)行持久化,需要考慮數(shù)據(jù)結(jié)構(gòu)。

有時(shí)候需要返回大聚合對(duì)象中的子聚合,可以考慮直接從資源庫(kù)中獲取,返回值對(duì)象。如果用例優(yōu)化查詢,還是需要多個(gè)查詢方法,可能是邊界劃分錯(cuò)誤,考慮使用CQRS。

領(lǐng)域?qū)硬豢紤]事務(wù),事務(wù)加在業(yè)務(wù)層,不要過多的在領(lǐng)域模型上使用事務(wù)。測(cè)試環(huán)境測(cè)試沒問題,生產(chǎn)環(huán)境有可能會(huì)有并發(fā)問題。

使用單個(gè)資源庫(kù)保存和獲取層級(jí)中不同的聚合類型,客戶端無需知道他們使用的實(shí)際類型,體現(xiàn)了里氏替換原則。

資源庫(kù)和DAO不同。DAO是從數(shù)據(jù)庫(kù)表角度來看待問題,提供CURD操作。可以將資源庫(kù)當(dāng)做DAO來看,不過設(shè)計(jì)資源庫(kù)時(shí),應(yīng)該面向集合,而不是面向數(shù)據(jù)。

集成限界上下文

多種方式,一種是:soap、http(xml)、rpc,另一種是消息隊(duì)列(發(fā)布—訂閱),第三種是 restful。

分布式系統(tǒng)本身是有風(fēng)險(xiǎn)的,兩個(gè)系統(tǒng)間的數(shù)據(jù)交互還需要考慮版本更新,數(shù)據(jù)結(jié)構(gòu)改變等等。比如消息消費(fèi)方的端口適配器應(yīng)該將自己內(nèi)部的領(lǐng)域模型和外部的領(lǐng)域模型隔離開,同時(shí)傳入的數(shù)據(jù)必須遵循本地限界上下文的類型定義。

無論那種方式(http、rpc) 部署接口/類,還是定義媒體類型契約(mq),看業(yè)務(wù)場(chǎng)景和項(xiàng)目階段。但從產(chǎn)品角度,使用低耦合的媒體類型更好。

開放主機(jī)服務(wù):當(dāng)一個(gè)限界上下文以URI的方式提供了大量REST資源時(shí),可稱其為開放主機(jī)服務(wù)。

比如下面這個(gè)Rest的URI,判斷某個(gè)用戶角色,返回200就是有該角色,其他的就沒有。

/tenants/{tenantId}/users/{username}/inRole/{role}

上面這個(gè)內(nèi)部實(shí)現(xiàn)是六邊形架構(gòu)的適配器,再調(diào)用應(yīng)用服務(wù)和領(lǐng)域服務(wù)。

防腐層是上下文協(xié)作交互的方式,數(shù)據(jù)轉(zhuǎn)換的作用,防腐層通常有一個(gè)特定的適配器。

利用消息隊(duì)列傳遞上下文需要考慮順序和冪等,最小化或者消除不同限界上下文之間的信息復(fù)制。

長(zhǎng)時(shí)處理過程指的是完全走完一個(gè)流程,比如發(fā)布兩個(gè)對(duì)象,經(jīng)過了哪些過濾器。其中有跟蹤器,目的是監(jiān)聽哪些過期,哪些可以重試。

跟蹤器放到本地上下文,而不是協(xié)作上下文。

針對(duì)MQ超時(shí)重試,使用否定應(yīng)答和消息重發(fā)結(jié)合的方式。

消息集群宕機(jī)恢復(fù)后,服務(wù)監(jiān)聽器可以自動(dòng)重連。

應(yīng)用程序

應(yīng)用程序通過用戶界面向外界展示領(lǐng)域模型的概念,并且允許用戶在模型上執(zhí)行各種操作。

DTO(Data Transfer Object) 數(shù)據(jù)傳輸對(duì)象,將包含需要的所有屬性值,從資源庫(kù)獲取再映射。缺點(diǎn)是DTO 可能暴露領(lǐng)域內(nèi)部數(shù)據(jù)結(jié)構(gòu),應(yīng)該考慮解耦。

調(diào)停者模式,即雙分派和回調(diào)。客戶端實(shí)現(xiàn)調(diào)停者接口,把對(duì)象引用傳給聚合,聚合通過調(diào)停者發(fā)布自身狀態(tài)。

DPO(Domain Payload Object) 領(lǐng)域負(fù)載對(duì)象,包含了整個(gè)聚合實(shí)例的引用,而不是單獨(dú)屬性。也使用調(diào)停者解耦,避免延遲加載的問題,強(qiáng)制手動(dòng)訪問所有延遲加載的屬性。

VO(View Object) 客戶端展示層,通過適配器將DTO轉(zhuǎn)換。

優(yōu)化資源庫(kù)查詢,可以直接返回值對(duì)象。

應(yīng)用服務(wù)不等于領(lǐng)域服務(wù),所有的業(yè)務(wù)領(lǐng)域邏輯放到領(lǐng)域模型,不管是聚合、值對(duì)象或者領(lǐng)域服務(wù),應(yīng)用服務(wù)是很薄的一層,只使用他們協(xié)調(diào)對(duì)模型的任務(wù)操作。

一種方式是多應(yīng)用層,每個(gè)用戶界面組件都提供所有的應(yīng)用層,此時(shí)用戶界面組件將向領(lǐng)域模型靠近。結(jié)果有點(diǎn)像貧血領(lǐng)域?qū)ο蟆?/p>

領(lǐng)域模型需要考慮模塊包的命名,比如:

com.consumerhive.productreviews.domain.model.product

基礎(chǔ)設(shè)施的職責(zé)是為應(yīng)用程序的其他部分提供技術(shù)支持。(比如自己初始化bean,注入spring容器)

總結(jié)

盡管盡量減少章節(jié)回顧的內(nèi)容,還是有很多不好理解的點(diǎn)。

DDD的概念推出很久了,不過感覺用的人不多,會(huì)用的人就更少了。

大家一直強(qiáng)調(diào)微服務(wù),模塊、實(shí)體、nosql、mq,這些跟DDD都有交集,不過建模真的考慮過DDD么,是貧血領(lǐng)域?qū)ο筮€是應(yīng)用服務(wù)當(dāng)做領(lǐng)域服務(wù)。

領(lǐng)域模型的建立必須是懂得業(yè)務(wù)的人參與,純技術(shù)是沒辦法建模的。

下一篇想結(jié)合實(shí)戰(zhàn),寫一下DDD在實(shí)際業(yè)務(wù)中的使用。

總結(jié)

以上是生活随笔為你收集整理的《实现领域驱动设计》读书笔记的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。