1. 程式人生 > >領域驅動設計:理念,架構和若干重要細節(draft)

領域驅動設計:理念,架構和若干重要細節(draft)

緒論:

三點:軟體開發的方法論,討論系統分層的必要性,提出構建領域模型的重要性;討論OO技術是構建領域模型的主角;

爭論:面向物件還是面向資料?一個

企業級應用的系統架構是應該面向物件還是面向資料的爭論由來已久,並且從未停止過.這是一個非常尖銳且很難抉擇的問題.產生這一問題的根源就在於當前企業級應用所依賴的資料庫幾乎無一例外的都是關係型資料庫,關係型資料已經盛行了很多年,它也確實....但是後來隨著面向物件技術的興起,人們意識到面向物件技術在解決複雜業務問題上有著無可比擬的優勢.這又驅使人們試圖通過oo技術構建一個領域模型來處理業務邏輯.然後面向物件的領域模型和麵向關係的資料模型天生存在著巨大的差異,這種差異使得企業級應用中構建領域模型變得

  在基於企業級應用必須依賴於關係資料庫的前提下,人們並沒有放棄通過OO技術構建領域模型的嘗試,隨著這方面的理論不斷地成熟,具有實際可操作性的設計模式被總結並加以應用,人們逐漸地總結出了一整套將物件模型對映成關係模型的理論和方法,併產生了很多優秀的ORM框架,從而在關係模型和領域模型之間構建起一座橋樑,讓開發人員得以通過OO技術來解決複雜的領域問題.

  客觀地講,當今的企業級應用的主流依然是以面向資料為主.

  我們無意要在這裡比較孰優孰略,但是一般而言,對於那些資料量巨大,效能要求較高的系統,面向資料的架構要更好一些,而對於業務邏輯複雜,需求變動頻繁的系統,面向領域的架構會更加適合.當然,正所謂技高人膽大,想要做到魚和熊掌兼得,也不是不可能的.如何權衡整體的得失做出全域性性的決策,讓系統的綜合性能達到最高,是一名架構師安身立命的核心技能之一.

1.領域模型:重中之重

從mvc談起,涉及CC中關於軟體複雜度管理的論述.

若干處來,MVC之所以成為一種廣泛應的經久不衰的架構模式,根本原因在於它對一個軟體系統做了合理的劃分

自...以來,人類之所以能夠完成各種巨集大的工程,無不在應用這樣一條放之四海而皆準的原則:將複雜任務分解為多個簡單的子任務!也就是"關住點分離".MVC便是這一恩想下的典型架構

2.領域模型中的重要元素:

Entities

Value Objects

Aggregates

Domain Events

2.ORM不能迴避的現實問題

在構建領域模型時,ORM確實是非常非常重要的一環.而且這一環也非常複雜,包括類繼承體系與資料庫的對映,抓取策略和快取管理在內的一系列問題都是非常棘手的.即使我們現在已經有了像Hibernate這樣優秀成熟的ORM框架,開發人員依然必須對ORM的原理和內部機制有深入地瞭解才能完成這一工作.否則領域模型很可能會受到資料庫關係模型的"汙染"進而被"同化",或者更常見的情況是因為糟糕的對映導致系統性能嚴重下降.講到這裡想說句題外話.筆者認識很多從事企業級應用開發的朋友,他們中有很多學習和使用Hibernate已經有三四年了,但是自覺依然不得要領,他們在專案中總是固定使用Hibernate中的"一小部分"功能,對一些所謂的"高階"機制從為涉及過,而且也找不適用的場合.這說明他們過去參與過的專案並沒有構建過直正的領域模型.如果我們從領域模型的角度出發去思考物件應該如何從資料庫中重建出來,我們就會發現我們會面臨很多"必須"面對的問題,當你帶著這些問題去學習一個ORM框架時,你會驚奇地發現,你所想到過的這些問題框架都給出瞭解決方案.學習ORM框架,必須要有面向物件方面的設計思想作為背景,總是從領域模型出發思考如何對映到資料庫,如何從資料庫中加載出物件才能領悟ORM框架的真實用意.

阻抗失配

關於效能的考量;可選方案.

3.IOC&AOP:重要的補充

雖然人們將IOC視為一種設計模式,但由於IOC所解決的問題幾乎是所有OO系統都會遇到的,也可以說是OO技術本身在物件建立方面的缺失或者說是天生不足,這才導致IOC變得如此必須.,顯然,IOC有著超越一般設計模式的重要地位,

如同rod jonason所讚歎:"再怎麼讚揚IOC的好處都不為過!",IOC對於OO來說,就如同

4.團隊管理和工作流程

5.應用領域驅動設計的面臨的巨大挑戰

面向資料還是面向領域?這是個問題!

為什麼有如此之多的系統是面向資料而不是面向領域的?

 DDD一書中引入的獨創性概念中,Aggregation是非常重要的一個.這個概念在此之前從末被提出過,它對進一步合理細分領域模型提供了非常好的理論依據.劃分Aggregation是對領域模型的進一步深化,Aggregation能闡釋領域模型內部物件之間的深層關聯.對Aggregation的劃分會直接對映到程式結構上.比如:DDD推薦按Aggregation設計model的子包.每個Aggregation配備一個Repository.Aggregation內部的非root物件是通過導航獲得的.等等.

若干重要細節:

1.如何建立完整,自封閉的領域模型。舉例:user.subscribe()和user.post(Message reply)

所有的外部請求到達應用層後,應用層知道如何把外部請求轉換成驅動模型運轉的指令,模型根據指令運轉到達結果狀態,外部檢視選取模型中使用者關心的部分呈現出來。

2.如何建模領域服務。

3.關於領域物件的依賴注入

參考:AspectJ in Action

Spring參考文件:6.8.1. Using AspectJ to dependency inject domain objects with Spring

4.Repository VS. DAO

Repository:位於領域層,面向Aggregation Root。

DAO:是面向資料訪問的,不再需要。在領域領域驅動的專案中,去除DAO,淡化資料訪問的概念,使用更加OO的Repository來替代。

5.關於領域物件和領域服務以及Repository之間的互相依賴問題。

當領域物件所需要的資料需要通過查詢得到時應該怎麼辦?

1.通過為領域物件注入Repository來實現。

2.通過非同步訊息機制+Domain Event的形式來實現

考慮核心問題:領域物件可不可以依賴Repository?

一種聲音:有個感覺是無論是DAO或者是Resposity,都是domain logic裡的噪聲。如果Domain logic也能透明的呼叫DAO或Respoisty,這樣的domain模型會更完美,而且更關注業務。

這麼說來repository只用來取root?從概念上講不錯,可是要知道往往一個root下面會有成百上千個node,這麼巨大的一坨關係樹我們用repository取出來然後在“關係之間遊走”...是否有點滑稽?呃...或許我們能想到引入延遲載入,取出來的root下的二級node都用stub來佔位;不過這又為汙染我們純潔的領域模型創造了良機...

我們常說的“領域模型”是一個分析模型,是對領域問題的整體表述,決不是程式設計的實現模型,一個領域概念不一定會隱射成一個類,有可能要對映很多的類。同樣,我們的實現模型也有很多領域模型不設計或不關心的東西,像領域物件的crud,等。這對我們是一個啟示,在從領域模型到實現模型的隱射過程中,我們要明白它們各自的本質。這對實現模型的組織結構也有一定的借鑑意義。

“領域模型”是一個針對業務邏輯抽象的模型,是一組概念的集合,和軟體程式設計並無關係。

Repository的角色和Factory有些類似,它是一種程式設計層面上的Artifact,並無業務意義。對於它在架構中的位置,可能放在Model裡會好些。就像是Factory總是伴隨它的產品在一起一樣。

架構:

1.包結構:

領域層應該按業務邏輯相關性(即aggregation)來組織。

應用層面向外部應用,不應該使用領域層的分割模式。展現層同樣如此。

關於領域層的各物件:

領域物件和領域服務是領域模型的主體,地位相當,應等同對待。

Repository和Factory一樣,屬於設計和實現層面的衍生產物,在領域模型中沒無對應概念,但是確實應該置於領域層!

DDDSample中把一些依賴具體框架的實現類劃分到infrastructure包的做法,並不是一個好的做法。這分法試圖突出領域層的“純粹性”,但是,我們要明確,領域模型並不是領域層,領域層是領域模型的程式設計實現,既然是“實現”,那些具體類是不可避免的。它們是“實現模型”的重要組成部分!如果隔離到nfrastructure包,反而在包結構上讓它與它們的實現類產生較大的距離,這種包結構好不到哪裡去。