三 領域驅動設計-運用領域模型-綁定模型和實現

来源:https://www.cnblogs.com/zhijiancanxue/archive/2020/03/19/12523812.html
-Advertisement-
Play Games

[toc] 領域驅動設計 運用領域模型 綁定模型和實現 聰明的項目組成員花費了幾個月的時間進行仔細的研究並且開發出了詳盡的領域模型(類圖)。然而對類圖研究不能讓我深入地瞭解該應用程式的代碼和設計,這讓我備感困擾。當開發人員開始實現應用程式時,他們很快就發現,儘管分析人員說得頭頭是道,他們依然無法將這 ...


目錄

領域驅動設計-運用領域模型-綁定模型和實現

聰明的項目組成員花費了幾個月的時間進行仔細的研究並且開發出了詳盡的領域模型(類圖)。然而對類圖研究不能讓我深入地瞭解該應用程式的代碼和設計,這讓我備感困擾。當開發人員開始實現應用程式時,他們很快就發現,儘管分析人員說得頭頭是道,他們依然無法將這種錯綜複雜的關係轉換成可存儲、可檢索的且具有事務完整性的單元。

由於模型是“正確的”,這是經過技術分析人員和業務專家大量協作才得到的結果,因此開發人員得出這樣的結論:無法把基於概念的對象作為設計的基礎。於是他們開始進行專門針對程式開發的設計。他們的設計確實用了一些原有模型中類和屬性的名稱進行數據存儲,但這種設計並不是建立在任何已有模型的基礎上的。

這個項目雖然建立了領域模型,但是如果模型不能直接幫助開發可運行的軟體,那麼這種紙上談兵的模型又有什麼意義呢?

領域驅動設計要求模型不僅能夠指導早期的分析工作,還應該成為設計的基礎。這種設計方法對於代碼的編寫有著重要的意義。不太明顯的一點就是:領域驅動設計要求一種不同的建模方法

個人理解:建了模型可以更快瞭解所需知識,可又不能轉化成程式代碼實現,到底要怎樣?我也搞不懂了,反正覺得好複雜

MODEL-DRIVEN DESIGN

嚴格按照基礎模型來編寫代碼,能夠使代碼更好地表達設計含義,並且使模型與實際的系統相契合。

那些壓根兒就沒有領域模型的項目,僅僅通過編寫代碼來實現一個又一個的功能,它們無法利用前兩章所討論的知識消化和溝通所帶來的好處。如果涉及複雜的領域就會使項目舉步維艱。

另一方面,許多複雜項目確實在嘗試使用某種形式的領域模型,但是並沒有把代碼的編寫與模型緊密聯繫起來。這些項目所設計的模型,在項目初期還可能用來做一些探索工作,但是隨著項目的進展,這些模型與項目漸行漸遠,甚至還會起誤導作用。所有在模型上花費的精力都無法保證程式設計的正確性,因為模型和設計是不同的。

模型和程式設計之間的聯繫可能在很多情況下被破壞,但是二者的這種分離往往是有意而為之的。很多設計方法都提倡使用完全脫離於程式設計的分析模型,並且通常這二者是由不同的人員開發的。之所以稱其為分析模型,是因為它是對業務領域進行分析的結果,它在組織業務領域中的概念時,完全不去考慮自己在軟體系統中將會起到的作用。分析模型僅僅是理解工具,人們認為把它與程式實現聯繫在一起無異於攪渾一池清水。隨後的程式設計與分析模型之間可能僅僅保持一種鬆散的對應關係。在創建分析模型時並沒有考慮程式設計的問題,因此分析模型很有可能無法滿足程式設計的需求。

這種分析中會有一些知識消化的過程,但是在編碼開始後,如果開發人員不得不重新對設計進行抽象,那麼大部分的領域知識就會被丟棄。如此一來,就不能保證在新的程式設計中還能保留或者重現分析人員所獲得的並且嵌入在模型中的領域知識。到了這一步,要維護程式設計和鬆散連接的模型之間的對應關係就很不合算了。

個人理解:業務畫的模型圖,在技術人員看來,需要進行翻譯成程式模型圖(流程圖),這樣,兩個模型之間肯定會有不同的部分,會有一些領域知識捨棄,那這兩個模型對應關係需要來維護,無疑增加了複雜度。

無論是什麼原因,軟體的設計如果缺乏概念,那麼軟體充其量不過是一種機械化的產品——只實現有用的功能卻無法解釋操作的原因。

如果整個程式設計或者其核心部分沒有與領域模型相對應,那麼這個模型就是沒有價值的,軟體的正確性也值得懷疑。同時,模型和設計功能之間過於複雜的對應關係也是難於理解的,在實際項目中,當設計改變時也無法維護這種關係。若分析與和設計之間產生嚴重分歧,那麼在分析和設計活動中所獲得的知識就無法彼此共用。

個人理解:上面的我也沒看懂,反正就是說業務涉及的模型和技術流程圖是有很大不同,原因是思考方式不同,這樣很難對應維護。

MODEL-DRIVEN DESIGN(模型驅動設計)不再將分析模型和程式設計分離開,而是尋求一種能夠滿足這兩方面需求的單一模型。不考慮純粹的技術問題,程式設計中的每個對象都反映了模型中所描述的相應概念。這就要求我們以更高的標準來選擇模型,因為它必須同時滿足兩種完全不同的目標。

有很多方法可以對領域進行抽象,也有很多種設計可以解決應用程式的問題。因此,綁定模型和程式設計是切實可行的。但是這種綁定不能夠因為技術考慮而削弱分析的功能,我們也不能接受那些只反映了領域概念卻捨棄了軟體設計原則的拙劣設計。模型和設計的綁定需要的是在分析和程式設計階段都能發揮良好作用的模型。如果模型對於程式的實現來說顯得不太實用時,我們必須重新設計它。而如果模型無法忠實地描述領域的關鍵概念,也必須重新設計它。這樣,建模和程式設計就結合為一個統一的迭代開發過程。

將領域模型和程式設計緊密聯繫在一起絕對是必要的,這也使得在眾多可選模型中選擇最適用的模型時,又多了一條選擇標準。它要求我們認真思考,並且通常會經過多次反覆修改和重新構建的過程,但是通過這樣的過程可以得到與設計關聯的模型。

要想創建出能夠抓住主要問題並且幫助程式設計的單一模型並沒有說的那麼容易。我們不可能隨手抓個模型就把它轉化成可使用的設計。只有經過精心設計的模型才能促成切實可行的實現。

個人理解:建模好難,不管怎麼說,將業務和技術思維抽象成通用模型,本身就是學習成本,不是人人都能達到的。真的懷疑做模型的時間是不是還不如直接開發來的乾脆,少搞這些虛頭巴腦的東西。老外對模型是真愛!

建模範式和工具支持

為了使MODEL-DRIVEN DESIGN發揮作用,一定要在可控範圍內嚴格保證模型與設計之間的一致性。要實現這種嚴格的一致性,必須要運用由軟體工具支持的建模範式,它可以在程式中直接創建模型中的對應概念。

面向對象編程之所以功能強大,是因為它基於建模範式,並且為模型構造提供了實現方式。從程式員的角度來看,對象真實存在於記憶體中,它們與其他對象相互聯繫,它們被組織成類,並且通過消息傳遞來完成相應的行為。許多開發人員只是得益於對象的技術能力——用其組織程式代碼,只有用代碼表達模型概念時,對象設計的真正突破之處才彰顯出來。Java和許多其他工具都允許創建直接反映概念對象模型的對象和關係。

沒看懂,直接忽略。設計不是一蹴而就的。我們需要反覆研究領域知識,不斷重構模型,才能將領域中重要的概念提煉成簡單而清晰的模型。

為什麼模型對用戶至關重要

從理論上講,也許你可以向用戶展示任何一種系統視圖,而不管底層如何實現。但實際上,系統上下層結構的不匹配輕則導致誤解,重則產生bug。

如果程式設計基於一個能夠反映出用戶和領域專家所關心的基本問題的模型,那麼與其他設計方式相比,這種設計可以將其主旨更明確地展示給用戶。讓用戶瞭解模型,將使他們有更多機會挖掘軟體的潛能,也能使軟體的行為合乎情理、前後一致。

個人理解:這裡說了很多理論,其實就是一點,如果模型做的不好,直接導致做出來的東西會複雜難用,用戶難以接受。

HANDS-ON MODELER

人們總是把軟體開發比喻成製造業。這個比喻的一個推論是:經驗豐富的工程師做設計工作,而技能水平較低的勞動力負責組裝產品。這種做法使許多項目陷入困境,原因很簡單——軟體開發就是設計。雖然開發團隊中的每個成員都有自己的職責,但是將分析、建模、設計和編程工作過度分離會對MODEL-DRIVEN DESIGN產生不良影響。我曾經在一個項目中負責協調不同的應用程式開發團隊,幫助開發可以驅動程式設計的領域模型。但是管理層認為建模人員就應該只負責建模工作,編寫代碼就是在浪費這種技能,於是他們不准我編寫代碼或者與程式員討論細節問題。

個人理解:現在軟體工程就是分了很多流程:調研-需求評審-概要設計-詳細設計-系統開發-測試-上線-維護,難道每個人負責自己的模塊不好嗎?很多對日外包就是拿日本人設計好的偽代碼和流程圖,直接用程式翻譯出來。難道自己的理解有問題了?

開始項目進展的還算順利。我和領域專家以及各團隊的開發負責人共同工作,消化領域知識並提煉出了一個不錯的核心模型。但是該模型卻從來沒有派上用場,原因有兩個。

其一,模型的一些意圖在其傳遞過程中丟失了。模型的整體效果受細節的影響很大這些細節問題並不是總能在UML圖或者一般討論中遇到的。如果我能擼起袖子,直接與開發人員共同工作,提供一些參考代碼和近距離的技術支持,那麼他們也許能夠理解模型中的抽象概念並據此進行開發。

第二個原因是模型與程式實現及技術互相影響,而我無法直接獲得這種反饋。例如,程式實現過程中發現模型的某部分在我們的技術平臺上的工作效率極低,但是經過幾個月的時間,我才一點一點獲得了關於這個問題的全部信息。其實只需較少的改動就能解決這個問題,但是幾個月過去了,改不改已經不重要了。因為開發人員已經自行編寫出了可以運行的軟體——完全脫離了模型的設計,在那些還在使用模型的地方,也僅僅是把它當作純粹的數據結構。開發人員不分好壞地把模型全盤否定,但是他們又有什麼辦法呢?他們再也不願意冒險任由呆在象牙塔里的架構師擺佈了。

與其他項目一樣,這個項目的初始環境傾向於不讓建模人員參與太多的程式實現。對於該項目所使用的大部分技術,我都有著大量的實踐經驗。在做建模工作之前,我甚至曾經在同類項目中領導過一個小的開發團隊,所以我對項目開發過程和編程環境非常熟悉。但是如果不讓建模人員參與程式實現,我就是有這些經歷也無法有效地工作。

如果編寫代碼的人員認為自己沒必要對模型負責,或者不知道如何讓模型為應用程式服務,那麼這個模型就和程式沒有任何關聯。如果開發人員沒有意識到改變代碼就意味著改變模型,那麼他們對程式的重構不但不會增強模型的作用,反而還會削弱它的效果。同樣,如果建模人員不參與到程式實現的過程中,那麼對程式實現的約束就沒有切身的感受,即使有,也會很快忘記。MODEL-DRIVEN DESIGN的兩個基本要素(即模型要支持有效的實現並抽象出關鍵的領域知識)已經失去了一個,最終模型將變得不再實用。最後一點,如果分工阻斷了設計人員與開發人員之間的協作,使他們無法轉達實現MODEL-DRIVEN DESIGN的種種細節,那麼經驗豐富的設計人員則不能將自己的知識和技術傳遞給開發人員。

HANDS-ON MODELER(親身實踐的建模者)並不意味著團隊成員不能有自己的專業角色。包括極限編程在內的每一種敏捷過程都會給團隊成員分配角色,其他非正式的專業角色也會自然而然地產生。但是如果把MODEL-DRIVEN DESIGN中密切相關的建模和實現這兩個過程分離開,則會產生問題。

整體設計的有效性有幾個非常敏感的影響因素——那就是細粒度的設計和實現決策的質量和一致性。在MODEL-DRIVEN DESIGN中,代碼是模型的表達,改變某段代碼就改變了相應的模型。程式員就是建模人員,無論他們是否喜歡。所以在開始項目時,應該讓程式員完成出色的建模工作。

任何參與建模的技術人員,不管在項目中的主要職責是什麼,都必須花時間瞭解代碼。任何負責修改代碼的人員則必須學會用代碼來表達模型。每一個開發人員都必須不同程度地參與模型討論並且與領域專家保持聯繫。參與不同工作的人都必須有意識地通過UBIQUITOUS LANGUAGE與接觸代碼的人及時交換關於模型的想法。

將建模和編程過程完全分離是行不通的,然而大型項目依然需要技術負責人來協調高層次的設計和建模,並幫助做出最困難或最關鍵的決策。

個人理解:每個人都要會一點建模,就算是開發人員,也要參與其中,就算是業務人員,也要稍微懂些代碼。每個人要有自己的專業能力,同時也要全面發展,瞭解整個流程的工作內容。一句話:可以不做,但是不能不會。突然有一個需要程式員去做需求或者詳細設計,也要能扛下來這個任務。目的不是讓一個人做多個任務,擔任軟體開發流程中的多個職責,而是懂得一些後大家溝通建模沒有障礙,會相互理解。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • JavaScript進階之高階函數篇 簡介:歡迎大家來到woo爺說前端;今天給你們帶來的是JavaScript進階的知識,接下來的系列都是圍繞著JavaScript進階進行闡述;首先我們第一篇講的是高階函數。 高階函數定義:高階函數是指操作函數的函數;一般情況在項目開發過程中都會分兩種情況 函數可以 ...
  • JavaScript 中函數原型是實現繼承的基礎。prototype、construct、原型鏈以及基於原型鏈的繼承是面向對象的重要內容 ...
  • 故事背景: 沙雕在公司一個開放API團隊工作,平時的工作內容主要是做一些對外API項目開發,負責跟第三方系統對接。雖然工作也幾年了,但是一直都是按照上級做好的設計文檔和分配的任務去做,很少自己去做設計和思考。有一天團隊老大跑路了,部門老闆想提拔他做團隊老大的工作,但需要負責一個新項目架構設計工作來試 ...
  • 策略模式(Strategy):它定義了演算法家族,分別封裝起來,讓它們之間可以互相替換,此模式讓演算法的變化不會影響到使用演算法的客戶。 ——《大話設計模式》 策略模式主要用來解決當有多種相似演算法的時,使用if...else產生的難以維護的問題。它主要由三部分組成:Strategy介面、具體的Strate ...
  • 圖解Java設計模式之橋接模式 手機操作問題 傳統方案解決手機操作問題 傳統方案解決手機操作問題分析 橋接模式(Bridge)-基本介紹 橋接模式解決手機操作問題 橋接模式在JDBC中的源碼解析 橋接模式的註意事項和細節 橋接模式其它應用場景 手機操作問題 現在對不同手機類型的不同品牌實現操作編程( ...
  • [toc] 領域驅動設計 領域對象的生命周期 每個對象都有生命周期,如圖6 1所示。對象自創建後,可能會經歷各種不同的狀態,直至最終消亡——要麼存檔,要麼刪除。當然,很多對象是簡單的臨時對象,僅通過調用構造函數來創建,用來做一些計算,而後由垃圾收集器回收。這類對象沒必要搞得那麼複雜。但有些對象具有更 ...
  • [toc] 軟體中所表示的模型 表示模型的3種模型元素模式:ENTITY、VALUE OBJECT和SERVICE。從錶面上看,定義那些用來捕獲領域概念的對象很容易,但要想反映其含義卻很困難。這要求我們明確區分各種模型元素的含義,並與一系列設計實踐結合起來,從而開發出特定類型的對象。 個人理解:就是 ...
  • [toc] 模型驅動設計的構造塊 分離領域 在軟體中,雖然專門用於解決領域問題的那部分通常只占整個軟體系統的很小一部分,但其卻出乎意料的重要。我們需要著眼於模型中的元素並且將它們視為一個系統。絕不能像在夜空中辨認星座一樣,被迫從一大堆混雜的對象中將領域對象挑選出來。我們需要將領域對象與系統中的其他功 ...
一周排行
    -Advertisement-
    Play Games
  • Dapr Outbox 是1.12中的功能。 本文只介紹Dapr Outbox 執行流程,Dapr Outbox基本用法請閱讀官方文檔 。本文中appID=order-processor,topic=orders 本文前提知識:熟悉Dapr狀態管理、Dapr發佈訂閱和Outbox 模式。 Outbo ...
  • 引言 在前幾章我們深度講解了單元測試和集成測試的基礎知識,這一章我們來講解一下代碼覆蓋率,代碼覆蓋率是單元測試運行的度量值,覆蓋率通常以百分比表示,用於衡量代碼被測試覆蓋的程度,幫助開發人員評估測試用例的質量和代碼的健壯性。常見的覆蓋率包括語句覆蓋率(Line Coverage)、分支覆蓋率(Bra ...
  • 前言 本文介紹瞭如何使用S7.NET庫實現對西門子PLC DB塊數據的讀寫,記錄了使用電腦模擬,模擬PLC,自至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1.Windows環境下鏈路層網路訪問的行業標準工具(WinPcap_4_1_3.exe)下載鏈接:http ...
  • 從依賴倒置原則(Dependency Inversion Principle, DIP)到控制反轉(Inversion of Control, IoC)再到依賴註入(Dependency Injection, DI)的演進過程,我們可以理解為一種逐步抽象和解耦的設計思想。這種思想在C#等面向對象的編 ...
  • 關於Python中的私有屬性和私有方法 Python對於類的成員沒有嚴格的訪問控制限制,這與其他面相對對象語言有區別。關於私有屬性和私有方法,有如下要點: 1、通常我們約定,兩個下劃線開頭的屬性是私有的(private)。其他為公共的(public); 2、類內部可以訪問私有屬性(方法); 3、類外 ...
  • C++ 訪問說明符 訪問說明符是 C++ 中控制類成員(屬性和方法)可訪問性的關鍵字。它們用於封裝類數據並保護其免受意外修改或濫用。 三種訪問說明符: public:允許從類外部的任何地方訪問成員。 private:僅允許在類內部訪問成員。 protected:允許在類內部及其派生類中訪問成員。 示 ...
  • 寫這個隨筆說一下C++的static_cast和dynamic_cast用在子類與父類的指針轉換時的一些事宜。首先,【static_cast,dynamic_cast】【父類指針,子類指針】,兩兩一組,共有4種組合:用 static_cast 父類轉子類、用 static_cast 子類轉父類、使用 ...
  • /******************************************************************************************************** * * * 設計雙向鏈表的介面 * * * * Copyright (c) 2023-2 ...
  • 相信接觸過spring做開發的小伙伴們一定使用過@ComponentScan註解 @ComponentScan("com.wangm.lifecycle") public class AppConfig { } @ComponentScan指定basePackage,將包下的類按照一定規則註冊成Be ...
  • 操作系統 :CentOS 7.6_x64 opensips版本: 2.4.9 python版本:2.7.5 python作為腳本語言,使用起來很方便,查了下opensips的文檔,支持使用python腳本寫邏輯代碼。今天整理下CentOS7環境下opensips2.4.9的python模塊筆記及使用 ...