領域模型驅動應用心得

2021-05-24 01:50:13 字數 4979 閱讀 2088

幾乎每種語言、開發框架和工具面世時,都號稱要把開發人員解放出來,讓他/她們更加關注於業 務邏輯的處理。但目前的工作狀況是,每當乙個新的「解放工具」出現,就會有眾多的技術狂熱者蜂擁而上,而忽略了他們最應該關注的業務邏輯部分。還好,從 2023年開始,「領域驅動設計」的聲音開始浮現,開始逐漸扭轉這種局面。

領域驅動設計詞解

儘管提出人eric evens 已給出了領域驅動設計的官方的解釋,但始終讓人感覺存在一些困惑。筆者將從乙個工程實踐者的角度來重新對這些詞做出簡要的解釋。

領域eric給出的解釋是:「使用者應用軟體的主題區域」。那麼我們應該如何理解這句話呢?例如,如果有人想把個人的社會關係寫程式展現出來,類似於「我是孫向暉,我是豆豆的父親,我是我父親的兒子。」有多少人會感覺到這段可能出自「好玩」的程式的價值?

但是,國家正在建立個人和企業的全國徵信系統,以建立信用檔案,規避「我給豆爺做汽車貸款擔保,豆爺給豆豆做房屋貸款擔保,豆豆給我做商業貸款擔保」這樣的風險,這樣以來,個人的社會關係就成為非常有價值的基礎資訊建設。

因此,軟體的主題區域應該是在浩瀚的知識和客戶要求(customer request)中被精心選擇和摘取出來的部分,用來解決實際的業務問題。但是經常被專案研發團隊混淆或者忽略的是:客戶需要不一定就是有效需求。

很多團隊將自己的工作重點放在了滿足客戶的變更需要上,結果客戶滿意度反而下降了。在這種情況下,這個團隊更應該審視一下自己的變更控制流程,目前團隊實現的是不是太多的客戶需要而非有效需求呢?

乙個軟體涵蓋的業務範圍會非常的廣,我們需要繼續根據二八原則來進行識別,以便找出其中的核心領域作為軟體開發的重點。

為了確定軟體的領域,我們通常可以問如下兩個問題:

1.軟體實現後的核心業務價值是什麼?

2.誰會為這個核心業務價值的實現來買單?

驅動「驅動」這個詞近些年來不絕於耳,耳熟能詳的如:用例驅動開發 (udd)、特性驅動開發(fdd)、測試驅動開發 (tdd),驅動的本質是什麼?

「驅動」就是試圖讓我們的思路更順暢,場景的切換更平滑。「領域驅動設計」就是希望在我們的設計中首先體現的是核心領域的選擇和實現。我們做出來的設計跟所選擇的領域之間更具有可追溯性、可度量性。

領域發生了變化,領域模型和設計就要發生相應的變化;設計變化了,一定能夠追溯到領域的變更。引發設計變化的因素很多,一定要是關鍵的領域部件所帶動的。

模型

雖然,我們可以從眾多的線索中抽取出比較核心的部分(也就是領域),但是領域還是太大,所以我們需要對領域的不同的側面進行描述,以期團隊成員可以很好的跟領域專家進行溝通,不至於在若干的岔路前迷失。

領域專家

為了獲得真正的領域,應該讓領域專家進入團隊。這個角色對於專案的成敗至關重要。請緊記,乙個專案團隊之所以能夠正確地從業務線索中篩選出核心領域,其前提是團隊中有乙個真正的「領域專家」。而現在我們通常見到的是讓一些技術人員去「編寫」需求。

那麼將上面的詞彙進行彙總,我們最後能夠得到的是什麼?

如果要做到「領域驅動設計」,那麼我們需要和真正的領域專家一起工作,從眾多的線索中,篩選出最能夠體現核心業務價值的領域,為它建立乙個可以設計和實現的領域模型,並在團隊中始終使用這個模型進行交流溝通。

常規專案的領域建模6步法

如果不考慮太多的因素,只是想在專案團隊中實踐「領域驅動設計」,那麼我們可以遵循乙個簡單的6步法。

1.提取概念。在這一步驟中,應該盡量多的進行領域走查,從文件資料或者交流過程中發現並標記出更多概念,儘管這些概念會有重複或者被混淆的可能,盡量先不要打斷自己的或者領域專家的思路。

2. 標註關係。概念的關係會有很多種,但最重要的就是兩種,關聯關係和泛化關係。因為兩個概念之間可能有若干種關聯關係,所以,應該在每乙個關係關係上標記關 聯方向、關聯名稱和多重性。注意,關聯應該盡量根據業務邏輯形成單方向的關聯,關聯關係的箭頭方向也不要跟資料模型中的外來鍵關係相混淆。儘管目前出於各種 原因,很多的語言很難實現出這種強語義的單向關係,但作為對業務的深入理解,將其簡化更容易消除我們思維中的領域複雜性。

我個人的實踐觀點是,不一定要選擇哪一種固定的分類方法,應該根據業務的實際情況,合理的選擇一種或者幾種分類作為自己的分類方法。

4.深究疑問。可能有人對為什麼要進行分類(第3步)心存疑惑。分類的最大的目的是為了形成高內聚低耦合,其次通過分類,還能夠讓我們將分類剩餘的或者類別中不和諧的部分查詢出來。對於任何疑問,都應該記錄下來,並且應該找領域專家進行討論,並澄清其中的概念。

在深究疑問的過程中,經過一定的領域知識的積累,可能會達到從量變到質變的突破。雖然突破很難出現,但只要它真的出現,就會給整個團隊帶來一種新的開發思路,領域的複雜度往往會隨著「突破」的出現而發生變化。

其實在現實生活中,我們眼見後第一感覺並不一定就是真實的領域邏輯,比方說,我們會在日常的交流中大量的使用規約(specification):「某文件 建立人的所有的直線上級都可以檢視該文件」這句話經過領域建模後,可能會形成以下的要記錄的規約:「某種文件型別,其建立者在『行政編制』中的所有的直線 上級都具有『檢視該文件』的許可權」;而「辦理資產入庫登記」會演變成「登記某種資產型別的一批號段的批量入庫」。

5. 對映到資料模型並實現。作為企業級應用,大部分的領域模型是要被儲存下來的,包括那些隱式的概念。隱式的概念的處理有兩種方式,一種是直接運算後記錄運算 結果;一種是記錄下規約,在執行時解釋。前一種方式的執行速度會很快,但是規約適用的範圍發生變更時調整起來比較麻煩,後者執行時運算速度慢,但是應對變 化能力更強些。因此,可以將這兩種方式結合,同時記錄規約和規約運算的結果。

我們現在在專案團隊中的做法是,是將核心領域中的業務需求細化成可度量的使用者故事,採用「測試驅動開發」的方式整理測試用例和測試夾具(fixture)。 這種方法的好處是整個的需求把握是從領域模型出發的,不會將需求的覆蓋和設計的推導寄託在持「技術思考」的開發人員身上。通過實現帶有檢查點的使用者故事, 提煉出來的介面往往是最實用的,會對「預先設計」產生的工件產生改天換地的效果。

6.就如同「降龍第十八掌就是要將前面的十七掌連起來再打一遍」一樣,是乙個迭代的過程,需要根據變更的情況對領域模型進行重組和調整,為了方便的進行重構的同時保證質量,應該在專案團隊中實施自動化的專案構建,並確保持續整合。

在大規模專案應用

我們前面說的所謂的「常規專案」是指從頭開始開發乙個新的專案,基本上是遵循的從上到下的專案研發模式。但是,經過若干年的資訊化,每個企業都已經或多或少的擁有了自己的資訊系統了,推翻了重新開發是行不通的。

我個人認為,領域驅動設計之所以會如此獲得很多人的青睞,跟它最初將自己的應用場景放到了企業架構層面不無道理。

企業中的組織機構中有多種組織編制關係,每種組織關係中會有不同的匯報和隸屬關係。有的組織機構同時具備水平管理或者垂直管理,如此,這樣的組織架構所執行的業務的含義也會有很大的不同。

企業架構中的應用架構檢視,告訴你有多少遺留的系統,每個系統著力於去解決在企業管理中的某個層面中的業務問題。

企業架構中的開發架構檢視,告訴你有多少個開發團隊和維護團隊在現有的或者將來的系統上工作著,那麼這些團隊之間都是什麼樣的關係呢?他們應該如何協助才是合理的?

在大規模專案中,為了要保證資訊化建設的延續性,保護已有的投資,就要在系統建設開始之前,進行大規模的領域走查,在分類時要確定更大規模的資訊架構用於跟企業架構對應。常用的方法有:

1.精煉:乙個專案足夠大時,不是所有的子系統都具有一致的優先順序,我們應該對核心業務和支撐類業務進行區分,對核心領域和通用的子領域進行區分,對要優化或者要刪除的領域部分進行區分。

2.職責分層: 因為組織機構是分層的,所有業務元件和領域模型也是分層。不同的層級關注的點不同,這點需要尤其注意。

3.上下文對映:當擁有不同的研發團隊、遺留系統時,就會自然的形成若干的限界上下文,有的領域概念在不同的上下文中含義不同,例如:乙個客戶,在同乙個系統 的呼叫中心上下文中是訪銷客戶,在crm上下文中是零售終端,在物流上下文中是配送客戶,在專賣上下文中是被監管的客戶。要在乙個模型中維護所有的資訊是 不太現實的,應該在各個上下文中建立起概念間的對映關係。

4.強化(highlighted):如果這個系統足夠大,大到讓所有的人一看那些細節就暈,那麼就應該在其系統遠景的基礎上,整理出一幅能夠輕鬆讓團隊每乙個成員都能達成共識的強化領域模型。在超大規模專案中使用這樣的模型,會讓團隊的領域整體把握能力大大增強。

真實案例應用

我想最後還是可以哪齣我們最近的乙個「全面預算管理」系統的例子來跟大家分享。這個系統是乙個非常大規模的系統。要在集團公司和旗下的若干個子公司中部署實 施,每個子公司要在集團統一的預算體系下有自己的特色(這是中國的企業最希望強調的一點),預算的過程要從上而下然後從下而上的反覆過若干次,並且各責任 中心的預算的版本要有保留。

最後,根據預算的實際執行結果要跟預算額進行比對分析,以便為考核以及下乙個預算週期的預算打好基礎。無論是預算體系的設計還是預算的編制或者變更,都涉及了諸多的業務部門參與,另外研發團隊分成若干個部分,還有要和若干的遺留的業務系統以及財務系統、考核系統對接。

在接收這樣的大專案時,我們的第一步是要做企業架構的採集和評估,了解集團企業的戰略目標,明確系統建設的長期目標和短期任務。比如:如果企業「全面預算」 的長期建設目標是提高企業的「預算精準程度」,那麼它希望通過幾年的建設達到該目標;那麼企業「全面預算」在年內的短期目標是實現預算編製和修訂工作的電 子化嗎?

針對確定下來目標,進行領域走查,確定熱點的業務元件。我們會根據其組織架構將業務元件和領域模型進行職責分層:

1.決策層 全面預算體系的設計。

2.執行層 全面預算工作的編制和修訂。

3.控制層 全面預算編製的評審和執行結果評估。

如果第一年的建設目的是實現編制和修訂工作的電子化,那麼決策層的工作一定要做,但不應該將它作為一期軟體實現的重點。我們可以採用批量匯入的方式來建立企業的全面預算體系。

為了更大程度的保護既有投資,我們需要考慮「全面預算管理」系統和其他系統之間的業務流和資訊流向:哪些資訊流是要求同步的,哪些可以是非同步的。為了保證各研發團隊不發生整合大**,各限界上下文之間的整合部分要提前考慮,並建立定期的溝通交流機制。

領域驅動設計不光給我們帶來了理解企業資訊化本質的最實用的思考方式,還給我們帶了切實可行的實現模型。在ibm soa的解決方案中,「領域驅動設計」被其推薦為提煉和實現soa服務的參考方法。我們在眾多的大規模專案中成功的應用了這一敏捷方法學,願與更多的朋友 一道在專案中積累自己的使用心得。

floyd應用心得

1.巧用floyed思路確定樹中節點的關係 題目描述 今天的問題是求子樹大小。輸入一棵樹 樹的度最大為10 求每棵子樹大小,請輸出以每棵子樹的節點總數。輸入檔案 tree.in 第一行 n 結點個數,n 100 m 邊數 以下m行 每行兩個結點x和y,表示y是x的孩子。輸出檔案 tree.out 依...

JdonFramework領域模型驅動

概念 領域模型是對領域內的概念類或現實世界中物件的視覺化表示。又稱概念模型 領域物件模型 分析物件模型。它專注於分析問題領域本身,發掘重要的業務領域概念,並建立業務領域概念之間的關係。領域模型 domain model 是描述業務用例實現的物件模型。它是對業務角色和業務實體之間應該如何聯絡和協作以執...

DDD領域驅動設計 充血模型 貧血領域模型

最早廣泛應用源於ejb2,最強盛時期則是由spring創造,把 分離到不同的物件中 貧血領域模型是乙個存在已久的反模式,它不是個好東西。它完全和物件導向設計背道而馳。物件導向設計主張將資料和行為繫結在一起,而貧血領域模型則更像是一種面向過程設計。貧血領域模型的根本問題在於,它引入了領域模型設計的所有...