領(lǐng)域驅(qū)動設(shè)計——一種將概念模型化的方式-創(chuàng)新互聯(lián)

原文發(fā)布于:http://www.gufeng.tech/  谷風(fēng)的個人主頁

創(chuàng)新互聯(lián)公司專注于淶水企業(yè)網(wǎng)站建設(shè),響應(yīng)式網(wǎng)站,商城開發(fā)。淶水網(wǎng)站建設(shè)公司,為淶水等地區(qū)提供建站服務(wù)。全流程按需網(wǎng)站制作,專業(yè)設(shè)計,全程項目跟蹤,創(chuàng)新互聯(lián)公司專業(yè)和態(tài)度為您提供的服務(wù)

1.引子

   2004年Eric Evans 發(fā)表了一本書:《Domain-Driven Design: Tackling Complexity in the Heart of Software》(中文名:《領(lǐng)域驅(qū)動設(shè)計:軟件核心復(fù)雜性應(yīng)對之道》),在這本書中作者提出了領(lǐng)域驅(qū)動設(shè)計(DDD)的概念,到現(xiàn)在已經(jīng)10多年的時間了。

1.1 面向?qū)ο笈c面向?qū)ο笳Z言

   面向?qū)ο笏枷胍呀?jīng)存在相當(dāng)長的歷史了(相對于軟件的歷史),我而們使用的語言,很多也都是面向?qū)ο蟮?,但是我們使用面向?qū)ο蟮恼Z言就一定能寫出來面向?qū)ο蟮某绦騿??顯然是不可能的。業(yè)務(wù)邏輯代碼的堆積、缺乏良好設(shè)計的系統(tǒng)或模塊亦或是功能,這樣是不能保證代碼的復(fù)用性、擴展性的。

1.2 領(lǐng)域模型

   領(lǐng)域驅(qū)動設(shè)計的出現(xiàn),就是為了解決這一問題的。領(lǐng)域驅(qū)動設(shè)計是以建立正確的領(lǐng)域模型為核心,以構(gòu)建清晰的分層架構(gòu)基礎(chǔ),從而使面向?qū)ο蟮拈_發(fā)進入到了一個新的階段。

   領(lǐng)域驅(qū)動設(shè)計的前提是有一種能夠在領(lǐng)域?qū)<遥I(yè)務(wù)專家)、設(shè)計人員、開發(fā)人員(為什么會有開發(fā)人員,我們會在后面介紹原因)三類參與者通用的溝通語言,在三類參與者的不斷交流、溝通中發(fā)現(xiàn)領(lǐng)域概念(業(yè)務(wù)概念),再將概念固化成模型,最后由領(lǐng)域模型驅(qū)動設(shè)計并實現(xiàn)。

   說到這里,看上去領(lǐng)域模型并沒有什么特別的地方,與我們?nèi)粘7治龅姆绞經(jīng)]什么大的區(qū)別,我們首先來簡單介紹寫領(lǐng)域模型的兩個特點:

   1)業(yè)務(wù)邏輯集中在領(lǐng)域?qū)ο螅悾┥希?/small>

   2)每個領(lǐng)域?qū)ο笫峭暾酮毩⒌?,并具有自己的屬性和行為?/small>

   在接下來的內(nèi)容中,我們一起來了解下如何實現(xiàn)領(lǐng)域驅(qū)動設(shè)計以及領(lǐng)域驅(qū)動設(shè)計的優(yōu)點。

2.領(lǐng)域驅(qū)動設(shè)計

   領(lǐng)域驅(qū)動設(shè)計涵蓋了領(lǐng)域模型、領(lǐng)域語言、架構(gòu)設(shè)計、實現(xiàn)幾部分內(nèi)容,下面我們逐一了解一下。

2.1 領(lǐng)域模型

   關(guān)于什么是領(lǐng)域模型以及領(lǐng)域模型的特點,在前面內(nèi)容中我們有了整體的了解,接下來我們就領(lǐng)域模型本身進行一下簡單的了解。

2.1.1 抽象模型

   領(lǐng)域模型是某個邊界內(nèi)的領(lǐng)域的一個抽象,是客觀世界的模型,首先它使有邊界的,清晰的邊界是領(lǐng)域模型抽象是否完整的一個重要衡量指標(biāo)。在該領(lǐng)域模型內(nèi),我們只關(guān)心領(lǐng)域內(nèi)的內(nèi)容。

   領(lǐng)域模型只是實際業(yè)務(wù)的一種反映,與具體實現(xiàn)技術(shù)無關(guān)??梢哉f領(lǐng)域模型建立的成功與否,直接關(guān)系到最終的實現(xiàn)、使用等等。領(lǐng)域模型確保任參與人在任何時間看到的內(nèi)容都是一樣的,了解了模型,就能知道實現(xiàn)的步驟。

   領(lǐng)域模型對于提高軟件的維護性、復(fù)用性以及業(yè)務(wù)可理解性等方面都有很好的幫助。領(lǐng)域模型貫穿整個分析、設(shè)計、開發(fā)過程,前面提到的三類參與者使用一種大家都能理解的語言進行溝通,確保所有人對模型的理解是一致的,這樣最終開發(fā)出來的結(jié)果和最初的設(shè)計才能大程度的吻合。

   要建立一個好的領(lǐng)域模型并不簡單,甚至可能是一路坎坷,需要領(lǐng)域?qū)<?、設(shè)計人員、開發(fā)人員通力配合、深入交流、共享信息和知識。最后,領(lǐng)域模型要通過文檔或圖形方式展現(xiàn)出來(推薦使用圖形分解整體結(jié)構(gòu),配以文字說明)。設(shè)計足夠好的領(lǐng)域模型,肯定是符合業(yè)務(wù)需求的,同時也能夠快速響應(yīng)需求變化。

   與領(lǐng)域模型緊密相關(guān)的還有另外一組概念:聚合、聚合根。下面我們來簡單了解下這兩個概念。

   聚合:通過定義對象間的隸屬關(guān)系和邊界來實現(xiàn)領(lǐng)域模型的內(nèi)聚,

   聚合根:聚合內(nèi)的某個實體,外部調(diào)用聚合時,必須從聚合根開始調(diào)用,不能繞過。

   關(guān)于聚合的一些特點:

   1)每個聚合有一個根和邊界;

   2)內(nèi)部對象可互相引用,但是外部對象訪問聚合時,必須從聚合根開始;

   3)除根外,其它對象在聚合內(nèi)保持唯一即可;

   4)聚合內(nèi)部對象可以保持對其它聚合根的引用;

   5)刪除聚合根時,必須同時刪除其它聚合內(nèi)對象。

   所有具有獨立含義并且能夠被單獨訪問的內(nèi)容是聚合。

2.1.2 領(lǐng)域通用語言

    設(shè)想一下,領(lǐng)域?qū)<覞M口的專業(yè)術(shù)語,設(shè)計人員滿口的設(shè)計理論,開發(fā)人員滿口的開發(fā)語言及算法,這樣的團隊怎么溝通!當(dāng)然可以引入“翻譯”,但是“翻譯”的結(jié)果以及對結(jié)果的理解會造成多大程度上的信息丟失,誰也不確定。

   基于以上的原因,迫切需要一種大家都能夠表達出來和理解的語言——這就是領(lǐng)域通用語言。領(lǐng)域通用語言是領(lǐng)域驅(qū)動設(shè)計的基礎(chǔ)和前提。在三類參與者的各種形式溝通中,都要使用領(lǐng)域通用語言,確保自己的信息能夠被其他人完整、快速的理解。

2.1.3 模型到實現(xiàn)

    假設(shè)我們已經(jīng)擁有了一個非常正確且嚴謹?shù)哪P停敲词欠衲軐⑦@個模型直接轉(zhuǎn)換成代碼嗎?肯定是不行的。所以要求我們在領(lǐng)域建模和設(shè)計時,就要考慮最終的代碼實現(xiàn),將領(lǐng)域模型與實現(xiàn)緊密關(guān)聯(lián)起來,這就是為什么要有開發(fā)人員參與的原因。

   這樣的結(jié)構(gòu)(開發(fā)人員參與模型建立、結(jié)構(gòu)設(shè)計)有利于盡早發(fā)現(xiàn)那些不適合在軟件中實現(xiàn)的模型部分并要求修正,這樣也避免了在最后實現(xiàn)時發(fā)現(xiàn)問題、修正設(shè)計所帶來的巨大時間損失。同時,因為開發(fā)人員參與了模型設(shè)計,所以在編碼實現(xiàn)時,都會盡力保護模型不被破壞(因為這是大家共同努力的結(jié)果),同時當(dāng)開發(fā)人員發(fā)現(xiàn)編碼實現(xiàn)有不滿足模型或者不完善的地方,也會去完善它,進行代碼重構(gòu),這樣能夠在很大程度上提升軟件的可靠性,也便于其他人員在接手時能快速了解模型、掌握實現(xiàn)。

2.2 領(lǐng)域驅(qū)動設(shè)計的架構(gòu)分層

   我們先來看一張Eric Evans 在他的《Domain-Driven Design: Tackling Complexity in the Heart of Software》一書中提到的分層圖:

領(lǐng)域驅(qū)動設(shè)計  ——一種將概念模型化的方式

   關(guān)于這張圖可能都不陌生,但是每一層在領(lǐng)域驅(qū)動設(shè)計中的職責(zé)是什么?完成什么樣的功能?層與層之間的協(xié)作關(guān)系是什么樣的?這些問題會在后面一一解釋。

2.2.1 分層

    1)用戶界面

   人機交互部分,沒有特殊內(nèi)容。

   2)應(yīng)用

    此應(yīng)用非彼應(yīng)用,這里的應(yīng)用只是很薄的一層,用于給User Interface提供功能接口,并調(diào)用Domain完成功能邏輯,看到這里應(yīng)該有了比較明確的認識了,Application不包括任何業(yè)務(wù),只是將根據(jù)User Interface的需要提供接口,并完成對一個或者多個Domain的調(diào)用。

    本層包含了所有軟件系統(tǒng)要完成的任務(wù),通過本層就能了解整體功能,User Interface僅僅是一種展現(xiàn)方式。

   3)領(lǐng)域

    這一層是整個系統(tǒng)的核心部分,包括了全部的業(yè)務(wù)邏輯、業(yè)務(wù)規(guī)則等全部業(yè)務(wù)相關(guān)內(nèi)容。

   4)基礎(chǔ)設(shè)施

    這里的基礎(chǔ)設(shè)施指的是基礎(chǔ)技術(shù)組件,包括消息通信、持久化、緩存等等所有的基礎(chǔ)技術(shù)組件。

2.2.2 幾種輔助模式

    1)實體(Entity)

   具有跨越系統(tǒng)的生命周期甚至能超越軟件系統(tǒng)的一系列的延續(xù)性和標(biāo)識符的對象成為實體。簡單說就是具有絕對唯一標(biāo)識的對象。比如銀行賬戶的ID是唯一的標(biāo)識,那么一個銀行賬戶就是一個實體。實體擁有自己的屬性,管理自己的內(nèi)部狀態(tài)并對外暴露行為。

   2)值對象(Value Object)

   當(dāng)我們關(guān)心對象的唯一標(biāo)識而只關(guān)心其屬性值的時候,這個對象就是一個值對象。對于值對象,理論上可以被輕易的創(chuàng)建以丟掉。如果是可共享值對象,那應(yīng)該確保它的值是不可變的。“值對象應(yīng)該保持盡量的簡單。當(dāng)其他當(dāng)事人需要一個值對象時,可以簡單地傳遞值,或者創(chuàng)建一個副本。”

   3)服務(wù)(Service)

   是不是所有的領(lǐng)域都能映射成對象呢?顯然是不可能的,那么如何處理不能夠映射成對象的領(lǐng)域呢?這時候就需要服務(wù)這個東西了。服務(wù)通常對應(yīng)領(lǐng)域的動作,代表領(lǐng)域中得一些重要行為,而這些行為又不屬于任何一個實體或者值對象。這些行為可以定義為服務(wù)對象。

   服務(wù)可能存在于領(lǐng)域?qū)?、基礎(chǔ)設(shè)施層等,所以要區(qū)分服務(wù),不要濫用服務(wù)。

   服務(wù)對象不包含內(nèi)部狀態(tài),只有行為,所以它提供的主要是行為,作為操作接口存在。我們需要注意的是,不需要對每一個操作創(chuàng)建服務(wù)。我們一起來一下服務(wù)的幾個特征:

  (1)服務(wù)執(zhí)行的操作涉及一個領(lǐng)域概念,這個領(lǐng)域概念通常不屬于一個實體或者值對象;

  (2)被執(zhí)行的操作涉及到領(lǐng)域中的其他的對象;

  (3)操作是無狀態(tài)的。

   4)模塊(Module)

   當(dāng)模型巨大,難以整體討論時,需要把這個大得模型拆成幾個關(guān)聯(lián)的模塊。

   5)聚合&聚合根

   聚合是針對數(shù)據(jù)變化可以考慮成一個單元的一組相關(guān)的對象。聚合使用邊界將內(nèi)部和外部的對象劃分開來。每個聚合有一個根,是一個實體,并且它是外部可以訪問的唯一的對象。

   關(guān)于聚合與聚合根的內(nèi)容,可參考2.1.1節(jié)。

    6)Factory(工廠)

   引入工廠模式,是因為領(lǐng)域模型本身的復(fù)雜性決定的,創(chuàng)建領(lǐng)域?qū)ο笠h遠比創(chuàng)建pojo對象復(fù)雜得多,尤其是聚合會更加復(fù)雜。此時引入工廠模式,可以將復(fù)雜的實現(xiàn)放在工廠內(nèi),外部調(diào)用工廠方法即可得到相應(yīng)領(lǐng)域?qū)ο螅瑫r也隱藏了創(chuàng)建邏輯(主要是提供給Application和Infrastructure使用的)。

    7)Repository(倉儲、資源庫)

   倉儲最初的設(shè)計目的是用來管理內(nèi)存中的對象,但我們可以擴展使用,對于需要持久化的領(lǐng)域?qū)ο?,使用Repository將其持久化到數(shù)據(jù)庫(或其它持久化存儲)中,再次需要時,可以通過Repository將對象從數(shù)據(jù)庫中恢復(fù)。通常情況下,一個聚合對應(yīng)一個倉儲。

   那么對于那些不能夠通過單一Repository查詢出來的結(jié)果(比如界面中需要展現(xiàn)的數(shù)據(jù)來源于多個Repository的情況)我們該怎么辦呢?當(dāng)然可以通過調(diào)用多個Repository查詢出結(jié)果,但更好的方式是通過CQRS架構(gòu)來實現(xiàn),也就是說對于查詢可繞過Domain,直接由Application發(fā)起調(diào)用另外的架構(gòu)或者層來實現(xiàn)。

    8)CQRS(Command Query Responsibility Segregation,命令查詢職責(zé)分離)

   從字面理解,就是命令和查詢要分離開,那么什么事命令呢?非查詢的操作即命令。結(jié)合領(lǐng)域驅(qū)動設(shè)計,我們可以理解成命令可以通過領(lǐng)域驅(qū)動設(shè)計完成,查詢則可使用簡單、直接的方式完成(如直接寫SQL)。

   由于是分離的,所以兩部分可以采用相同甚至完全不同的架構(gòu)來實現(xiàn),由此引申,是不是數(shù)據(jù)庫也可以分開設(shè)計呢?當(dāng)然是可以的。

3.結(jié)束

   本文中我們粗略的了解了領(lǐng)域驅(qū)動設(shè)計的一些基本概念、原則和一些所謂的“模式”,在實際使用或者叫“領(lǐng)域驅(qū)動設(shè)計落地”的過程中,除了一些必須遵守的原則外,我們可以根據(jù)自己的業(yè)務(wù)特點、團隊優(yōu)勢進行裁剪。

   沒有任何一種語言是具有絕對優(yōu)勢的,同樣也沒有任何一種設(shè)計方法是絕對正確的。找準(zhǔn)我們自己的方向,找出適合我們業(yè)務(wù)特點、團隊特點的方法,并對該方法進行落地裁剪,使之更具生命力、能夠解決我們的實際問題。

   最后,不要迷信、迷戀任何一種或幾種方法、模式,所有的方法都是人根據(jù)經(jīng)驗總結(jié)出來,方法、模式可以參考并綜合使用,最終達到擁有自己的方法、自己的模式,這樣才能更好的服務(wù)于自己的業(yè)務(wù),創(chuàng)造技術(shù)體系。

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機、免備案服務(wù)器”等云主機租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。

分享名稱:領(lǐng)域驅(qū)動設(shè)計——一種將概念模型化的方式-創(chuàng)新互聯(lián)
轉(zhuǎn)載來源:http://muchs.cn/article2/dhieic.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供定制開發(fā)、虛擬主機App設(shè)計、網(wǎng)站維護、網(wǎng)站營銷標(biāo)簽優(yōu)化

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)