溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

php中的DDD有什么用

發(fā)布時(shí)間:2021-07-06 17:59:29 來(lái)源:億速云 閱讀:178 作者:chen 欄目:編程語(yǔ)言

本篇內(nèi)容主要講解“php中的DDD有什么用”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“php中的DDD有什么用”吧!

DDD 是什么(首先它不是什么)

DDD 是 Domain Driven Design 的縮寫(xiě),在中文中常被翻譯為領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)。在我們了解 DDD 是什么之前,首先討論下它不是什么。

  • DDD 不是一個(gè)軟件框架。但是基于 DDD 思想的框架是存在的,比如 Axon,它是以 DDD 為指導(dǎo)思想,使用 Java 實(shí)現(xiàn)的一個(gè)微服務(wù)軟件框架。

  • DDD 不是一種軟件設(shè)計(jì)模式。它不是像工廠,單例這樣子的設(shè)計(jì)模式。但是 DDD 思想中提出了諸如資源庫(kù)(Repository)之類的設(shè)計(jì)模式。

  • DDD 不是一種系統(tǒng)架構(gòu)模式。它不是像 MVC 之類的架構(gòu)模式。但是 DDD 思想中提出了諸如事件溯源(Event Souring),讀寫(xiě)隔離(Command Query Responsibility Segregation) 之類的架構(gòu)模式。

那么 DDD 到底是什么

軟件是服務(wù)于人類,為提高人類生產(chǎn)效率而產(chǎn)生的一種工具, 每一個(gè)軟件都服務(wù)于某一個(gè)特定的領(lǐng)域。比如一個(gè) CRM,它是以管理客戶數(shù)據(jù)為核心,幫助商戶與客戶保持聯(lián)系的工具。

而軟件的實(shí)質(zhì)是計(jì)算機(jī)中運(yùn)行的代碼,如何將抽象的代碼更準(zhǔn)確地映射到人類所關(guān)心的領(lǐng)域中,這是軟件開(kāi)發(fā)者一直在探尋的話題,不管是函數(shù)式編程(FP)還是面向?qū)ο缶幊蹋∣OP)也好,都是為了幫助開(kāi)發(fā)者開(kāi)發(fā)出更貼近于領(lǐng)域中的軟件模型。

在傳統(tǒng)的軟件開(kāi)發(fā)方法中,我們常常會(huì)遇到一系列影響軟件質(zhì)量的技術(shù)以及非技術(shù)問(wèn)題:

  • 開(kāi)發(fā)者熱衷于技術(shù),但缺乏設(shè)計(jì)和業(yè)務(wù)思考。開(kāi)發(fā)人員在不完全了解業(yè)務(wù)需求的情況下,閉門(mén)造車,即使功能上線也無(wú)人問(wèn)津。

  • 代碼輸入而非業(yè)務(wù)輸入。技術(shù)人員對(duì)技術(shù)實(shí)現(xiàn)情有獨(dú)鐘,出現(xiàn)殺雞焉用牛刀的情況。

  • 過(guò)于重視數(shù)據(jù)庫(kù)。以數(shù)據(jù)庫(kù)設(shè)計(jì)為中心,而非業(yè)務(wù)來(lái)進(jìn)行開(kāi)發(fā),結(jié)果往往是,軟件無(wú)法適應(yīng)一直在變動(dòng)的業(yè)務(wù)邏輯。

DDD 是一種設(shè)計(jì)思想,一種以領(lǐng)域(業(yè)務(wù))為出發(fā)點(diǎn),以解決軟件建模復(fù)雜度為目的設(shè)計(jì)思想,我們也可以將其理解為一種建模的方法論。

DDD 的設(shè)計(jì)思想分為戰(zhàn)略和戰(zhàn)術(shù)兩部分。

我們可以將戰(zhàn)略設(shè)計(jì)理解為宏觀層面的設(shè)計(jì),它的目的包括,分析業(yè)務(wù)的復(fù)雜程度,拆分業(yè)務(wù)的領(lǐng)域范疇,指導(dǎo)業(yè)務(wù)整合方式等等 。我們可以將戰(zhàn)術(shù)設(shè)計(jì)理解為微觀層面(代碼層面)的設(shè)計(jì),它為我們?cè)趯?shí)現(xiàn)業(yè)務(wù)邏輯提供一系列工具。

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

通用語(yǔ)言(Ubiquitous Language)

語(yǔ)言本是人類溝通的基本工具,然而開(kāi)發(fā)人員習(xí)慣了使用技術(shù)術(shù)語(yǔ),領(lǐng)域?qū)<遥I(lǐng)域?qū)<以诖朔褐妇I(yè)務(wù)的專家,比如用戶,客戶等等)對(duì)技術(shù)術(shù)語(yǔ)毫不關(guān)心,于是造成了不可避免的溝通問(wèn)題,一旦溝通出現(xiàn)問(wèn)題,開(kāi)發(fā)出來(lái)的軟件便很難解決領(lǐng)域?qū)<业恼嬲袋c(diǎn)。

通用語(yǔ)言是 DDD 思想的基石,它是開(kāi)發(fā)人員和領(lǐng)域?qū)<夜餐瑒?chuàng)建一套溝通語(yǔ)言,一套在團(tuán)隊(duì)中流行的,通用的溝通語(yǔ)言,團(tuán)隊(duì)的組員之間可使用通用語(yǔ)言進(jìn)行無(wú)障礙交流。

這要求開(kāi)發(fā)人員摒棄技術(shù)味濃重的技術(shù)術(shù)語(yǔ),與領(lǐng)域?qū)<液献?,像領(lǐng)域?qū)<乙粯雨P(guān)注業(yè)務(wù)問(wèn)題,共同挖掘并打磨業(yè)務(wù)中的術(shù)語(yǔ),創(chuàng)建一套通用語(yǔ)言。

通用語(yǔ)言往往可以直接應(yīng)用于代碼中,它可以直接被寫(xiě)成一個(gè)類或者一個(gè)類的方法。

比如在開(kāi)發(fā)一個(gè)購(gòu)物車時(shí),與其使用技術(shù)術(shù)語(yǔ):

  • Cart::create(): 創(chuàng)建一個(gè)購(gòu)物車。

  • Cart::updateStatus():更新購(gòu)物車狀態(tài)。

  • Cart::remove():移除購(gòu)物車。

我們不妨使用更貼近業(yè)務(wù)的通用語(yǔ)言:

  • Cart::init(): 創(chuàng)建一個(gè)購(gòu)物車。

  • Cart::addItemToCart():添加商品。

  • Cart::removeItemFromCart():移除商品。

  • Cart::empty():清空購(gòu)物車。

在使用后者時(shí),開(kāi)發(fā)人員不用解釋每一個(gè)類方法的意義,領(lǐng)域?qū)<铱梢灾苯涌炊恳粋€(gè)類方法的目的。開(kāi)發(fā)人員甚至可以和領(lǐng)域?qū)<易谝黄鹗褂么a來(lái)打磨業(yè)務(wù)流程。

限界上下文(Bounded Context)

在實(shí)現(xiàn)了通用語(yǔ)言自由以后,我們需要使用限界上下文來(lái)規(guī)定每一套通用語(yǔ)言的使用邊界。限界上下文是語(yǔ)義和語(yǔ)境的邊界,在其內(nèi)的每一個(gè)元素都有自己特定的含義,也就是說(shuō)每一個(gè)概念在一個(gè)限界上下文中都是獨(dú)一無(wú)二,不可以出現(xiàn)一詞多義的情況。

我們可以用一個(gè)簡(jiǎn)單的例子來(lái)解釋限界上下文。比如在一個(gè)購(gòu)物車的限界上下文中,我們可以用 User 一詞來(lái)代表購(gòu)買(mǎi)商品的客戶。而在一個(gè)注冊(cè)系統(tǒng)中,我們可以用 User 一詞指的是帶有用戶名和密碼的賬號(hào)。雖然詞匯一樣,但是在不同的限界上下文中,它們的含義不同。

我們使用限界上下文和通用語(yǔ)言,對(duì)業(yè)務(wù)進(jìn)行語(yǔ)言層面的拆分。限界上下文為領(lǐng)域中的每一個(gè)元素賦予清晰的概念,開(kāi)發(fā)人員也就不會(huì)將情不自禁的在腦海中閃現(xiàn)多個(gè)支撐一個(gè)元素的概念,避免寫(xiě)出“大泥球”(big ball of mud)代碼。

子域(Subdomain)

如果說(shuō)限界上下文是對(duì)業(yè)務(wù)進(jìn)行語(yǔ)言層面拆分的話,那么子域便是對(duì)業(yè)務(wù)進(jìn)行商業(yè)價(jià)值的拆分。每一個(gè)商業(yè)都有自己的關(guān)注點(diǎn),即便是看起來(lái)一樣的電商平臺(tái),淘寶是開(kāi)放平臺(tái)模式,京東是價(jià)值鏈整合模式,一個(gè)明顯的區(qū)別是,淘寶使用第三方物流而京東自建物流體系。

那么作為一個(gè)開(kāi)發(fā)人員,為何要關(guān)心看起來(lái)似乎與自己無(wú)關(guān)的商業(yè)模式呢?恰恰相反,只有當(dāng)我們了解一個(gè)商業(yè)的結(jié)構(gòu)時(shí),才能開(kāi)發(fā)出一個(gè)主次分明的系統(tǒng)來(lái)支撐一個(gè)商業(yè)的飛速發(fā)展。

子域便是這樣一個(gè)幫助我們劃分主次的工具。

有三種類型的子域:

  • 核心域(Core Domain):這是系統(tǒng)中需要最大投資的領(lǐng)域,它代表著整個(gè)商業(yè)的核心競(jìng)爭(zhēng)力。我們需要花大量資源以及資源來(lái)打磨核心域,這關(guān)乎一個(gè)企業(yè)的存亡。比如京東的自建物流系統(tǒng)。

  • 支撐域(Supporting Domain):此領(lǐng)域并非一個(gè)企業(yè)的核心業(yè)務(wù),但是核心域卻離不開(kāi)它,它可以采用外包定制方案實(shí)現(xiàn)。比如認(rèn)證上下文,權(quán)限上下文。

  • 通用域(Generic Domain):如果已有成熟的解決方案,通用域可以采購(gòu)現(xiàn)成方案來(lái),如果沒(méi)有,也可以采用外包,在通用域上的投資應(yīng)該是最小的。比如對(duì)于淘寶而言,物流便是其通用域。

限界上下文和子域的關(guān)系眾說(shuō)紛紜,有專家提倡1:1,也有專家提倡1:N。個(gè)人比較提倡 1:1, 由于受實(shí)現(xiàn)領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)一書(shū)作者影響比較深。

上下文映射(Context Mapping)

在一個(gè)龐大的系統(tǒng)中,限界上下文之間必定存在一定的依賴關(guān)系。如何將一個(gè)上下文中的概念映射到另一個(gè)上下文中?我們使用上下文映射。

以下是幾種上下文映射的關(guān)系類型:

  • 合作關(guān)系(Partnership)

  • 共享內(nèi)核(Shared Kernel)

  • 客戶方-供應(yīng)方開(kāi)發(fā)(Customer-Supplier Development)

  • 遵奉者(Conformist)

  • 防腐層(Anticorruption Layer)

  • 開(kāi)放主機(jī)服務(wù)(Open Host Service)

  • 發(fā)布語(yǔ)言(Published Language)

  • 另謀他路(SeparateWay)

  • 大泥球(Big Ball of Mud)

以上都是比較抽象的概念,有時(shí)兩個(gè)限界上下文之間也可以存在多重關(guān)系。

以上便是 DDD 戰(zhàn)略設(shè)計(jì)的幾個(gè)核心概念。

戰(zhàn)術(shù)設(shè)計(jì)

如何為限界上下文中的概念建立模型,我們將使用的是 DDD 所提供的戰(zhàn)術(shù)設(shè)計(jì)。

實(shí)體(Entity)

首先我們講到的是,實(shí)體。

實(shí)體是領(lǐng)域中獨(dú)立事物的模型,每個(gè)實(shí)體都擁有一個(gè)唯一的標(biāo)識(shí)符,比如 ID, UUID,Username 等等。大多數(shù)情況下,實(shí)體是可變的,它的狀態(tài)會(huì)隨著時(shí)間的遷移改變,不過(guò),一個(gè)實(shí)體不一定必須可變。

實(shí)體的最大的特征是它的個(gè)體性,唯一性。比如在一個(gè)簡(jiǎn)單的購(gòu)物車上下文中,訂單(Order) 便是一個(gè)實(shí)體,ID 是它的標(biāo)識(shí)符,它的狀態(tài)可以在提交(placed),確認(rèn)(confirmed) 以及已退 (refunded) 之間變化。

值對(duì)象(Value Object)

值對(duì)象是領(lǐng)域中用來(lái)描述,量化或者測(cè)量實(shí)體的模型。和實(shí)體不同,值對(duì)象沒(méi)有唯一的標(biāo)識(shí)符,兩個(gè)對(duì)等的值對(duì)象是可以替換的。值對(duì)象具有不變性(Immutability),一旦創(chuàng)建以后,一個(gè)值對(duì)象的屬性就定型了,不可更改。

理解值對(duì)象的最直接的方法是,想象我們現(xiàn)實(shí)生活中的鈔票,在日常生活中,甲的十塊錢(qián)人民幣和乙的十塊錢(qián)人民幣是可以對(duì)等交換的。

在上文的購(gòu)物車上下文中,金額(Money)便是一個(gè)值對(duì)象,金額由貨幣(currency)和數(shù)目(amount):

class Money {
  public $currency;
  public $amount;

  function __construct($currency, $amount) {
    $this->currency = $currency;
    $this->amount = $amount;
  }  
}

使用值對(duì)象進(jìn)行建模,能幫助我們用代碼更精確地建立領(lǐng)域模型。

聚合(Aggregate)

聚合是什么?聚合是上下文中對(duì)業(yè)務(wù)領(lǐng)域更精細(xì)的劃分,每一個(gè)聚合保證自己的業(yè)務(wù)一致性。

那么什么是業(yè)務(wù)不變性?業(yè)務(wù)不變性表示一個(gè)業(yè)務(wù)規(guī)則,該規(guī)則在業(yè)務(wù)領(lǐng)域中不可違背,必須保證其一致性。比如,在進(jìn)行訂單退款時(shí),退款金額不可以超過(guò)已付金額。

聚合的組成部分是實(shí)體和值對(duì)象,有時(shí)候也只有實(shí)體。為了保護(hù)聚合的業(yè)務(wù)一致性,每個(gè)聚合只可以通過(guò)某一個(gè)實(shí)體對(duì)其進(jìn)行操作,該實(shí)體被稱為聚合根。

領(lǐng)域事件(Domain Event)

領(lǐng)域事件是通過(guò)通用語(yǔ)言分析出來(lái)的事件,與常見(jiàn)的事務(wù)事件不同的是它與業(yè)務(wù)息息相關(guān),所以它的命名往往夾帶業(yè)務(wù)名詞,而不應(yīng)該與數(shù)據(jù)庫(kù)掛鉤。比如購(gòu)物車增添商品,對(duì)應(yīng)的領(lǐng)域事件應(yīng)該是 ProductAddedToCart, 而不是 CartUpdated。

總結(jié)

DDD 還提供了諸如應(yīng)用服務(wù)(Application Service),領(lǐng)域服務(wù)(Domain Service) 等戰(zhàn)術(shù)設(shè)計(jì),DDD 還提出了文章開(kāi)頭就提過(guò)的事件溯源,六邊形等架構(gòu)模式,在此我們將不一一介紹。

DDD 的核心是從業(yè)務(wù)的角度為軟件建立模型,其目的是打造更貼近業(yè)務(wù)的代碼,能更直觀的從代碼理清業(yè)務(wù)流程。 然而實(shí)現(xiàn) DDD 并非一日之舉,它需要不斷的實(shí)踐,不斷的打磨。

到此,相信大家對(duì)“php中的DDD有什么用”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

php
AI