Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
輯導語:DDD(Domain-driven design,領域驅(qū)動設計)是一種架構(gòu)設計方法論,通過邊界劃分,將復雜業(yè)務領域簡單化,幫助我們設計出清晰的領域和應用邊界,保證業(yè)務模型與代碼模型的一致性。本文作者結(jié)合實際經(jīng)驗,介紹了如何從0到1實踐DDD,一起來看看吧。
隨著業(yè)務的不斷發(fā)展,我們發(fā)現(xiàn)自己的系統(tǒng)開始變得有點臃腫,為了減少復雜性,我們嘗試借助DDD來改善我們的系統(tǒng)。本文記錄了自己對DDD的理解和實踐過程,歡迎大家一起探討。見識所限,難免有理解不到位,希望路過的大佬不吝賜教。
如果你有以上的一些疑問,那你可以試試領域驅(qū)動設計:
DDD(Domain-driven design,領域驅(qū)動設計)是一種架構(gòu)設計方法論,通過邊界劃分,將復雜業(yè)務領域簡單化,幫助我們設計出清晰的領域和應用邊界,保證業(yè)務模型與代碼模型的一致性。
在細看這個定義之前,我們可以思考一下,為什么我們的業(yè)務系統(tǒng)會慢慢變得復雜?
常見的情況是,業(yè)務在發(fā)展過程中為了探尋發(fā)力點,需要不斷地試錯迭代,調(diào)整方向,而系統(tǒng)在設計之初,難以預期到后面的瞬息萬變,為了應付業(yè)務,修修改改,久之,系統(tǒng)也變得復雜起來。
可以怎么辦呢?及時重構(gòu)唄——不改變軟件系統(tǒng)外部行為的前提下,改善它的內(nèi)部結(jié)構(gòu)。
然而重構(gòu)是從技術層面上抽煉出來的模型,往往不具有實際的業(yè)務含義,其他同學可能難以自然地將業(yè)務問題映射到對應的設計模型。另外,如果不能如實映射業(yè)務模型,隨著業(yè)務方向調(diào)整,代碼可能又開始腐敗……有點像芝諾悖論中,阿基里斯永遠追不上小烏龜。
那DDD怎么搞?
DDD是這么想的:”將業(yè)務架構(gòu)映射到系統(tǒng)架構(gòu)上,在響應業(yè)務變化調(diào)整業(yè)務架構(gòu)時,也隨之變化系統(tǒng)架構(gòu)”。可能大家平時有這樣的想法,但是比較模糊,未形成體系,而DDD就提供了一套完整的方法論。從業(yè)務角度去審視我們的系統(tǒng),從而實現(xiàn)高內(nèi)聚低耦合的代碼。
整體而言,領域驅(qū)動設計包括戰(zhàn)略建模和戰(zhàn)術建模: 戰(zhàn)略設計側(cè)重于高層次、宏觀上去劃分和集成限界上下文,而戰(zhàn)術設計則關注更具體使用建模工具來細化上下文。
1)領域、子域
在討論問題之前,我們需要先定義好問題。
領域即問題域,通常是根據(jù)一個組織所處的行業(yè)進行識別,它基于業(yè)務的愿景,定義了系統(tǒng)要解決的現(xiàn)實問題的目標和范圍。領域越大,業(yè)務的范圍也越大,大的領域可以拆分成小的問題域,稱之為子域。根據(jù)子域重要性和功能屬性劃,可以將其分為三類。
核心域、支撐域和通用域:
這個幾個概念其實很容易理解,不過在劃分的時候,注意要從業(yè)務的視角,而不是技術功能模塊來劃分。
2)限界上下文
我們語言博大精深,同樣的話在不同語境下就可演變出不同含義,這在溝通時總是帶來不必要的麻煩。為了準確地溝通,我們需要統(tǒng)一語言的邊界,在相同的語言邊界內(nèi)溝通,才不容易出差錯。
一則阿凡提當理發(fā)師懲罰一個狡猾牧師的趣事:理發(fā)時,阿凡提刮臉時問牧師:“牧師,是否要眉毛?”牧師答:“這還用問,眉毛豈能不要?”.“好,你要我就給你!”,說著就把牧師的眉毛刮下來遞到他手里,牧師氣得說不出話來,誰叫自己說要呢。阿凡提又問:“牧師,胡子要嗎?”.“不要,不要!”牧師連忙說。“好,你不要就不要。” 嗖嗖幾刀就把牧師的胡子刮下來。
在一個系統(tǒng)中,一個名詞在不同語境可能有不同的含義,我們對它關注的屬性和行為也有所不同。例如,在電商系統(tǒng)中,對于產(chǎn)品Product, 在采購上下文,需要關注產(chǎn)品的進價、最小起訂量與供貨周期;在市場上下文中,則關心產(chǎn)品的品質(zhì)、售價,以及用于促銷的精美圖片和銷售類型;在倉儲上下文中,倉庫工作人員更關心產(chǎn)品放在倉庫的哪個位置,產(chǎn)品的重量與體積,是否易碎品以及訂購產(chǎn)品的數(shù)量。
限界上下文在《實現(xiàn)領域驅(qū)動設計》中,用了很大篇幅去講,它有幾個重要的意義:
經(jīng)過戰(zhàn)略建模之后,我們可以得到以下的一個模型:
為了更好地理解,我們對手上的一個項目:“IoT設備增值產(chǎn)品管理系統(tǒng)”進行實踐。該項目中,我們提供給商戶在IoT設備上管理增值運營產(chǎn)品的能力。這里的IoT設備主要是微信支付刷臉設備等。商戶可以在系統(tǒng)中創(chuàng)建我們業(yè)務中的增值運營產(chǎn)品,如電子海報、互動海報等,創(chuàng)建完之后,相關的增值產(chǎn)品會被投放到IoT設備上,進行展示、運作:
一開始我們從業(yè)務的用例出發(fā),認為我們的系統(tǒng)主要是商戶在我們頁面網(wǎng)站使用,以及IoT設備通過接口連接我們后臺服務,認為這兩個分屬不同的子域,然后梳理了一些支撐的功能:
畫完草圖之后,感覺不是很確定,于是便去咨詢部門的DDD專家王老師(十分感謝王立老師的指導),得到了一些寶貴的建議:我們應該避免直接從表現(xiàn)層去看業(yè)務,表現(xiàn)層就像是冰山露在水面上的棱角,這些棱角看起來毫不相干,但是實際上底層是連成一塊的,這些才是我們需要關注的。
就像這個項目,表面上商戶和設備是分開的,實際上它們在操作都是我們的增值運營產(chǎn)品,應該看成我們的系統(tǒng)提供統(tǒng)一對外的服務,然后商戶和設備來使用我們的服務。UGC內(nèi)容存儲業(yè)務用例其實沒有涉及到的,屬于實現(xiàn)時候的東西。一番建議讓我們理清了思路,于是重新梳理,得到以下的戰(zhàn)略建模圖:
整體而言,我們將整體系統(tǒng)梳理為8個子域:
其中我們系統(tǒng)中的商戶信息依賴了微信支付商戶賬號信息和IoT設備鋪設服務信息,這里使用防腐層進行隔離,將外部的商戶信息“翻譯”為我們業(yè)務中的商戶信息。三、如何實現(xiàn)DDD之戰(zhàn)術建模梳理清楚上下文之間的關系后,我們基本了解業(yè)務的概貌,接下來需要細化上下文,進一步完善我們的模型。這里也需要用到DDD的一些基本概念。
1)實體、值對象
實體和值對象是組成領域模型的基礎單元。當一個對象由其標識(而不是屬性)區(qū)分時,這種對象稱為實體。如在校園教務系統(tǒng)中,每個賬戶是對應著一個學生,根據(jù)學號來唯一標識,可以認為是一個實體。傳統(tǒng)的數(shù)據(jù)建模大多是根據(jù)數(shù)據(jù)庫范式設計的,每一個數(shù)據(jù)庫表對應一個實體,每一個實體的屬性值用單獨的一列來存儲,一個實體主表會對應 N 個實體從表。
與其不同,DDD 是先構(gòu)建領域模型,再將業(yè)務對象映射為持久化對象。這可能導致DDD建立出來的實體,映射到具體數(shù)據(jù)庫表時,可能是1對多,多對1的關系。
如一個賬戶實體,有它的基本信息和權(quán)限角色信息,可能就對應了2個持久化對象。另一方面,有時候為了某些查詢場景的方便,會把教師賬戶、學生賬戶等對應成一個持久化對象,就成了多對1。
通過對象屬性值來識別的對象,則可以認為是一個值對象。如地址信息{“省”: “廣東省”,”市”:”深圳市”},我們是通過它的屬性來區(qū)分出不同的地址。值對象實際上是想把一些不變的屬性組合起來,減少系統(tǒng)的復雜性。在設計值對象的時候,需要滿足以下的特性:
2)聚合、聚合根
在 DDD 中,實體和值對象是基礎的領域?qū)ο蟆嶓w一般對應業(yè)務對象,它具有業(yè)務屬性和業(yè)務行為;而值對象主要是屬性集合,對實體的狀態(tài)和特征進行描述。但是我們的一個業(yè)務流程中,一般會同時涉及多個實體、值對象的操作,這里業(yè)務邏輯緊密的實體和值對象便組合成一個聚合。
從數(shù)據(jù)層面來看,同個聚合內(nèi)的數(shù)據(jù)需要保持強一致性。
每一個聚合有一個聚合根實體,設置聚合根的主要目的是為了避免由于復雜數(shù)據(jù)模型缺少統(tǒng)一的業(yè)務規(guī)則控制,而導致聚合、實體之間數(shù)據(jù)不一致性的問題。聚合根可以看成是聚合的管理者,或是說handle。對內(nèi)其協(xié)調(diào)實體和值對象完成業(yè)務邏輯。對外則提供通過聚合ID供其他聚合關聯(lián)引用,屏蔽外部對內(nèi)部實體的直接訪問和修改。
建議的聚合設計原則:
3)領域服務
領域服務的定義:領域中的服務表示一個無狀態(tài)的操作,它用于實現(xiàn)特定于某個領域的任務。當某個操作不適合放在聚合(實體)或值對像上時,最好的方式便是使用領域服務。
舉個例子,在一個路線導航的項目中,“路線”可能是其中的一個實體,如果業(yè)務中有“推薦路線上相關的美食”這樣一個功能,那我們會想,這個功能應該歸給哪個領域?qū)ο螅o“路線”實體嗎?有點不合適,應該路線本身關注的是起終點,時間人物等。
此時可以將其這個功能歸為領域服務,它是一個路線狀態(tài)無關的服務,輸入路線各個節(jié)點,來得到沿路的各種美食。當然,要注意不要過度地使用領域服務,因為這很可能導致你把實體的行為都放在里面了,實體本身都變成了一些只有getter和setter的“貧血模型”。
4)領域事件
領域事件是領域模型中非常重要的一部分,用來表示領域中發(fā)生的事件。一個領域事件將導致進一步的業(yè)務操作,在實現(xiàn)業(yè)務解耦的同時,還有助于形成完整的業(yè)務閉環(huán)。
領域事件含義很廣泛,可以是業(yè)務流程的一個步驟,也可以是一個事件發(fā)生后觸發(fā)的后續(xù)動作,繳費完成之后,觸發(fā)短信通知;上面在設計聚合的時候,我們提到一個原則:在邊界之外使用最終一致性,一次事務最多只能更改一個聚合的狀態(tài)。如果一次業(yè)務操作涉及多個聚合狀態(tài)的更改,應通過領域事件,達到最終一致性。
實際上是通過事件驅(qū)動的這種異步方式,對系統(tǒng)進行解耦。當然,如果你覺得某兩個步驟,業(yè)務流程上不允許是不一致的,那就得重新考慮將其歸在同個聚合中了。
我們以增值運營服務上下文為例,根據(jù)上面的理解,結(jié)合業(yè)務實際,得到以下模型:
其中增值產(chǎn)品是其中的一個聚合根,通過該聚合根進行各種領域操作。海報縮略圖是其中的一個領域服務,通過輸入產(chǎn)品素材中的海報url,來得到一個海報的縮略圖。
在《領域驅(qū)動設計——軟件核心復雜性的應對之道》一書中,Eric提出了這樣的一種分層結(jié)構(gòu),將整個系統(tǒng)劃分為四層:用戶接口層、應用層、領域?qū)雍突A設施層。
用戶接口層:用戶接口層負責向用戶顯示信息和解釋用戶指令。
應用層:應用層相對來說是較“薄”的一層,主要是部署了應用服務。應用服務的實現(xiàn)中,它負責編排和轉(zhuǎn)發(fā)下一層的領域?qū)拥慕涌冢瑢⒁獙崿F(xiàn)的功能委托給一個或多個領域?qū)ο髞韺崿F(xiàn),本身只負責處理業(yè)務用例的執(zhí)行順序以及結(jié)果的拼裝。
領域?qū)樱?/strong>領域?qū)邮潜容^“厚”的一層,它包含聚合根、實體、值對象、領域服務等領域模型中的領域?qū)ο螅瑢崿F(xiàn)了核心的業(yè)務邏輯。領域?qū)雍蛻脤拥穆氊熆雌饋碛悬c模糊。
個人覺得,可以理解是應用層描述了一個具體操作從開始到結(jié)束的每一個環(huán)節(jié),而領域?qū)觿t是對其的細化,用來處理具體的某一個環(huán)節(jié)。
比如,比如線上購物中,購物車結(jié)算這一場景可看成是一個應用行為。而這個行為又主要包括金額計算、支付、生成訂單,這些子環(huán)節(jié)就可以理解為一個領域?qū)拥姆樟恕?/p>
基礎設施層:可以看到上面三層都有箭頭指向基礎設施層,它的作用就是為其它各層提供通用的技術和基礎服務,如數(shù)據(jù)持久化、消息中間件等DDD 分層架構(gòu)中的要素與傳統(tǒng)三層架構(gòu)(用戶界面層、業(yè)務邏輯層、數(shù)據(jù)訪問層)還是挺相似的,一個主要的變化是將業(yè)務邏輯層的服務拆分到了應用層和領域?qū)印脤禹憫獦I(yè)務用例的變化,領域?qū)雨P注不變的領域模型。
圖片來自極客時間
《DDD實戰(zhàn)課》在實際的代碼工程便是按照這樣的目錄來劃分,最近部門在推的整潔Git,也是這樣劃分目錄:
接下來,便是將領域?qū)ο笥成涞綄嶋H的類,實現(xiàn)對應的屬性和行為。當然,具體實現(xiàn)中有很多范式可參考和討論,我們也在摸索中,待后續(xù)慢慢補充……
DDD首先不是關于技術的,而是關于討論、聆聽、理解、發(fā)現(xiàn)業(yè)務價值的。——Vaughn Vernon《實現(xiàn)領域驅(qū)動設計》
如Vernon所說的,DDD首先是關注業(yè)務的價值的。一開始我們對業(yè)務的邊界、目標可能有個大概了解,但是見解還是不盡相同。
通過一起對業(yè)務的討論與思考,我們了解了業(yè)務的概貌及核心,明確價值所在。關注到了核心,自然可以幫助我們實現(xiàn)與業(yè)務契合的系統(tǒng)。通過這次學習與實踐,我們進一步接觸了DDD。
當然,這也還只是開始,更多的關聯(lián)知識還隱藏在冰山之下。同時我們也明白,DDD也只是一種方法論上的參考,不是“銀彈”,需要不斷地去實踐與思考,才能體會出它的價值。
參考:
作者:bryanzhao,微信支付后臺開發(fā)工程師
本文由 @騰訊大講堂 原創(chuàng)發(fā)布于人人都是產(chǎn)品經(jīng)理,未經(jīng)許可,禁止轉(zhuǎn)載。
題圖來自 Pixabay,基于CC0協(xié)議。
概念
SGML稱為:標準通用標記語言。
定義電子文檔結(jié)構(gòu)和描述其內(nèi)容的國際標準語言。
特點
1:通用標言為語法置標提供了異常強大的工具,同時具有極好的擴展性,因此在數(shù)據(jù)分類和索引中非常有用;
2:是所有 電子文檔標記語言的起源,早在萬維網(wǎng)發(fā)明之前“通用標言”就已存在。
只描述文檔標記應該是怎么樣的元語言。
總結(jié):HTML是SGML的一個實例,它的DTD作為標準被固定下來,因此,HTML不能作為定義其它置標語言的元語言。
概念
標記電子文件使其具有結(jié)構(gòu)性的標記語言,可擴展標記語言。
特點
1:結(jié)合
結(jié)合了HTML和SGML,是一種非常復雜的文檔的結(jié)構(gòu)。
2:友好
網(wǎng)站設計者可以定義自己的文檔類型。
用途
1:大量高度結(jié)構(gòu)化數(shù)據(jù)的防衛(wèi)區(qū)
2:其他各種工業(yè)領域,利于分類和索引。
下面是 小二哥 寫給 小二妹 的便簽,存儲為 XML:
<note>
<to>小二妹</to>
<from>小二哥</from>
<heading>Reminder</heading>
<body>記得給小伙伴們發(fā)福利哦!</body>
</note>
總結(jié):XML 被設計用來傳輸和存儲數(shù)據(jù),是擴展標記語言(EXtensible Markup Language),很類似 HTML。XML 的設計宗旨是傳輸數(shù)據(jù),而非顯示數(shù)據(jù),標簽沒有被預定義。需要自行定義標簽。具有自我描述性,是 W3C 的推薦標準。
DHTML 不是 W3C 標準。指動態(tài) HTML(Dynamic HTML)。
DHTML 不是由萬維網(wǎng)聯(lián)盟(W3C)規(guī)定的標準,是一個營銷術語 - 被網(wǎng)景公司(Netscape)和微軟公司用來描述 4.x 代瀏覽器應當支持的新技術。
用途
DHTML 是一種用來創(chuàng)建動態(tài)站點的技術組合物。
總結(jié):對大多數(shù)人來說,DHTML 意味著 HTML 4.0、樣式表以及 JavaScript 的結(jié)合物,是動態(tài)的HTML。
XHTML是更嚴格更純凈的 HTML 代碼。是指可擴展超文本標簽語言(EXtensible HyperText Markup Language)。
XHTML是當前HTML版的繼承者。HTML語法要求比較松散,這樣對網(wǎng)頁編寫者來說,比較方便,但對于機器來說,語言的語法越松散,處理起來就越困難,對于傳統(tǒng)的計算機來說,還有能力兼容松散語法,但對于許多其他設備,比如手機,難度就比較大。因此產(chǎn)生了由DTD定義規(guī)則,語法要求更加嚴格的XHTML。
實例:
<!DOCTYPE Doctype goes here>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Title goes here</title>
</head>
<body>
</body>
</html>
總結(jié):XHTML 的目標是取代 HTML,與 HTML 4.01 幾乎是相同的, 是更嚴格更純凈的 HTML 版本。XHTML 是作為一種 XML 應用被重新定義的 HTML。是一個 W3C 標準。
HTML5是下一代的 HTML。將成為 HTML、XHTML 以及 HTML DOM 的新標準。
HTML 的上一個版本誕生于 1999 年。自從那以后,Web 世界已經(jīng)經(jīng)歷了巨變。
HTML5 仍處于完善之中。然而,大部分現(xiàn)代瀏覽器已經(jīng)具備了某些 HTML5 支持。
特點
1:語義特性(Class:Semantic)
2:本地存儲特性(Class: OFFLINE & STORAGE)
3:設備兼容特性 (Class: DEVICE ACCESS)
4:連接特性(Class: CONNECTIVITY)
5:網(wǎng)頁多媒體特性(Class: MULTIMEDIA)
6:三維、圖形及特效特性(Class: 3D, Graphics & Effects)
一個簡單的媒體播放實例
<!DOCTYPE HTML>
<html>
<body>
<video width="320" height="240" controls="controls">
<source src="kecheng.ogg" type="video/ogg">
<source src="kecheng.mp4" type="video/mp4">
你的瀏覽器不支持html5,請更換瀏覽器。
</video>
</body>
</html>
總結(jié):至于html5和html就不用多講了吧。HTML5在2007年被萬維網(wǎng)聯(lián)盟(W3C)新的工作組采用。這個工作組在2008年1月發(fā)布了HTML 5的首個公開草案。眼下,HTML5處于“最火”狀態(tài),HTML5 已成為 HTML、XHTML 以及 HTML DOM 的新標準。
上面分別介紹了SGML、XML、DHTML、XHTML、HTML5和HTML的之間的關系。順便也看看HTML吧。
概念
超文本標記語言,標準通用標記語言下的一個應用。
特點
1:一種規(guī)范。
2:一種標準。
3:簡單但是功能強大,靈活方便。
4:具有極強的擴展性。
5:不牽扯平臺。
實例:
<html>
<body>
<h1>這個是標題</h1>
<p>這個是段落。</p>
</body>
</html>
總結(jié):是用來描述網(wǎng)頁的一種超文本標記語言 (Hyper Text Markup Language), 不是一種編程語言,而是一種標記語言 (markup language),使用標記標簽來描述網(wǎng)頁。
·歡迎留言評論哦~
.它是一種計算機(PC)的超文本標記語言(Hyper Text Markup Language),縮寫為HTML,HTML是一種標記語言(markup language),是制作網(wǎng)頁所必備的語言,語法較為松散,不嚴格的web語言;標簽可以不閉合,不區(qū)分大小寫。
2.標記標簽通常被稱為HTML標簽,標簽由尖括號包圍的關鍵字組成,通常都是成對出現(xiàn)的,有開始標簽和結(jié)束標簽,如<html></html>。
瀏覽器不會顯示html標簽(白話:瀏覽器只會顯示標簽里邊的內(nèi)容),而是使用標簽來解釋頁面的內(nèi)容。
比如這一行代碼:<body>你好 </body>要放在<html></html>里邊,網(wǎng)頁只展示了你好 其他內(nèi)容并沒有展示。
代碼
頁面
以下資料均由自己的認知和資料整理所得:
1989年,歐洲物理量子實驗室(CERN)的信息專家蒂姆·伯納斯·李發(fā)明了超文本鏈接語言, 使用此語言能輕松地將一個文件中的文字或圖形連到其它的文件中去,這就是HTML的前身。1991年,蒂姆伯·納斯·李在CERN定義了HTML語言的第一個規(guī)范,之后成為W3C組織為專門在互聯(lián)網(wǎng)上發(fā)布信息而設計的符號化語言規(guī)范。可以說,HTML(Hypertext Markup Language)是SGML的一個實例,它的DTD作為標準被固定下來。因此,HTML不能作為定義其它符號化語言的元語言。
作為World Wide Web的一個組成部分,HTML語言發(fā)展很快,在短短的幾年里,它已歷經(jīng)了HTML1.0、HTML2.0和HTML3.0、HTML4.0等多個版本,同時DHTML (動態(tài))、VHTML(虛擬)、SHTML等也飛速發(fā)展起來。HTML以簡單精練的語法、極易掌握的通用性與易學性,使Web網(wǎng)頁可以親近于每一個普通人,互聯(lián)網(wǎng)因此得以普及發(fā)展以至今日輝煌。
但是,目前的HTML還不穩(wěn)定,不同的瀏覽器會產(chǎn)生不同的顯示效果。此外,由于HTML對超級鏈接支持不足,并缺乏空間立體描述,處理圖形、圖像、音頻、視頻等多媒體能力較弱,圖文混排功能簡單,不能表示多種媒體的同步關系等缺點,也影響HTML的大規(guī)模應用以及用于復雜的多媒體數(shù)據(jù)處理,一種語言各有各的優(yōu)點和缺點。
人們常常贊美蒂姆·伯納斯·李“與其他所有推動人類進程的發(fā)明不同,這是一件純粹個人的勞動成果,萬維網(wǎng)只屬于蒂姆·伯納斯·李一個人。”而這個心懷浪漫、獻身科學的英國學者,卻將只屬于他一個人的發(fā)明,無償獻給了世界。
*請認真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。