<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      DDD落地實踐-架構師眼中的餐廳 | 京東云技術團隊

      在去年、我整理了一篇名為《如何做架構設計?》的文章,主要探討了架構設計的目標和過程,然而、那是一篇概括性的文章,用于啟發思路,并不是具體的實踐指南,因此、我一直期望給出具體參考案例。

      我幾乎忘了這件事,如今回顧、我發現并沒有合適的案例可供參考,現有的案例要么不完整、要么是與業務耦合的特定場景,要么無法支撐研發落地。所以我決定從實際生活中出發,虛擬一個案例場景,以便能夠系統性的闡述這個問題。

       

      正文開始


       

      本案例側重于DDD的實踐,從實際業務場景推導軟件架構,將業務元素映射為系統元素,以完美的方法構建完美的系統,讓系統本身成為最好的業務文檔。在本案例中,我們選擇餐廳作為業務場景,但不在意餐廳實現細節,而是側重于落地實踐和經驗總結。希望讀者能夠從中吸取精華,去其糟粕,全文較長、耐心讀完、必有收獲。


       

      1、領域設計

      在分析業務的時候,不需要考慮技術問題,我們以純業務的視角分析業務問題、以免受到技術慣性思維的干擾,避免將業務問題和技術問題混為一談。

      領域設計的核心是業務驅動的分而治之,旨在縮小軟件系統與真實業務的差異,從而減少差異帶來的問題

      當業務與系統之間存在差異時,我們無法將業務邏輯和程序邏輯對應起來,從而分不清區域,也分不清職責,因此會覺得混亂。就像你平時不會將枕頭和被子放在廚房或衛生間一樣,你的床上不會放著大米白面,否則你想睡覺是一件很復雜的事情,軟件系統也是如此。

      所以,首先要把業務分析清楚,然后設計與業務模型對應的軟件模型這就是DDD的核心思想。

      1.1 宏觀流程

      假如我要設計一個餐廳,由于分而治之的需要,我會首先從宏觀流程去分析可以幫我們迅速找到重要的區域。

       


       

      因此會得到幾個明確的行為區域,我將餐廳劃分為“菜品域”,“訂單域”,“廚房域”,“用餐域”,這是宏觀級別的領域劃分,后續應該針對每個區域單獨分析。

      產出物是:宏觀流程和參與角色

       

      1.2 統一語言

      語言貫穿于整個開發過程,從需求分析到設計、從設計到編碼,因此好的語言非常重要,好的語言體現了清晰的業務概念

      在這個階段,我們需要通過梳理,找到業務中都有哪些實體與行為,對其做一些歸納。我們的核心問題是“誰”通過什么“行為”影響了“誰”其中的三個要素分別是“角色”、“行為”、“實體”,因此我的建議是找到 “角色”、“行為”、“實體”,并對他們歸類我常常關注角色以及具體身份、行為以及包含的重要步驟、實體以及具體實例。

      角色是施事主語、是名詞,是主動發起行為的一類實體。

      行為是動詞、是做了什么事情,是行為本身。

      實體是名詞,是除“角色”之外的其他實體。

      推薦使用腦圖畫出來,我認為歸納后的腦圖有助于我們識別根本要素,有利于抽象。

      產出物是:名詞、概念定義、相關腦圖。

       


       

       

      1.3 用例分析

      在這一步、我們使用相對宏觀的分析,不需要進入用例的細節分析,主要的目的是掌握角色與行為之間的關系,理清誰在做什么,角色的職責目的是什么,用于指導領域劃分以及領域服務設計。

      產出物:用例圖

      以做菜為例,如圖

       


       

       

      1.4 領域劃分

      我們在分析宏觀流程時,劃分了幾個行為區域,但那是業務級別的。在那基礎之上,我們需要拉進某個區域的視角,再結合之前的用例分析,按照“功能相關性”、“角色相關性”進一步劃分領域我們不僅要知道誰做了什么,還需要知道誰“在哪”做了什么

      功能相關性任何問題空間都是圍繞一件事情展開的,軟件是由功能組成的,所以“功能相關性”是劃分領域的黃金標準,通過劃分領域、從而梳理用例與領域之間的關系例如與做菜相關的用例都應該歸屬于廚房,所以我們確認了廚房域,確認了廚房域包含的用例,這是很自然的事。

      角色相關性:其次是角色,常用于劃分子域某個區域涉及多個角色參與,可以按照角色的分工,拆分為多個子域,從而滿足不同角色的個性化需要。例如廚房的采購人員負責買菜、刀工負責切菜、大廚負責烹飪。我們就會考慮將廚房劃分為“采購子域”、“加工子域”、“烹飪子域”。

      通常來說,子域不具備獨立的問題空間,不會作為獨立的領域存在。

      產出物:領域、子域、領域與用例的關系

      以廚房域為例,如圖

       


       

       

      在復雜業務時,可以使用事件風暴方法輔助分析,并輸出上述產出物。

       

      1.5 領域服務

      什么是領域服務?一個領域可以有幾個領域服務? 我們如何劃分領域服務?標準是什么?

      我認為一個領域不只有一個領域服務,我們不應該按照實體劃分,也不應該按照聚合劃分,也不該按照功能相關性劃分。

      領域服務用于實現用例功能,我認為應該使用角色劃分領域服務。在用例圖中,不同的角色發起不一樣的用例,不同的領域服務提供不一樣的用例,只有這樣、才能將用例圖映射到領域服務中,也才能真正體現業務含義。領域服務是面向角色的,在一個領域中、每個角色對應一個領域服務。另外、同一個用例的邏輯差異是與角色的身份有關的,角色的身份對應了服務的泛化,角色的用例對應了服務的方法對于此觀點、我們在后續功能設計的部分也有體現。

      例如:廚房域(廚師服務、刀工服務、采購員服務),菜品域(客戶服務、管理者服務)。

      產出物:領域服務類圖

       


       

       

      1.6 領域建模

      我們思考一下,到底什么才是領域驅動設計? 我經常看見“廚房域”被稱為“菜域”,“廚師”的“做菜”功能被稱為“菜服務”的“做菜”功能,也經常看見“菜品域”有個“菜品服務”,“菜品服務”提供了“增、刪、改、查”的功能。我們往往以最核心的實體為中心,誤以為業務就是在操作數據,丟掉了業務本質含義,逐漸也就走歪了。

      不要學傳統的數據模型驅動設計,實體模型驅動設計與前者的本質是一樣的,是換湯不換藥的,換個充血模式也改變不了本質問題。我們必須把精力放在業務本身,防止領域驅動設計變成領域模型驅動設計我們不應該優先思考領域模型,不應該以領域模型命名一切,不應該讓領域模型決定業務的實現方式。廚房不只有菜,也有服務員和廚師,我們使用合適的語言對應合適的元素,以確保軟件元素是真實業務的映射例如“廚師在廚房做菜”,這句話中的所有元素都要在系統中得以保留,丟了一個也不行,更何況只剩下菜了。

      回到正題、我們在這一步的重點是分析實體與領域之間關系(領域聚合),實體與實體的關系(OO聚合)其中OO關系影響了功能的擴展性,需要我們特別關注。我推薦做法是將領域的功能放在一起分析,找到他們的共同性,充分考慮變化,使用兼容性更好的模型解決問題。

       

       

      組合、聚合

      聚合(aggregation):聚合關系是一種弱的關系,整體和部分可以相互獨立。

      組合(composition):組合關系是一種強的整體和部分的關系,整體和部分具有相同的生命周期。

      可以使用如下案例,既能表達領域聚合,又能表達OO聚合的關系。

       


       

      產出物:聚合、實體、值對象、實體的屬性

       

      1.7 領域上下游

      領域上下游關系,不是領域的依賴關系,依賴關系指的是能力的依賴,是共用了某些能力。領域上下游關系,也不是調用關系,調用關系是與用例相關的,不是用于描述領域處境的。

      領域上下游關系指的是影響力的關系上游影響下游,影響力分為“邏輯影響”和“數據影響”,一般說來我們更應該關注“數據影響”,所以領域上下游關系是一種數據流向的限制,是業務發生的順序限制用于規定該領域所使用的數據,是下游領域依賴上游領域“準備就緒”的體現。合理的上下游限制,有助于減少領域之間的不必要依賴和重復的計算。

      領域上下游是與場景相關的并不是一成不變的,不同場景的情況下,存在不同的上下游關系,各場景應該獨立說明。

      產出物:各場景的上下游說明

       

      例:在【菜品管理】場景下

       

       

      如果廚房的某些食材不足了,或者某個廚師休假了,就會影響到菜品的展示,從而影響到客戶的訂單。

       

      例:在【客戶消費】場景下

       

       

      客戶的訂單、影響廚房生產的菜,從而影響刀工的行為,也影響到了采購。

       

      請對比下面兩個圖,用于理解領域的上下游

       


       

      實際上,廚師不應該依賴采購人員的采購功能,也不依賴刀工的切菜功能,他只是依賴“初加工食材”而已,而“初加工食材”就是被處理好的數據,廚師在做飯時,“初加工食材”就已經被處理好了,上面的圖例只是為了說明一個關于領域上下游的問題,這是業務發生順序以及數據來源的問題。

      我們常常使用領域事件串聯業務流程,在使用領域事件時,不止要關注點對點的解耦,更應該使業務流程符合領域上下游限定,讓各個領域獨立運行,使用數據依賴替代功能依賴,減少業務變化帶來的影響。

       

      2、架構設計

      架構設計是為了解決軟件系統復雜度帶來的問題,找到系統中的元素并搞清楚他們之間關系

      架構的目標是用于管理復雜性、易變性和不確定性,以確保在長期的系統演化過程中,一部分架構的變化不會對其它部分產生不必要的負面影響。這樣做可以確保業務和研發效率的敏捷,讓應用的易變部分能夠頻繁地變化,對應用的其它部分的影響盡可能地小。

      架構設計三原則:合適原則、簡單原則、演化原則

      2.1 分層架構

      我們需要按照 接口層、領域層(領域用例層、領域模型層)依賴層、基礎層 構建架構模型

      接口層為外部提供服務的入口,是適配層的北向網關。不實現任何業務邏輯,也不處理事務,是跨領域的,是流程編排層,是門面服務。

      領域用例層:是領域服務層,是領域用例的實現層、隸屬于某個領域、是業務邏輯層,是事務層,業務邏輯應該在這層完整體現,不要分散到其他層級。

      領域模型層:是領域模型(實體、值對象、聚合)的所在位置,專注于領域模型自身的能力,不包含業務功能,可以處理事務,是原子化的能力,是領域對象的自我實現

      依賴層 是連接外部服務的出口,是適配層的南向網關。包括倉儲,端點、RPC等,主要作用是領域和外部解耦,是跨領域的。

      基礎層:與業務無關的,與領域無關的,通用的技術能力,技術組件等。

       

      2.2 架構映射

      架構的視角,從大到小依次是:系統->應用(微服務)->模塊(包)->子模塊 這樣的從大到小的層級。

      業務領域映射我們將劃分好的領域,按照對應的視角映射為對應的元素,領域模型映射到架構模型時,應該是視角對等的如果餐廳是系統、那么廚房就是應用,如果餐廳是應用、那么廚房就是模塊。也應該是層級匹配的,將用例的實現映射到用例層,將領域模型的實現映射到領域模型層。也應該是名稱一致的將領域名映射為應用名或包名,將實體名映射為實體類名,將角色名映射為領域服務類名,將角色身份名映射為服務類的子類名,將用例名映射為服務類的方法名。

      技術和抽象問題:有時候、業務領域分析不能體現那些共性的技術問題,所以需要適當結合技術視角,可能需要對領域模型微調。同時、我們需要找到共同需要的基礎能力,例如“水”、“電”、“煤氣”等等,將這些作為額外的考慮因素,要做到業務問題與技術問題解耦,不要將技術問題和業務邏輯揉成一團

      領域設計,類似餐廳設計師,他設計餐廳有幾個區域,區域的用途是什么。

      架構設計,類似建筑設計師,他設計如何走水電煤氣、如何施工等。

      產出物:分層架構圖

       

      以廚房為視角,其架構如下

       

       

      以餐廳為視角,其架構如下

       


       

      分層架構圖,體現邏輯上的層級分布,而不是代表組件的具體含義,組件是應用還是模塊、需要結合實際情況而定。

       

      2.3 必要的約束

      1、分層架構越往下層就越是穩定的下層是被上層依賴的,下層不可以反向依賴上層(擴展點除外)。因為分層架構的核心原則是將容易變化的邏輯上浮,將共性的、原子化的、通用的邏輯下沉,被依賴的下層應該是穩定的,這要求上層承接更多業務變化。下層離開上層應該是可以獨立存在的,例如在接口層定義的DTO不可以在下層被使用,但領域層定義的實體可以被上層使用。

      2、在使用充血模型時,應該符合面向對象編程原則不要隨意的將一些能力都充到領域實體模型中。以“菜”為例,重量和規格是“菜”的自身的屬性,激發味蕾是“菜”的能力,“菜”可以維護自身的持久化狀態。但是、請注意、“菜”不可以“炒菜”,因為“炒菜”的時候,“菜”還沒有出現呢,“菜”不是自己的上帝,“菜”需要被做出來,所以“菜”被做出來之前是沒有“菜”的,這是個時間上的概念,不要錯把“炒菜”的能力放在“菜”的身上。“炒菜”用到的“水+電+氣+食材+調料+廚具”不應該是“菜”的屬性范圍,這些元素都在“廚房”的范圍中,不要讓領域的模型包含不屬于自身的元素,領域的實體模型只是領域的一部分,只用于實現通用的模型能力

      3、接口層和依賴層是與領域無關的他們是與技術相關的層級,不屬于任何領域,這兩層不能包含業務邏輯。有時候我們可以把接口層拆為兩層(接口層、應用層),但是我不建議這樣做,我們沒有必要把很輕的一層再次拆分。我們也可以把依賴層拆分為兩個(領域模型依賴、其他依賴),我非常建議這樣做,因為領域模型依賴的資源不會被其他領域使用,拆開之后可以有效限制領域模型的依賴,以及保持領域模型層的獨立性。

      4、領域層是與環境無關的無論某個領域是應用還是模塊,都應該具備獨立的用例層和獨立的模型層,即使多個領域在同一個應用當中,也要按照他們是分別獨立去看待,無論某個領域是應用還是模塊,領域對外部的交互,不可以繞過依賴層和接口層。

      5、領域應該是最小完備的把一個領域拆分為子域、子子域..... 無限拆分,子域就不完整了。或者沒有按照功能相關性拆分,也可能破壞領域的完整性。不完整的子域是不可以獨立存在的,獨立存在的領域應該具備獨立的問題空間。當一個領域的內部子域不具備獨立性時,子域之間不必嚴格解耦,不需要通過依賴層訪問本領域的其他子域,他們之間可以直接調用

      6、領域用例層和領域模型層是兩個層級領域用例層指的就是領域服務層,他們倆是同一回事兒,都是用于實現領域內的用例的。不建議將領域服務與領域模型放在同一層這可能會導致邏輯的分散(一部分在領域服務層、一部分在領域模型層)。如果將業務邏輯寫在領域模型中,會導致業務邏輯進一步下沉,業務邏輯的不確定性太大,是不適合下沉的,是違反分層架構原則的。領域模型對應的是實體、領域服務對應的是用例分開就是更有效的限制措施

      7、領域用例層只能承接符合自身領域的用例我們劃分出領域的目的,就是為了區分每個領域的職責所在,因此他們必須嚴格按照職責辦事,我們在之前已明確了用例和領域之間的關系,需要嚴格遵守。 如果出現跨領域的編排,請在接口層串聯。如果依賴其他領域的功能,請把被依賴的功能邏輯放在其他領域中。

      8、領域模型層遵循最小依賴原則只可以依賴必要的資源,必要資源指的是領域模型實現自身能力需要的資源,不包括實現業務邏輯依賴的資源。例如領域模型需要依賴DB完成持久化,可以依賴數據訪問資源,但不應該依賴其他領域資源、不可以依賴RPC資源等。 最好的做法就是將領域模型依賴的資源單獨拿出來,并且與領域模型放在一起。

       

      2.4 微服務劃分

      服務劃分以領域劃分為參考,主要看我們要拆分到什么粒度,這 應該符合低耦合高內聚原則,不破壞領域實體的聚合關系

      產出物:微服務

       

      例如餐廳:是有必要拆分的,餐廳的“菜品域”,“訂單域”,“廚房域”有獨立的問題空間。

      例如廚房:是沒有必要拆分的,廚師與刀工的耦合非常高,他們都在做飯,分開之后是不完整的,分開就是沒有必要的。

       

      所以餐廳被拆分為:廚房、菜品、訂單,三個微服務。基于此、我們單獨拿出餐廳門面服務作為接口層應用,再單獨拿出餐廳基礎服務作為水電煤氣的應用。

      一般情況下,依賴層不會作為單獨的服務提供,會被以組件的形式嵌入到其他服務中。

       


       

       

      3、功能設計(用例實現)

      如果說領域設計是餐廳的設計師、架構設計是餐廳的建筑師、那么功能設計就是餐廳的廚師。

      任何設計都要落地到功能設計,如果廚師不守規則,偏偏要去洗手間洗菜,最后的結果依然是一團亂,最終會導致前面的所有設計泡湯。

      功能設計是實現 “面向擴展開放、面向修改關閉” 的途徑,

      功能設計是為研發提供的落地支撐。

       

      3.1 功能的概念

      功能迭代時,功能會發生一些變化,所以他的含義是可能變化的,所以我們需要再次審視功能的概念,及時加以調整。

      例如、我們實現了一個“做蛋炒飯”的功能,后來又實現了一個“做辣椒炒蛋”的功能,那么我們應該將功能升級為“炒菜”,甚至是“制作菜品”等。

      結合相關功能,系統性思考和抽象,明確功能的概念,是功能設計的前提。

      產出物:更新語言庫,更新腦圖

       

      3.2 用例的位置

      我們在領域分析章節,已明確了用例與角色的關系,用例與領域的關系

      然而一個新功能的加入,我們仍然要再次評估,以確保他處于正確的位置。

      產出物:更新用例圖

       

      3.3 事件風暴

      我們需要深入功能的細節,首推的方法是事件風暴,適用于解構復雜功能。

      事件風暴的作用并不限于功能分析,只是我覺得很適用于功能分析,事件風暴的一張圖包含很多內容,正好是功能設計所需要的。

      將功能拆分為多個子功能(步驟)。(在后續使用)

      確認參與該步驟的角色和領域。(在后續的3.6章節落地)

      確認步驟的串聯流程和領域事件。(在后續的3.6章節落地)

      確認參與該步驟的領域實體。(在后續的3.7章節落地)

      產出物:事件風暴模型

       

      3.4 用例分析

      我們暫且收回思路,首先要關注共性和差異問題,以實現功能復用或擴展。

      - 確認用例的泛化+差異點,實現功能的擴展。

      - 尋找共同包含的步驟,實現邏輯的復用。

      產出物:用例分析圖

       

      例:制作菜品(做大拌菜、做鐵鍋燉、做炒雞蛋、做蒸米飯、做炒米飯)

       


       

       

      3.5 用例實現類(領域服務類)結構圖

      首要關注點是領域服務類的結構問題,結構決定了擴展,我們需要先達到“面相修改關閉,面相擴展開放”的目的。

      類結構圖是用例分析圖的一種映射,類結構圖反向映射了角色的身份,進一步說明了領域服務應該按照角色劃分。

      產出物:用例層的類結構圖

       


       

       

      3.6 用例流程圖

      我們接回思路,更進一步,將事件風暴模型落實到代碼層面。

      我們將步驟分配到實現類中、步驟就是該類的一個方法進一步明確由哪個類和方法來實現該步驟,從而就規定了步驟所在的領域服務。再將步驟和領域事件串聯起來,規定了業務實現流程

      步驟就是子功能,在領域分析中已經體現了步驟所在的位置,使用功能相關性定位領域,使用角色相關性定位子域和服務,使用身份相關性定位服務實現類。

      推薦使用泳道圖表達上述內容。泳道的縱向組件是領域服務類,領域服務承接了所有子功能,流程圖也需要體現所有的步驟,是用例層的橫向交互。

      程序流程就是業務流程的映射,步驟的分布就是角色身份差異的映射

      產出物:用例流程圖

       

      以炒雞蛋為例,其用例流程圖如下

       


       

       

      3.7 活動圖(時序圖)

      進一步將事件風暴模型落實到代碼層面,我們使用時序圖,體現依賴和調用關系,規定了步驟與領域實體模型的關系,說明該步驟影響了誰。

      時序圖體現了領域服務內部的縱向交互,為了簡便、我們可以收起領域服務類(用例層)的泳道。

      產出物:時序圖、活動圖

       


       

       

      在本篇文章中,通過三大步驟闡述了映射辦法,讓軟件系統成為真實業務的說明書,軟件系統似乎在對我們說“誰做了什么事、影響了誰、是怎么做的、不同角色身份有什么差異......等等”。例如我們畫的圈成為了應用名或包名,圈中的領域模型圖成為了實體類+數據模型,圈中的用例圖成為了領域服務和方法,功能流程成為了程序調用鏈,每個步驟都成為了方法,領域服務類結構反向體現了角色身份,也體現了不同身份的差異...... 系統就是業務、業務就是系統、兩者可以自動化映射,這是完美的餐廳嗎?

      DDD的概念有很多,然而、概念如何應用呢?到底什么是DDD?是思想嗎?核心思想是什么?是方法論嗎?具體的方法是什么? 一些人認為DDD沒有用、一些人認為DDD難以落地,每個人都有自己的理解。在我看來、DDD是一套系統化的辦法,無法用幾句話說清楚,所以我需要借助這篇案例來表達,以此分享DDD的落地模式。

      好的、歡迎多多點贊并轉發給好友哦。

      作者:京東科技 董健

      來源:京東云開發者社區 轉載請注明來源

      posted @ 2024-01-03 09:35  京東云開發者  閱讀(5079)  評論(15)    收藏  舉報
      主站蜘蛛池模板: 午夜性刺激在线观看| 日韩在线视频线观看一区| 国产色无码专区在线观看| 亚洲午夜无码久久久久蜜臀av | 伊人激情av一区二区三区| 免费成人网一区二区天堂| gogogo高清免费观看| 日韩乱码人妻无码中文字幕视频 | 大尺度国产一区二区视频| 色成人精品免费视频| 国产精品99一区二区三区| 日韩乱码人妻无码中文字幕视频 | 亚洲一二三区精品美妇| √天堂资源网最新版在线| 97色成人综合网站| 日韩大片看一区二区三区| 999福利激情视频| 亚洲日韩一区二区| 成人一区二区人妻不卡视频| 亚洲精品美女一区二区| 久播影院无码中文字幕| 国产精品美女久久久久久麻豆| 欧美性大战久久久久久| 国产电影无码午夜在线播放| 国产精品无码av不卡| 四川省| 在线精品自拍亚洲第一区| 蜜桃无码一区二区三区| 亚洲精品亚洲人成在线| 国产色悠悠综合在线观看 | 99久久国产成人免费网站| 97色成人综合网站| 国产美女久久久亚洲综合| 人妻少妇久久久久久97人妻| 国产午夜福利一区二区三区 | 乱人伦中文字幕成人网站在线| 沈阳市| 久久久久久久久18禁秘| 台湾佬自拍偷区亚洲综合| 三上悠亚精品一区二区久久| 成人午夜福利一区二区四区|