淺析領域驅動設計

1.概要

DDD(Domain-driven design,模型驅動設計)是一種軟件設計的指導思想,而非固定的一套公式化開發模板(這樣就會導致網絡上出現各種基于自己或業務上的理解而產出的DDD落地的實現,會讓很想學習的開發者迷茫)。在項目的全生命周期內,所有崗位的人員都基于對業務的相同的理解來展開工作。所有人員站在用戶的角度、業務的角度區思考問題,而不是從一開始就站在技術的角度去思考。

? ? ? ?在項目初期,需要將領域專家引入到團隊中。那什么是領域專家呢?他應該是誰?領域專家是指對業務領域非常熟悉(或在該業務領域耕耘了很多年)。他可以是團隊中的任何人,項目經理、產品經理、架構師等等都可以是領域專家,在需求分析階段大家都需要對需求整體進行評估。團隊需要思考這幾個問題,是否需要使用DDD?現有的團隊人員是否能支撐起DDD?任何技術或者設計都需要整體的評估,而不是一味地去迎合。

? ? ? ?接下來讓我們看看什么是領域驅動設計。

f9a02b64913bf961f507459bd2dc057f.png

1.1需求分析

需求分析的方式有很多,例如:用例法,四色建模法。其目的就是為了去建立領域模型的認知。以上兩種方法可能會有些抽象,在項目前期與客戶溝通過程屬于需求分析層面該如何去做。就需要一種統一的一種規則,需要統一語言。接下來就是介紹Domain Story Telling這個概念(這個概念是由domainstorytelling.org網站提出)。包含下圖的四個部分。

be7b8d234da0a878348dae28768902fe.png

由項目經理或產品經理通過這四種概念對需求進行梳理,通過這種方式可以很清楚直白的表達出業務場景。那么這四個部分各代表什么含義呢?

  • Pictograms and Vocabulary(象形圖和詞匯)

    • 1.Actors(角色),(故事場景的參與者,故事指的是功能點)。

    • 2.WorkObjects(參與者與參與者之間傳遞的內容,或需要呈現的內容稱為工作對象)。

    • 3.Acivities(代表的Actors和WorkObjects之間關系,用線的方式來表示)。

    • 4.Annotations(所有流程的注解)。

基于以上概念畫出來的圖大概是這樣,圖中大致描述的是電商購物的一個流程分析。

a70b6d38801c194f4c39208c053a6f90.png

以商城購物系統為例。

(1)用戶查看商品,向購物網站發送商品列表請求信息。

ba8483a89d6184aaedac492ca047c506.png

(2)購物網站響應商品信息給客戶。

e82d0242206f65cce033dde6a985b2e1.png

(3)用戶選擇商品、購買,發送購買商品請求

b8701f14a5722ebcbe2bccd3f44e3c67.png

(4)購物網站響應訂單信息給客戶。此時訂單是未支付的。

(4.1)用戶拿到訂單信息之后,開始支付。發送支付請求。

60f35d752ec33c869e30ca5562b8c363.png

(5)購物網站根據用戶提供的支付信息,去(銀行系統)對應的銀行賬戶中進行扣款。

(5.1)扣款成功之后,再將扣款成功的訂單信息返回給購物網站。

621dc5023b0ea1f02d81cf3ef4913a02.png

(6)購物網站拿到扣款成功的訂單信息之后,開始通知倉庫管理員準備發貨。(6.1)并且通知用戶,扣款成功購物網站準備發貨了。

320204024b04c7350faca94206629214.png

(7)倉庫管理員拿到貨物之后打包發送給快遞員。

4506dda7303076035ccdeed18d5d3f21.png

(8)快遞員送貨上門給客戶。

8fa96f71fe87c119a08ad1579710ab95.png

基于以上的分析,大家可以清楚的了解到商城購物的整個環節。

1.2領域分析

領域(Domain ) :一個組織做的事情(舉個比較狹隘的例子,阿里這個組織做的事情就是做電商)。

子域

  • 核心域:解決項目核心問題,和組織業務緊密關聯。

  • 支撐域:解決項目的非核心問題,則具有組織特性,但不具有通用性。

  • 通用域:通用特性,沒有組織特性。

  • 關心的業務重點不同,領域的劃分也不同。

d2f4aa793dee1788d62b251c90f963c5.png

項目初期應考慮的是如何領域建模,用業務語言去描述和構建系統。而不是用技術語言,去思考代碼怎么寫。技術是服務于業務的脫離業務談技術或者架構、設計都是空談。

(1)商品瀏覽核心域

(2)選擇購買商品、支付訂單

(3)訂單支付,銀行交互

(4)發貨、倉庫管理

(5)配送

目前我們暫時先把購物到配送整個過程劃分為五個子域,為什么不是四部分?為什么不是三部分?這個沒有明確的標準取決于分析者的當前對業務的理解,站在現有的角度去分析領域邊界。并不是說誰做就會更好,符合當前場景下的分析即可。那么劃分領域的原則是什么呢?原則是業務并不是功能,圍繞的是業務的走向劃分而不是以業務的功能點劃分。

有了領域邊界之后,就開始繪制領域的邊界圖。那么又會引出新的問題,邊界和邊界之間存在什么樣的關系?是如何交互的?

329e5d7f04431c75e2f8e140d69f7d39.png

站在系統的角度從商品的查詢到最終的發貨是一個整體的流程。

(1)查詢商品的邊界和訂單的數據做交互(2)訂單需要跟支付、倉庫做交互(3)倉庫跟物流送貨做交互那么為了讓領域的內聚性更強,會需要去對領域做一個保護。保護手段有三種:防腐層(ACL)、開放主機服務(OHS)、發布語言(PL)。

防腐層(ACL)

通過適配器,橋接模式、外觀模式對于訪問操作的一種保護。查詢商品和訂購商品之間的交互是通過一個接口來實現的。定義這個接口是為了不影響別人是需要做一個處理,這個接口不會因為你的領域類的變化而影響接口的定義,我就不會去關心你的內部實現了只考慮在接口層面怎么去交互。接口的表現形式有很多種,在項目中可以是一個接口,在多個項目中可以是一個協議。例如reset api也是一種接口的實現,OSH/OL相當于就是做兩個根本不在一起的服務進行交互的一種方式。ACL可以理解為它是一種接口(Interface)層面的定義,D和U就是Down和UP用于區分上下級的關系。以查詢商品和訂購商品(訂單)舉例,如果需要做防腐層應該在哪個邊界中去做呢?答案是在查詢商品,因為不管你商品是什么樣的,對于訂單來說查詢商品屬于低層。而對于PL(訂購支付)來說就不是了,訂購支付屬于高層所以訂購商品需要主動去做防腐處理。

1.3 Domain Design

b96e7be5ac874701bcd0a1d394d5a2bc.png

(領域建模工具,推薦使用:StarUML,或微軟的Viso)

BoundedContext(界限上下文)https://thedomaindrivendesign.io/bounded-context/

Aggregate(聚合根)

聚合根相當于領域中的一個大對象,它其實是由多個Entities和多個Value Obiect組成。它是操作具體業務流程中的關鍵點,它會由創建它的方法比如說Factories當然也可以去new。

Entities

Entities是有id的唯一標識的,有狀態的對象。比如說商城中訂單就是這樣一個概念。

Value Obiect

是一個無狀態的值對象,訂單中包含的那些數據可以看作成值對象,例如收貨信息address無論這些字段的數值如何改變都不會影響訂單的狀態而發生改變,只會影響數據不會影響狀態。

Services

在Entities滿足不了需要的情況下,它操作的都是無狀態的數據對象和邏輯。需要先考慮這兩條規則。例如轉賬功能,有AB兩個賬戶,AB都有一個Entities對象,那么誰轉賬給誰呢?如果在Entities做一個轉賬好像又不是那么合理,所以會提出一個轉賬的Services,需要傳遞兩個賬戶的Content來完成轉賬的服務。不能在Entities體現這個業務,這個業務是無狀態的,這個業務不會去影響Entities的狀態只是去做了一個業務邏輯的處理。這種情況下是可以用Services去做的。在DDD中需要弱化Services,大家不要把領域模型花了那么大心思去分析的業務,又大部分通過Services去實現成為了一個數據驅動的開發方式上。所以在做領域設計的時候大家一定要想清楚當時定義的意思和作用。

DomainEvents

因為Entities是有生命周期的且有狀態改變的,它很多業務的一些觸發條件都是因為這些狀態改變而觸發的,所以這個領域事件可以關聯很多業務的執行邏輯。例如:訂單支付完成付款之后,是需要根銀行進行交互的,當銀行將訂單數據返回給商城之后。需要觸發兩個事件,第一個通知用戶,第二個通知倉庫管理員。這兩件事情的完成都是需要基于支付完訂單之后通知給下游的兩個領域。所以我們就需要知道領域事件可以作為領域邊界觸發的一種行為,也可以立即為是解耦的一種方式。如果用領域事件的方式去實現業務那么可以拆分的更細。DomainEvents結合事務的一個分享。分布式事務里的事務消息問題,我們是把一個業務劃分為主次的,這個業務關系是相對的。以銀行扣款支付成功之后觸發兩條業務線為例子,什么是主呢?銀行的消息提醒給你已經支付成功了這個業務,這是一個主業務,那么它的延申業務有兩個(1)通知倉庫管理員去發貨(2)通知用戶支付成功。在實現業務的時,接收銀行返回支付狀態改變的時候去觸發兩個事件給延申業務。站在事務的角度上來說,需要滿足主線的業務事務提交兩個延申的業務,提交之后就不做管理了成功就成功失敗就失敗,主線就是主線延申就是延申。本地事務提交了才會發送事務消息。事務消息發送完成之后,由兩個訂閱者去完成各自的業務邏輯,如果失敗了也可以通過事務消息來做重復的事務補償。

Factories

是為了創建Entities和Aggregate的對象,Aggregate實際上也是一個Entities對象,Aggregate只是一個概念實際對應的還是一個對象。具體的實現是Entities、Value Obiect、Services、DomainEvents、Factories、Repositories。而BoundedContext、Aggregate是抽象的概念。

Repositories

代表的是數據操作的資源和方法。比如說:訂單信息最終還是要落庫的,那么就會涉及到數據庫操作那么就需要一個數據庫操作的對象。讓領域不關心數據的操作。

1.4UML(統一語言)

f30ca723f76ef9bc8b341e541ed6c615.png

(看字面意思就能懂的直接略過...)

組合:兩個類的對象生命周期是關聯的。

聚合:其他業務也可能包含同樣的對象。

1.5 實踐

COLA(COLA是阿里巴巴基于領域模型實現的一套服務端的框架)

2a1ab14c97ea652c07621e76fdb7d57e.png

1.6 Specification introduction(規范介紹)

121a8562bc12b99bdcc794fba059fd49.png

1.7GIT Manager(Git代碼庫版本管理)

5816d34e76b3f3f7f159ada18ab46ec6.png

1.8Test(測試環節)

cbaf0e52d49515ed1b91e3b7b460ab5a.png

單元測試:主要測試的是業務領域模型的邏輯。為什么要測試它呢?因為在做的時候我們的領域是不需要數據的,只要測試通過表示系統的關鍵業務沒有出問題。

性能測試:根據在設計系統的時候,需要設置指標比如系統支撐的最大上限是多少,檢測是否滿足性能指標。性能測試的前提是在一定的資源下去做的,如果不斷的增加服務器數量也是能達到性能指標的。

功能測試:大部分項目中的常見的測試,通過測試用例來驗證功能是否可用。還有集成測試和回歸測試。

2.Ref

https://domainstorytelling.org/#dst-ddd

https://www.wps.de/modeler/index.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/279917.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/279917.shtml
英文地址,請注明出處:http://en.pswp.cn/news/279917.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Delphi實現的透明陰影以及蒙版效果菜單

QQ2010的皮膚控件目前實現了一部分,看到有些軟件的菜單,都有陰影,透明等效果,于是開始重新實現菜單控件,QQ2009版的菜單控件,是自己從TComponent繼承了完全模擬實現的一個菜單,雖然實現了菜單控…

cortana搜索框_如何在Windows 10任務欄上隱藏Cortana搜索框

cortana搜索框One of the most talked about features in the latest version of Windows 10 was the Cortana personal assistant that is integrated directly into the taskbar. But what if you don’t want to waste all that taskbar space? 最新版本的Windows 10中最受…

Kotlin 基礎 - 數據類型

一、Boolean 類型 Boolean 值有兩個值,分別為 true 或 false。多數情況下,Kotlin 中的 Boolean 相當于 Java 中的基本類型 boolean,只有在必要的情況下才會裝箱成為 Java 中的裝箱類型 Boolean。這一切都是交由編譯器來完成,我們無…

全框眼鏡拆卸鏡片方法分享

全框眼鏡拆卸鏡片方法分享http://www.iqiyi.com/w_19ru97p1n9.html 很多直接用手掰就成(眼鏡布) 轉載于:https://www.cnblogs.com/OceanF/p/9288411.html

發送http請求

public static String httpGetSend(String url) {String responseMsg "";HttpClient httpClient new HttpClient();GetMethod getMethod new GetMethod(url);// GET請求try {// http超時5秒httpClient.getHttpConnectionManager().getParams().setConnectionTimeo…

微軟公布Entity Framework 8.0規劃

微軟.NET團隊在博客上公布了有關 Entity Framework Core 8.0(也稱為 EF Core 8 或 EF8)的未來規劃。EF Core 8 是 EF Core 7 之后的下一個版本,這將是一個長期支持版本;計劃于 2023 年 11 月與 .NET 8 同時發布。該公司表示&#…

roku能不能安裝軟件_如何阻止假期更改Roku主題

roku能不能安裝軟件Wondering why your Roku looks…different? Roku occasionally changes the background for its millions of users, something they call a “featured theme.” 想知道為什么您的Roku看起來...不同嗎? Roku偶爾會改變其數百萬用戶的背景&…

助力AIoT,雅觀科技發布空間智能化操作系統

雷鋒網(公眾號:雷鋒網)消息,3月14日,雅觀科技在上海舉辦了“「AI」悟及物 「柔」生萬屋”2019雅觀科技新品發布會,發布了空間智能化操作系統Akeeta、空間智能化柔性服務技術中臺Matrix,以及基于兩者開發的雅觀智慧社區…

HTTP與HTTPS區別(詳細)

轉:http://blog.sina.com.cn/s/blog_6eb3177a0102x66r.html 1、減少http請求(合并文件、合并圖片)2、優化圖片文件,減小其尺寸,特別是縮略圖,一定要按尺寸生成縮略圖然后調用,不要在網頁中用res…

Ajenti-Linux控制面板之自動化運維工具

ajenti http://ajenti.org/ https://github.com/ajenti/ajenti 源碼 http://docs.ajenti.org/en/latest/ http://docs.ajenti.org/en/latest/man/install.html# 安裝部署Fast remote access for every occasion Install once and never google for PuTTY downloads again. An…

MongoDB C# Driver 快速入門

MongoDB的官方C#驅動可以通過這個鏈接得到。鏈接提供了.msi和.zip兩種方式獲取驅動dll文件。C#驅動的基本數據庫連接,增刪改查操作。在使用C#驅動的時候,要在工程中添加"MongoDB.Bson.dll"和"MongoDB.Driver.dll"的引用。同時要在代…

如何在Windows 10的地圖應用程序中獲取離線地圖

If you know you’re going to be using your PC in a location without an Internet connection, and you need access to maps, you can download maps for specific areas in the “Maps” app in Windows 10 and use them offline. 如果您知道要在沒有Internet連接的地方使…

Hive初識(二)

Hive分區Hive組織表到分區。它是將一個表到基于分區列,如日期,城市和部門的值相關方式。使用分區,很容易對數據進行部分查詢。表或分區是細分成桶,以提供額外的結構,可以使用更高效的查詢的數據。桶的工作是基于表的一…

網站計數器 web映射

站點的網站計數器的操作 <% page import"java.math.BigInteger" %> <% page import"java.io.File" %> <% page import"java.util.Scanner" %> <% page import"java.io.FileInputStream" %> <% page import…

XenApp_XenDesktop_7.6實戰篇之八:申請及導入許可證

1. 申請許可證 Citrix XenApp_XenDesktop7.6和XenServer 6.5申請許可證的步驟是一致的&#xff0c;由于之前我已經申請過XenApp_XenDesktop的許可證&#xff0c;本次以XenServer6.5的許可證申請為例。 1.1 在申請試用或購買Citrix產品時&#xff0c;收到相應的郵件&#xff0…

Windows 11的記事本將獲得類似瀏覽器的標簽功能

Windows 11已經向全世界的客戶推出&#xff0c;自從它問世以來已經收到各種有趣的更新。例如&#xff0c;Windows 11的22H2版本&#xff08;操作系統的第一個大更新&#xff09;為文件資源管理器添加了標簽&#xff0c;啟用了任務欄的拖放支持&#xff0c;以及更多。Windows-11…

C#種將String類型轉換成int型

API&#xff1a; 有一點是需要注意的&#xff0c;那就是必須保證該String類型內全為數字&#xff0c;能確保轉換正確&#xff1b; 1.int.Parse(str);2.TryParse(str, out intA);3. Convert.ToInt32(str);以上都可以&#xff0c;其中 1和3 需要try&#xff5b;&#xff5d;異常&…

【本人禿頂程序員】技巧分享丨spring的RestTemplate的妙用,你知道嗎?

←←←←←←←←←←←← 快&#xff01;點關注 為什么要使用RestTemplate&#xff1f; 隨著微服務的廣泛使用&#xff0c;在實際的開發中&#xff0c;客戶端代碼中調用RESTful接口也越來越常見。在系統的遺留代碼中&#xff0c;你可能會看見有一些代碼是使用HttpURLConnectio…

譯?:Top Three Use Cases for Dapr and Kubernetes

有關譯者&#xff1a;陳東海(seachen)&#xff0c;?前就職于騰訊&#xff0c;同時在社區也是?名Dapr Member.導語&#xff1a;在SDLC(Software Development Lifecycle軟件開發?命周期中)&#xff0c;絕?多數CNCF項?都是專注于軟件開發的中后期階段&#xff0c;特別是運維和…

MySQL數據庫的datetime與timestamp

MySQL數據庫中有datetime與timestamp兩種日期時間型數據類型&#xff0c;其中timestamp可以用timestamp(n)來表示年月日時分秒的取值精度&#xff0c;如果n14則完整匹配于datetime的精度&#xff0c;那為什么還需要datetime這種類型呢&#xff1f;我做過試驗&#xff0c;timest…