關(guān)于我們
書(shū)單推薦
新書(shū)推薦
|
深入實(shí)踐 DDD:以 DSL 驅(qū)動(dòng)復(fù)雜軟件開(kāi)發(fā) 本書(shū)是擁有二十年商業(yè)軟件開(kāi)發(fā)經(jīng)驗(yàn)及十年技術(shù)管理經(jīng)驗(yàn)的資深技術(shù)專(zhuān)家嘔心瀝血之作,也是目前市場(chǎng)上少有的闡述如何通過(guò)使用領(lǐng)域?qū)S谜Z(yǔ)言(DSL)實(shí)現(xiàn)領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)(DDD)的圖書(shū)。 書(shū)中首先帶領(lǐng)讀者重溫DDD在戰(zhàn)術(shù)設(shè)計(jì)層面及戰(zhàn)略設(shè)計(jì)層面上的部分重要概念,并簡(jiǎn)要介紹了自DDD社區(qū)興起的一些軟件架構(gòu)模式。然后闡述如何設(shè)計(jì)一門(mén)DDD原生的DSL,包括這個(gè)DSL的規(guī)范支持哪些特性、如何幫助團(tuán)隊(duì)描述領(lǐng)域模型的方方面面、這些特性的選擇基于何種考量等。 然后在此基礎(chǔ)上詳細(xì)講解了如何使用技術(shù)工具將描述領(lǐng)域模型的DSL文檔直接轉(zhuǎn)化為可以工作的軟件代碼,在這個(gè)過(guò)程中結(jié)合諸多來(lái)自商業(yè)軟件開(kāi)發(fā)工作中的真實(shí)案例,展示并分析了大量的關(guān)鍵代碼,讓讀者可以深入地了解制造那些基于DSL的DDD技術(shù)工具的秘密。 之后講述了一些建模案例,并探討了一些與DDD相關(guān)的其他話(huà)題,對(duì)讀者開(kāi)拓技術(shù)思維、更深刻地理解DDD有所助益。 適讀人群 :1. 產(chǎn)品經(jīng)理與系統(tǒng)分析師。產(chǎn)品經(jīng)理不應(yīng)該僅僅關(guān)注軟件的界面原型、用戶(hù)體驗(yàn),產(chǎn)品經(jīng)理需要保證團(tuán)隊(duì)所開(kāi)發(fā)的是 “正確的軟件”。正確的軟件應(yīng)該邏輯自洽,功能處處傳達(dá)出那個(gè) (1)領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)里程碑之作,資深技術(shù)專(zhuān)家兼技術(shù)管理者二十年工作經(jīng)驗(yàn)結(jié)晶 (2)深度解讀DDD思想,揭示使用 DSL實(shí)現(xiàn)DDD快速落地的方法與技巧,緩解復(fù)雜軟件開(kāi)發(fā)之痛 【為什么要寫(xiě)這本書(shū)】 2004 年,DDD(領(lǐng)域驅(qū)動(dòng)設(shè)計(jì))這一軟件開(kāi)發(fā)的方法與愿景經(jīng)由建模專(zhuān)家 Eric Evans 的經(jīng)典著作Domain-Driven Design: Tackling Complexity in the Heart of Software 正式面世,當(dāng)即獲得了廣泛關(guān)注和高度評(píng)價(jià)。16 年過(guò)去了,我在網(wǎng)上看到越來(lái)越多關(guān)于 DDD的文章和討論。為什么我們現(xiàn)在還不停地討論 DDD?為什么DDD仍然如此重要? 在商業(yè)組織中,主張“技術(shù)為業(yè)務(wù)服務(wù)”的企業(yè)總可以在理論上立于不敗之地。誠(chéng)然,DDD主張?jiān)谲浖?xiàng)目中把領(lǐng)域本身作為關(guān)注的焦點(diǎn)(換句話(huà)說(shuō)就是技術(shù)人員要懂業(yè)務(wù))符合這種思想,但真正難能可貴的是,DDD提供了切實(shí)可行的應(yīng)對(duì)軟件核心復(fù)雜性的方法。 實(shí)踐證明,DDD 提出的方法不僅行之有效,而且歷久彌新。關(guān)于這一點(diǎn),我想從當(dāng)今 IT 業(yè)界的熱詞“云原生”“中臺(tái)”“產(chǎn)業(yè)互聯(lián)網(wǎng)”說(shuō)起。 什么是云原生?云原生計(jì)算基金會(huì)(Cloud Native Computing Foundation,CNCF)對(duì)云原生的定義是: 云原生技術(shù)有利于各組織在公有云、私有云和混合云等新型動(dòng)態(tài)環(huán)境中構(gòu)建和運(yùn)行可彈性擴(kuò)展的應(yīng)用。云原生的代表技術(shù)包括容器、服務(wù)網(wǎng)格、微服務(wù)、不可變基礎(chǔ)設(shè)施和聲明式 API。 這些技術(shù)能夠構(gòu)建容錯(cuò)性好、易于管理和便于觀察的松耦合系統(tǒng)。結(jié)合可靠的自動(dòng)化手段,云原生技術(shù)使工程師能夠輕松地對(duì)系統(tǒng)做出頻繁和可預(yù)測(cè)的重大變更。 而阿里云發(fā)布的《云原生架構(gòu)白皮書(shū)》 對(duì)云原生架構(gòu)的定義是: 從技術(shù)的角度看,云原生架構(gòu)是基于云原生技術(shù)的一組架構(gòu)原則和設(shè)計(jì)模式的集合,旨在將云應(yīng)用中的非業(yè)務(wù)代碼部分進(jìn)行最大化剝離,從而讓云設(shè)施接管應(yīng)用中原有的大量非功能特性(如彈性、韌性、安全、 可觀測(cè)性、灰度等),使業(yè)務(wù)不再有非功能性業(yè)務(wù)中斷困擾的同時(shí),具備輕量、敏捷、高度自動(dòng)化的特點(diǎn)。 看了這些定義,你是否還是覺(jué)得迷惑?打開(kāi)CNCF的“l(fā)andscape”頁(yè)面——里面有很多的項(xiàng)目和成員,難怪有人說(shuō)云原生是一個(gè)“營(yíng)銷(xiāo)詞語(yǔ)”。在這個(gè)頁(yè)面中,在 Members(成員)這個(gè)標(biāo)簽頁(yè)的左邊,Serverless 獨(dú)占了一個(gè)標(biāo)簽頁(yè),十分顯眼。 廣泛認(rèn)同的Serverless 架構(gòu)是指這樣的應(yīng)用設(shè)計(jì):與第三方的后端即服務(wù)(Backend as a Service,BaaS)交互;在函數(shù)即服務(wù)(Function as a Service,F(xiàn)aaS)平臺(tái)上運(yùn)行函數(shù)式業(yè)務(wù)代碼,一般來(lái)說(shuō),它們是在受管理的、臨時(shí)性的容器中執(zhí)行的。 雖然新出現(xiàn)的基于容器的 Serverless 平臺(tái),比如 Knative,可以運(yùn)行開(kāi)發(fā)人員使用傳統(tǒng)方式開(kāi)發(fā)的應(yīng)用,但 FaaS 仍然是 Serverless 中最重要、最具代表性的產(chǎn)品形態(tài),因?yàn)樗屛覀円砸环N不同于傳統(tǒng)的方式思考技術(shù)架構(gòu)。 FaaS 中的“Function”就是不依賴(lài)特定框架和類(lèi)庫(kù)的最純粹的業(yè)務(wù)代碼——這是真正為業(yè)務(wù)帶來(lái)價(jià)值的東西?梢哉f(shuō),F(xiàn)aaS在將云應(yīng)用中的非業(yè)務(wù)代碼部分進(jìn)行最大化剝離方面做到了極致。我認(rèn)為它是云原生“皇冠上的明珠”。 不過(guò),大家普遍認(rèn)為當(dāng)前FaaS更適合開(kāi)發(fā)事件驅(qū)動(dòng)風(fēng)格的、處理少數(shù)幾個(gè)事件類(lèi)型的應(yīng)用組件,而不適合開(kāi)發(fā)傳統(tǒng)的具有很多入口的同步請(qǐng)求/響應(yīng)風(fēng)格的應(yīng)用組件。也就是說(shuō),如果你想問(wèn):“能不能基于 FaaS 做出一個(gè) SAP ERP?”目前可能大多數(shù)人給你的答案會(huì)是“NO”。 但是我想給你的答案是“YES”!因?yàn)橐脒_(dá)到這個(gè)目標(biāo),我們需要克服的所有障礙都不屬于 FaaS 的固有缺點(diǎn),而是當(dāng)前FaaS 的實(shí)現(xiàn)缺陷,比如啟動(dòng)延遲、集成測(cè)試、調(diào)試、交付、監(jiān)控與觀測(cè)等方面的問(wèn)題。 我認(rèn)為,以 DDD 方法實(shí)現(xiàn)的應(yīng)用可以極大地降低 FaaS 處理這些問(wèn)題的難度,甚至可以直接忽視某些問(wèn)題(因?yàn)樗鼈儗?duì)以 DDD 方法實(shí)現(xiàn)的應(yīng)用來(lái)說(shuō)不是問(wèn)題)。具體而言,我們可以使用 DDD 的聚合概念來(lái)切分應(yīng)用組件,每個(gè)聚合一個(gè)小組件,它們可以很快地被 FaaS 平臺(tái)“拉起”。這些高度內(nèi)聚的小組件是更復(fù)雜的應(yīng)用組件(比如說(shuō)領(lǐng)域服務(wù))的構(gòu)造塊。我們可以使用興起于 DDD 社區(qū)的 Event Sourcing(事件溯源,ES)模式,保證應(yīng)用狀態(tài)的每一次變更都會(huì)發(fā)布領(lǐng)域事件,并以富含業(yè)務(wù)語(yǔ)義的事件驅(qū)動(dòng)其他應(yīng)用組件運(yùn)行。比如,命令查詢(xún)職責(zé)分離(Command Query Responsibility Segregation,CQRS)模式中的 Denormalizer(去規(guī)范化器)組件就可以訂閱、消費(fèi)這些事件,為前端應(yīng)用構(gòu)建友好的查詢(xún)視圖——這些都是 DDD 社區(qū)在開(kāi)發(fā)嚴(yán)肅的商業(yè)軟件時(shí)一直在做的事情。如果之前你沒(méi)有接觸過(guò)聚合、ES、CQRS,也許難以理解上面所說(shuō)的內(nèi)容,不過(guò)沒(méi)關(guān)系,讀完本書(shū),我相信你就清楚了。 再說(shuō)“中臺(tái)”這個(gè)熱詞。以我的理解,中臺(tái)是將可復(fù)用的代碼抽取到一個(gè)平臺(tái)中,作為大家共用的軟件組件,它是服務(wù)于前臺(tái)的規(guī);瘎(chuàng)新。中臺(tái)(這里主要指業(yè)務(wù)中臺(tái))想要好用,必須具備“反映對(duì)領(lǐng)域的深度認(rèn)知”的軟件模型,甚至在某種程度上需要“過(guò)度設(shè)計(jì)”,并且絕對(duì)有必要維護(hù)良好的概念完整性,構(gòu)建所謂的企業(yè)級(jí)業(yè)務(wù)架構(gòu)——這些都是 DDD 可以大展身手的地方。 關(guān)于“產(chǎn)業(yè)互聯(lián)網(wǎng)即將進(jìn)入黃金時(shí)代”的說(shuō)法,大多是眾多傳統(tǒng)企業(yè)希望借力最新的信息化,特別是互聯(lián)網(wǎng)工具(即所謂“互聯(lián)網(wǎng)+”),提升內(nèi)部效率和對(duì)外服務(wù)的能力。傳統(tǒng)產(chǎn)業(yè)中的很多領(lǐng)域概念和業(yè)務(wù)流程并不一定為普通的開(kāi)發(fā)者所熟知——這與“消費(fèi)互聯(lián)網(wǎng)”不同,顯然人人都是消費(fèi)者。所以,傳統(tǒng)產(chǎn)業(yè)的信息化急需可以快速梳理并深刻地認(rèn)知領(lǐng)域,以及能構(gòu)建高質(zhì)量領(lǐng)域模型的技術(shù)人才。DDD 可以說(shuō)是技術(shù)人員升職加薪的“神兵利器”。 我在工作中看到的情況是,越來(lái)越多的技術(shù)人員在自己的求職簡(jiǎn)歷上寫(xiě)上了“熟悉(或精通)DDD”的描述。確實(shí),Eric Evans 的經(jīng)典著作以抽象、凝練著稱(chēng),可謂字字珠璣,甚至很多資深技術(shù)人員都不能領(lǐng)悟其中玄妙。所以,我也認(rèn)同掌握 DDD 是一件足以讓技術(shù)人員引以為傲的事情。 可以說(shuō),DDD 是公認(rèn)的解決軟件核心復(fù)雜性的“大殺器”。但是,在軟件開(kāi)發(fā)中實(shí)踐 DDD 是需要付出相當(dāng)大的成本的。也就是說(shuō),大家的普遍看法是:實(shí)踐 DDD 是一個(gè)先苦后甜的過(guò)程,一個(gè)項(xiàng)目要不要采用DDD,最好先看看它值不值得。 但是一個(gè)項(xiàng)目值不值得使用 DDD 有時(shí)不好判斷。大項(xiàng)目往往是由小項(xiàng)目發(fā)展而來(lái)的,很多從小項(xiàng)目演化而來(lái)的大系統(tǒng)最終變成開(kāi)發(fā)團(tuán)隊(duì)的噩夢(mèng),噩夢(mèng)的根源幾乎無(wú)一例外地在于軟件的概念完整性遭到了破壞。而DDD正是維護(hù)軟件概念完整性的良藥。如果在項(xiàng)目中實(shí)踐 DDD 的成本不高,那么即使是小項(xiàng)目,從一開(kāi)始就使用 DDD 不是一件很美好的事情嗎? 在軟件開(kāi)發(fā)項(xiàng)目中實(shí)踐 DDD 到底有何難處?16 年了,難道在 DDD 實(shí)踐中碰到的問(wèn)題我們不能從書(shū)本中尋得答案? 目前國(guó)內(nèi)已經(jīng)出版的DDD相關(guān)圖書(shū)中,除了 Eric Evans 的經(jīng)典著作之外,還有《實(shí)現(xiàn)領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)》《領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)精粹》《領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)模式、原理與實(shí)踐》等,不過(guò)寥寥數(shù)本。這與 DDD 的巨大聲望很不匹配,這也許說(shuō)明了一些問(wèn)題。 實(shí)踐DDD首先需要面對(duì)的一個(gè)(也許是最大的)難題是:難以描述的領(lǐng)域模型。 DDD 想要構(gòu)建的領(lǐng)域模型是什么?按照 Eric Evans 的觀點(diǎn),領(lǐng)域模型不是一幅具體的圖,而是那幅圖想要傳達(dá)的思想;不是一個(gè)領(lǐng)域?qū)<翌^腦中的知識(shí),而是那些經(jīng)過(guò)嚴(yán)格組織并進(jìn)行選擇性抽象的知識(shí)。 聽(tīng)起來(lái)是不是有點(diǎn)玄奧?系統(tǒng)分析師、產(chǎn)品經(jīng)理到底要拿出什么樣的領(lǐng)域模型才能說(shuō) “我的工作已經(jīng)做到位了”?這個(gè)模型到底是不是可以實(shí)現(xiàn)的?開(kāi)發(fā)人員、測(cè)試人員到底有沒(méi)有理解這個(gè)模型?大家的理解是不是一致的? 說(shuō)到底,一個(gè)領(lǐng)域模型要想有用,它必須足夠嚴(yán)格。如何使用一種嚴(yán)格的方式描述經(jīng)過(guò)嚴(yán)格組織并進(jìn)行選擇性抽象的知識(shí)呢? 問(wèn)題的答案很自然地指向了 DSL。 其實(shí),Eric Evans 早就意識(shí)到了這一點(diǎn)。他曾經(jīng)在訪談中說(shuō): 更多前沿的話(huà)題發(fā)生在領(lǐng)域?qū)S谜Z(yǔ)言(DSL)領(lǐng)域,我一直深信 DSL 會(huì)是領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)發(fā)展的下一大步,F(xiàn)在,還沒(méi)有一個(gè)工具可以真正給我們想要的東西。但是人們?cè)谶@一領(lǐng)域比過(guò)去做了更多的實(shí)驗(yàn),這使我對(duì)未來(lái)充滿(mǎn)了希望。 通過(guò)本書(shū),我想要告訴大家的是:在項(xiàng)目中運(yùn)用 DDD 可以不像大家想象的那么痛苦,DDD 并不是只適用于大項(xiàng)目,使用 DDD 并不一定需要犧牲敏捷性,一切的關(guān)鍵在于 DSL 的運(yùn)用。 我和我工作過(guò)的團(tuán)隊(duì)曾經(jīng)在多個(gè)項(xiàng)目中使用 DSL 實(shí)現(xiàn)了 DDD 的真正落地。獨(dú)樂(lè)樂(lè)不如眾樂(lè)樂(lè)!現(xiàn)在,我想把這些實(shí)踐經(jīng)驗(yàn)分享給大家。 【讀者對(duì)象】 領(lǐng)域模型是一種“思想”,它可以為軟件開(kāi)發(fā)的全過(guò)程提供指導(dǎo),所以我相信本書(shū)可以為很多人提供幫助: 產(chǎn)品經(jīng)理與系統(tǒng)分析師。產(chǎn)品經(jīng)理不僅僅需要保證團(tuán)隊(duì)開(kāi)發(fā)的是“正確的軟件”,也不應(yīng)該只是關(guān)注軟件的界面原型、用戶(hù)體驗(yàn),更應(yīng)該讓軟件有內(nèi)涵。迷人的產(chǎn)品不僅需要漂亮的界面和交互,更需要邏輯自洽,功能處處傳達(dá)出一個(gè)思想——優(yōu)美而深刻的領(lǐng)域模型。在有的團(tuán)隊(duì)中,產(chǎn)品經(jīng)理同時(shí)也是系統(tǒng)分析師。作為近十幾年來(lái)最有影響力的軟件分析和設(shè)計(jì)的方法論,系統(tǒng)分析師有必要了解DDD,從中汲取營(yíng)養(yǎng)。 架構(gòu)師。架構(gòu)師需要根據(jù)業(yè)務(wù)需求提供技術(shù)解決方案。DDD 想要構(gòu)建的領(lǐng)域模型不僅僅是領(lǐng)域業(yè)務(wù)知識(shí)的提煉總結(jié),也包含了對(duì)軟件設(shè)計(jì)的考量,可以用于直接指導(dǎo)軟件的編碼實(shí)現(xiàn)。構(gòu)建這樣的模型,需要架構(gòu)師的積極參與。 開(kāi)發(fā)工程師。開(kāi)發(fā)工程師應(yīng)該理解領(lǐng)域模型,領(lǐng)域模型應(yīng)該被忠實(shí)地映射到代碼實(shí)現(xiàn)中。代碼中對(duì)象的命名、對(duì)象之間的關(guān)系,都應(yīng)該與領(lǐng)域模型一致。唯有如此,代碼才能具備良好的可讀性、可維護(hù)性,敏捷 XP 方法的狂熱愛(ài)好者們所言的“代碼即文檔”才可能實(shí)現(xiàn)。 測(cè)試工程師。如今很多測(cè)試工程師已經(jīng)被稱(chēng)為“測(cè)試開(kāi)發(fā)工程師”,他們也應(yīng)該理解領(lǐng)域模型。測(cè)試工程師應(yīng)該像產(chǎn)品經(jīng)理一樣了解軟件的設(shè)計(jì),甚至應(yīng)該比產(chǎn)品經(jīng)理更深刻地理解領(lǐng)域模型面向軟件設(shè)計(jì)所做的考量。實(shí)例化需求的自動(dòng)化測(cè)試(或者說(shuō)行為驅(qū)動(dòng)測(cè)試)應(yīng)該基于領(lǐng)域模型,而非基于 UI/UE 來(lái)構(gòu)建,因?yàn)橛脩?hù)界面以及用戶(hù)交互是易變的,而領(lǐng)域模型相對(duì)來(lái)說(shuō)穩(wěn)定得多。 項(xiàng)目經(jīng)理。項(xiàng)目經(jīng)理是負(fù)責(zé)“正確開(kāi)發(fā)軟件”的人。如果不深刻理解領(lǐng)域,不知道如何抓住領(lǐng)域模型中的關(guān)鍵點(diǎn),會(huì)很難評(píng)估任務(wù)工作量的大小以及應(yīng)該在何處投入足夠的資源,甚至無(wú)法判斷項(xiàng)目的實(shí)際進(jìn)度。 高校研究生以及其他有志于從事 IT 行業(yè)的人。 【如何閱讀本書(shū)】 本書(shū)的第一部分會(huì)帶領(lǐng)讀者從戰(zhàn)術(shù)層面以及戰(zhàn)略層面重溫領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的重要概念,然后進(jìn)一步闡述Eric Evans經(jīng)典著作中沒(méi)有顯式提出的或者被太多人忽略的但我認(rèn)為對(duì) DDD 落地非常重要的若干概念,同時(shí)簡(jiǎn)要介紹從 DDD 社區(qū)興起的一些軟件架構(gòu)模式。通過(guò)第一部分,讀者可以更完整、更深刻地掌握 DDD 的知識(shí)體系。 第二部分闡述如何設(shè)計(jì)一種DDD的DSL,包括這個(gè)DSL的規(guī)范(Specification)支持哪些特性、如何幫助團(tuán)隊(duì)描述領(lǐng)域模型的方方面面、這些特性的選擇基于何種考量等。 這種領(lǐng)域?qū)S谜Z(yǔ)言需要一個(gè)名字,我們總不能一直說(shuō)“我設(shè)計(jì)的 DDD 的 DSL”吧,于是我給它起了一個(gè)名字:DDDML。我認(rèn)為這是一個(gè)很棒的名字。其實(shí)這種語(yǔ)言叫什么并不太重要,重要的是它可以用一種足夠嚴(yán)格的方式描述領(lǐng)域模型。我認(rèn)為目前它在簡(jiǎn)單與復(fù)雜之間取得了不錯(cuò)的平衡。當(dāng)然,其中還有不小改進(jìn)的空間。比如,我很樂(lè)意讓它支持更多像“賬務(wù)模式”這樣的分析模式。 第三部分介紹如何將“思想照進(jìn)實(shí)現(xiàn)”——通過(guò)使用工具將描述領(lǐng)域模型的 DSL 文檔變成可以運(yùn)行的軟件。這個(gè)過(guò)程涉及大量的技術(shù)工具(工具鏈)的設(shè)計(jì)與實(shí)現(xiàn)。只有將這些技術(shù)工具——比如從 DSL 自動(dòng)生成應(yīng)用的源代碼的模板——實(shí)現(xiàn)出來(lái),才能減輕開(kāi)發(fā)人員實(shí)踐 DDD 的負(fù)擔(dān),進(jìn)而提升而不是降低軟件團(tuán)隊(duì)的生產(chǎn)效率。本部分會(huì)介紹這些技術(shù)工具設(shè)計(jì)與實(shí)現(xiàn)的細(xì)節(jié)。 我和我的同事把自制的 DDDML 工具鏈稱(chēng)為 DDDML Tools。出于商業(yè)原因,我無(wú)法展示這些工具的源代碼,但是會(huì)詳盡地展示這些工具運(yùn)行的結(jié)果——主要是由工具生成的應(yīng)用的源代碼。這些源代碼可能經(jīng)過(guò)一些簡(jiǎn)化,但是與我們?cè)谏a(chǎn)系統(tǒng)上運(yùn)行的代碼十分接近,完全可以說(shuō)明問(wèn)題。 讀完全書(shū),你將發(fā)現(xiàn)其實(shí)我們已經(jīng)全無(wú)秘密。你會(huì)熟知 DDDML 的規(guī)范,見(jiàn)到工具運(yùn)行的結(jié)果,你幾乎可以馬上動(dòng)手制造自己的 DDDML 工具。其實(shí)設(shè)計(jì) DDDML 的規(guī)范才是整件事情(使用 DSL 實(shí)現(xiàn)領(lǐng)域驅(qū)動(dòng)設(shè)計(jì))中最難的部分,制作工具不是。雖然想要復(fù)刻我們已經(jīng)做過(guò)的所有工具確實(shí)需要相當(dāng)大的工作量,但也僅僅是工作量而已。 幸運(yùn)的是,你并不需要制造整條 DDDML 的工具鏈才可以享受使用 DSL 的樂(lè)趣。比如,你可以先寫(xiě)一些模板,生成一些持久對(duì)象(Persistant Object),它們無(wú)非是一些簡(jiǎn)單的 Java 對(duì)象(Plain Ordinary Java Object,POJO),然后再生成一些 O/R Mapping XML,就可以馬上使用 JPA/Hibernate 來(lái)實(shí)現(xiàn)應(yīng)用的 DAL(數(shù)據(jù)訪問(wèn)層)了。如果你再生成 Repository,那就更漂亮啦! 第四部分講述的是一些建模案例以及其他與 DDD 相關(guān)的話(huà)題。領(lǐng)域模型是一種思想,DSL 是一種工具,但是如何運(yùn)用、結(jié)果如何,因人而異。我希望通過(guò)輕松的漫談和隨想,將我的一點(diǎn)DDD應(yīng)用經(jīng)驗(yàn)分享給大家。 楊捷鋒, 曾就職于南開(kāi)戈德集團(tuán)、普天集團(tuán)、通路快建等公司。曾作為獨(dú)立技術(shù)顧問(wèn)為海爾集團(tuán)、沈陽(yáng)飛機(jī)工業(yè)集團(tuán)、上廣電NEC、天馬微電子等企業(yè)提供軟件開(kāi)發(fā)與技術(shù)咨詢(xún)服務(wù)。目前在一家電商創(chuàng)業(yè)公司擔(dān)任技術(shù)負(fù)責(zé)人。有多個(gè)大型企業(yè)應(yīng)用軟件的分析建模經(jīng)驗(yàn),以及大型開(kāi)發(fā)框架(ORM、IoC等)的架構(gòu)經(jīng)驗(yàn)。多年來(lái)一直未脫離軟件開(kāi)發(fā)一線(xiàn)工作,對(duì)軟件系統(tǒng)分析、數(shù)據(jù)建模、領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)、項(xiàng)目管理略有心得。 【第一部分 概念】 第1章 DDD 的關(guān)鍵概念 2 1.1 自頂而下、逐步求精 3 1.1.1 DDD開(kāi)創(chuàng)全新分析流派 3 1.1.2 什么是軟件的核心復(fù)雜性 4 1.2 什么是領(lǐng)域模型 4 1.3 戰(zhàn)術(shù)層面的關(guān)鍵概念 6 1.3.1 實(shí)體 6 1.3.2 值對(duì)象 6 1.3.3 聚合與聚合根、聚合內(nèi)部實(shí)體 7 1.3.4 聚合的整體與局部 9 1.3.5 聚合是數(shù)據(jù)修改的單元 9 1.3.6 聚合分析是“拆分”的基礎(chǔ) 10 1.3.7 服務(wù) 12 1.4 戰(zhàn)略層面的關(guān)鍵概念 13 1.4.1 限界上下文 13 1.4.2 限界上下文與微服務(wù) 14 1.4.3 防腐層 15 1.4.4 統(tǒng)一語(yǔ)言 18 1.5 ER 模型、OO模型和關(guān)系模型 19 1.6 概念建模與模型范式 21 第2章 其他DDD相關(guān)概念 22 2.1 領(lǐng)域 ID 22 2.1.1 自然鍵與代理鍵 23 2.1.2 DDD 實(shí)體的 ID 需要被最終用戶(hù)看到 23 2.1.3 什么時(shí)候使用代理鍵 24 2.2 ID、Local ID 與 Global ID 26 2.3 命令、事件與狀態(tài) 27 第3章 CQRS 與 Event Sourcing 29 3.1 命令查詢(xún)職責(zé)分離 29 3.2 事件溯源 32 3.3 From-Thru 模式 33 3.3.1 示例:ProductPrice 33 3.3.2 示例:PartyRelationship 35 3.4 CQRS、ES 與流處理 36 【第二部分 設(shè)計(jì)】 第4章 DDD 的 DSL是什么 40 4.1 為什么 DDD 需要 DSL 41 4.1.1 為什么實(shí)現(xiàn) DDD 那么難 41 4.1.2 搞定 DDD 的“錘子”在哪里 42 4.2 需要什么樣的 DSL 43 4.2.1 在“信仰”上保持中立 44 4.2.2 DDD 原生 45 4.2.3 在復(fù)雜和簡(jiǎn)單中平衡 46 4.2.4 通過(guò) DSL 重塑軟件開(kāi)發(fā)過(guò)程 48 4.3 DDDML——DDD 的 DSL 48 4.3.1 DDDML 的詞匯表 49 4.3.2 DDDML 的 Schema 51 4.4 DDDML 示例:Car 52 4.4.1 “對(duì)象”的名稱(chēng)在哪里 55 4.4.2 使用兩種命名風(fēng)格:camelCase 與 PascalCase 55 4.4.3 為何引入關(guān)鍵字 itemType 56 第5章 限界上下文 57 5.1 DDDML 文檔的根結(jié)點(diǎn)下有什么 57 5.2 限界上下文的配置 59 5.3 名稱(chēng)空間 62 5.3.1 再談 PascalCase 命名風(fēng)格 62 5.3.2 注意兩個(gè)字母的首字母縮寫(xiě)詞 63 5.4 關(guān)于模塊 64 第6章 值對(duì)象 67 6.1 領(lǐng)域基礎(chǔ)類(lèi)型 68 6.1.1 例子:從 OFBiz 借鑒過(guò)來(lái)的類(lèi)型系統(tǒng) 70 6.1.2 例子:任務(wù)的觸發(fā)器 73 6.2 數(shù)據(jù)值對(duì)象 75 6.3 枚舉對(duì)象 76 第7章 聚合與實(shí)體 79 7.1 用同一個(gè)結(jié)點(diǎn)描述聚合及聚合根 79 7.2 實(shí)體之間只有一種基本關(guān)系 82 7.3 關(guān)于實(shí)體的 ID 85 7.4 不變的實(shí)體 89 7.5 動(dòng)態(tài)對(duì)象 90 7.6 繼承與多態(tài) 92 7.6.1 使用關(guān)鍵字 inheritedFrom 94 7.6.2 超對(duì)象 95 7.7 引用 97 7.7.1 定義實(shí)體的引用 97 7.7.2 屬性的類(lèi)型與引用類(lèi)型 101 7.8 基本屬性與派生屬性 102 7.8.1 類(lèi)型為實(shí)體集合的派生屬性 103 7.8.2 類(lèi)型為值對(duì)象的派生屬性 106 7.9 約束 107 7.9.1 在實(shí)體層面的約束 107 7.9.2 在屬性層面的約束 109 7.10 提供擴(kuò)展點(diǎn) 110 第8章 超越數(shù)據(jù)模型 112 8.1 實(shí)體的方法 112 8.1.1 聚合根的方法 115 8.1.2 非聚合根實(shí)體的方法 116 8.1.3 屬性的命令 117 8.1.4 命令 ID 與請(qǐng)求者 ID 119 8.2 記錄業(yè)務(wù)邏輯 119 8.2.1 關(guān)于 accountingQuantityTypes 120 8.2.2 關(guān)于 derivationLogic 120 8.2.3 關(guān)于 filter 121 8.2.4 使用關(guān)鍵字referenceFilter 121 8.2.5 業(yè)務(wù)邏輯代碼中的變量 122 8.2.6 說(shuō)說(shuō)區(qū)塊鏈 123 8.3 領(lǐng)域服務(wù) 123 8.4 在方法定義中使用關(guān)鍵字 inheritedFrom 125 8.5 方法的安全性 126 第9章 模式 128 9.1 賬務(wù)模式 128 9.2 狀態(tài)機(jī)模式 132 9.3 樹(shù)結(jié)構(gòu)模式 137 9.3.1 簡(jiǎn)單的樹(shù) 137 9.3.2 使用關(guān)鍵字structureType 138 9.3.3 使用關(guān)鍵字structureTypeFilter 139 【第三部分 實(shí)踐】 第10章 處理限界上下文與值對(duì)象 142 10.1 項(xiàng)目文件 143 10.2 處理值對(duì)象 144 10.2.1 一個(gè)需要處理的數(shù)據(jù)值對(duì)象示例 145 10.2.2 使用 Hibernate 存儲(chǔ)數(shù)據(jù)值對(duì)象 146 10.2.3 處理值對(duì)象的集合 149 10.2.4 在 URL 中使用數(shù)據(jù)值對(duì)象 151 10.2.5 處理領(lǐng)域基礎(chǔ)類(lèi)型 153 第11章 處理聚合與實(shí)體 161 11.1 生成聚合的代碼 162 11.1.1 接口 163 11.1.2 代碼中的命名問(wèn)題 178 11.1.3 接口的實(shí)現(xiàn) 179 11.1.4 事件存儲(chǔ)與持久化 207 11.1.5 使用 Validation 框架 218 11.1.6 保證靜態(tài)方法與模型同步更新 220 11.1.7 不使用事件溯源 222 11.2 Override 聚合對(duì)象的方法 223 11.3 處理繼承 225 11.3.1 TPCH 226 11.3.2 TPCC 227 11.3.3 TPS 228 11.4 處理模式 229 11.4.1 處理賬務(wù)模式 229 11.4.2 處理狀態(tài)機(jī)模式 234 第12章 處理領(lǐng)域服務(wù) 238 12.1 處理數(shù)據(jù)的一致性 239 12.1.1 使用數(shù)據(jù)庫(kù)事務(wù)實(shí)現(xiàn)一致性 240 12.1.2 使用 Saga 實(shí)現(xiàn)最終一致性 241 12.2 發(fā)布與處理領(lǐng)域事件 243 12.2.1 編寫(xiě) DDDML 文檔 243 12.2.2 生成的事件發(fā)布代碼 245 12.2.3 編寫(xiě)生產(chǎn)端聚合的業(yè)務(wù)邏輯 253 12.2.4 實(shí)現(xiàn)消費(fèi)端領(lǐng)域事件的處理 254 12.3 支持基于編制的 Saga 255 12.3.1 編寫(xiě) DDDML 文檔 255 12.3.2 生成的 Saga 命令處理代碼 261 12.3.3 需要我們編寫(xiě)的 Saga 代碼 268 12.3.4 需要我們實(shí)現(xiàn)的實(shí)體方法 273 第13章 RESTful API 276 13.1 RESTful API 的最佳實(shí)踐 276 13.1.1 沒(méi)有必要絞盡腦汁地尋找名詞 277 13.1.2 盡可能使用 HTTP作為封包 277 13.1.3 異常處理 279 13.2 聚合的 RESTful API 280 13.2.1 GET 280 13.2.2 PUT 291 13.2.3 PATCH 293 13.2.4 DELETE 295 13.2.5 POST 295 13.2.6 事件溯源 API 296 13.2.7 樹(shù)的查詢(xún)接口 297 13.3 服務(wù)的 RESTful API 297 13.4 身份與訪問(wèn)管理 299 13.4.1 獲取 OAuth 2.0 Bearer Token 299 13.4.2 在資源服務(wù)器上處理授權(quán) 301 13.5 生成 Client SDK 302 13.5.1 創(chuàng)建聚合實(shí)例 303 13.5.2 更新聚合實(shí)例 304 13.5.3 使用 Retrofit2 306 第14章 直達(dá) UI 308 14.1 兩條路線(xiàn)的斗爭(zhēng) 309 14.1.1 前端“知道”領(lǐng)域模型 309 14.1.2 前端“只知道”RESTful API 312 14.2 生成 Admin UI 312 14.2.1 使用 referenceFilter 313 14.2.2 展示派生的實(shí)體集合屬性 315 14.2.3 使用屬性層面的約束 316 14.2.4 使用 UI 層元數(shù)據(jù) 317 14.2.5 構(gòu)建更實(shí)時(shí)的應(yīng)用 318 【第四部分 建模漫談與 DDD 隨想】 第15章 找回敏捷的軟件設(shè)計(jì) 322 15.1 重構(gòu)不是萬(wàn)能靈藥 323 15.2 數(shù)據(jù)建模示例:訂單的裝運(yùn)與支付 324 15.2.1 訂單與訂單行項(xiàng) 325 15.2.2 訂單與訂單裝運(yùn)組 327 15.2.3 訂單與裝運(yùn)單 328 15.2.4 訂單的項(xiàng)目發(fā)貨 329 15.2.5 訂單的支付 330 15.3 中臺(tái)是一個(gè)輪回 332 15.4 實(shí)例化需求與行為驅(qū)動(dòng)測(cè)試 334 15.4.1 什么是實(shí)例化需求 334 15.4.2 BDD 工具 335 15.4.3 BDD 工具應(yīng)與 DDD 相得益彰 336 15.4.4 不要在驗(yàn)收測(cè)試中使用固件數(shù)據(jù) 336 15.4.5 制造“制造數(shù)據(jù)”的工具 337 15.5 要領(lǐng)域模型驅(qū)動(dòng),不要 UI 驅(qū)動(dòng) 345 15.6 不要用“我”的視角設(shè)計(jì)核心模型 346 15.6.1 讓 User 消失 347 15.6.2 認(rèn)識(shí)一下 Party 348 15.7 我們想要的敏捷設(shè)計(jì) 350 第16章 說(shuō)說(shuō) SaaS 351 16.1 何為 SaaS 351 16.2 多租戶(hù)技術(shù) 352 16.3 構(gòu)建成功的 SaaS 有何難 353 16.3.1 多租戶(hù)系統(tǒng)的構(gòu)建成本 353 16.3.2 難以滿(mǎn)足的定制化需求 353 16.3.3 負(fù)重前行的傳統(tǒng)軟件公司 355 16.4 SaaS 需要 DDD 355 第17章 更好的“錘子” 356 17.1 我們制作的一個(gè) DDDML GUI 工具 357 17.1.1 給領(lǐng)域建模提供起點(diǎn) 357 17.1.2 創(chuàng)建新的限界上下文 358 17.1.3 從 OFBiz 中“借鑒”數(shù)據(jù)模型 359 17.1.4 構(gòu)建項(xiàng)目并運(yùn)行應(yīng)用 361 17.1.5 使用 HTTP PUT 方法創(chuàng)建實(shí)體 362 17.1.6 給聚合增加方法 363 17.1.7 生成限界上下文的Demo Admin UI 368 17.1.8 讓不同層級(jí)的開(kāi)發(fā)人員各盡其能 369 17.2 以統(tǒng)一語(yǔ)言建模 370 附錄 DDDML 示例與縮寫(xiě)表 373
你還可能感興趣
我要評(píng)論
|