您好,登錄后才能下訂單哦!
本篇內(nèi)容主要講解“php中的DDD有什么用”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“php中的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)模式。
軟件是服務(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ù)邏輯提供一系列工具。
語(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ù)流程。
在實(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)代碼。
如果說(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ū)作者影響比較深。
在一個(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è)核心概念。
如何為限界上下文中的概念建立模型,我們將使用的是 DDD 所提供的戰(zhàn)術(shù)設(shè)計(jì)。
首先我們講到的是,實(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ì)象是領(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)域模型。
聚合是什么?聚合是上下文中對(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)域事件是通過(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。
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í)!
免責(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)容。