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

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

[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與接觸代碼的人及時交換關於模型的想法。

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

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


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

更多相關文章
  • 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] 模型驅動設計的構造塊 分離領域 在軟體中,雖然專門用於解決領域問題的那部分通常只占整個軟體系統的很小一部分,但其卻出乎意料的重要。我們需要著眼於模型中的元素並且將它們視為一個系統。絕不能像在夜空中辨認星座一樣,被迫從一大堆混雜的對象中將領域對象挑選出來。我們需要將領域對象與系統中的其他功 ...
一周排行
  • 上一篇文章(https://www.cnblogs.com/meowv/p/12943699.html)完成了項目的全局異常處理和日誌記錄。 在日誌記錄中使用的靜態方法有人指出寫法不是很優雅,遂優化一下上一篇中日誌記錄的方法,具體操作如下: 在.ToolKits層中新建擴展方法Log4NetExte ...
  • 先安裝幾個包 獲取地址如下https://www.nuget.org/packages/QRCoder/https://www.nuget.org/packages/SixLabors.Fonts/https://www.nuget.org/packages/SixLabors.ImageSharp ...
  • 0. 前言 前一篇我們詳細的介紹了SqlSugar的增刪改查,那些已經滿足我們在日常工程開發中的使用了。但是還有一點點在開發中並不常用,但是卻非常有用的方法。接下來讓我們一起來看看還有哪些有意思的內容。 1. 不同尋常的查詢 之前介紹了針對單個表的查詢,同樣也是相對簡單的查詢模式。雖然開發完全夠用, ...
  • 最新.net core 圖片合併生成二維碼合成圖片 圖片添加文字 先安裝幾個包 獲取地址如下 https://www.nuget.org/packages/QRCoder/ https://www.nuget.org/packages/SixLabors.Fonts/ https://www.nug ...
  • 前言 之前我寫過一篇關於 Blazor WebAssembly 的文章瀏覽器中的 .Net Core —— Blazor WebAssembly 初體驗,如今已經更新到 RC-1,與預覽版有著較大的差異,為此補充這篇文章。 正文 與預覽版的主要差異 1、這次的候選版修改了大部分包名和命名空間,因此無 ...
  • 藍牙設置相關界面,以下是通過C#方式打開的幾個方式,記錄一下 藍牙設置界面 1.控制面板命令bthprops.cpl 可以用控制面板 control+bthprops.cpl,也可以直接bthprops.cpl。更多的命令見:所有運行命令指令大全、CMD & CPL:快捷系統命令和控制面板命令 bt ...
  • 一:背景 1. 講故事 去年阿裡聚石塔上的所有isv簡訊通道全部對接阿裡通信,我們就做了對接改造,使用阿裡提供的.net sdk。 網址:https://help.aliyun.com/document_detail/114480.html 同事當時使用的是ons-.net v1.1.3版本,程式上 ...
  • 一.相關介紹 Dockerfile:關於Dockerfile的使用說明,我在文章《讓.NetCore程式跑在任何有docker的地方》中有說到,這裡不在贅述,需要的可以先看下,本文主要介紹Jenkinsfile結合dockerfile配合使用,自動構建.NetCore應用程式。 Jenkinsfil ...
  • 當用戶嚮應用程式發出請求時,伺服器將解析該請求,生成響應,然後將結果發送給客戶端。用戶可能會在伺服器處理請求的時候中止請求。就比如說用戶跳轉到另一個頁面中獲取說關閉頁面。在這種情況下,我們希望停止所有正在進行的工作,以浪費不必要的資源。例如我們可能要取消SQL請求、http調用請求、CPU密集型操作 ...
  • 在.NET中,我們可以通過Task.WhenAll用來等待多個任務。任務完成之後,我們可以使用await等待他們來獲取結果。 Task<int> task1 = Task.Run(() => 1); Task<string> task2 = Task.Run(() => "hello"); awai ...