五 領域驅動設計-軟件中所表示的模型

軟件中所表示的模型

表示模型的3種模型元素模式:ENTITY、VALUE OBJECT和SERVICE。從表面上看,定義那些用來捕獲領域概念的對象很容易,但要想反映其含義卻很困難。這要求咱們明確區分各類模型元素的含義,並與一系列設計實踐結合起來,從而開發出特定類型的對象。數據庫

我的理解:就是實體類(entity),VALUE OBJECT(值對象,我沒懂)和服務(service),開發人員一看就懂了。性能優化

關聯

對象之間的關聯使得建模與實現之間的交互更爲複雜。模型中每一個可遍歷的關聯,軟件中都要有一樣屬性的機制。架構

一個顯示了顧客與銷售表明之間關聯的模型有兩個含義。一方面,它把開發人員所認爲的兩個真實的人之間的關係抽象出來。另外一方面,它至關於兩個Java對象之間的對象指針,或者至關於數據庫查詢(或相似實現)的一種封裝。框架

例如,一對多關聯能夠用一個集合類型的實例變量來實現。但設計無需如此直接。可能沒有集合,這時可使用一個訪問方法(accessor method)來查詢數據庫,找到相應的記錄,並用這些記錄來實例化對象。這兩種設計方法反映了同一個模型。設計必須指定一種具體的遍歷機制,這種遍歷的行爲應該與模型中的關聯一致。數據庫設計

現實生活中有大量‚多對多‛關聯,其中有不少關聯天生就是雙向的。咱們在模型開發的早期進行頭腦風暴活動並探索領域時,也會獲得不少這樣的關聯。但這些廣泛的關聯會使實現和維護變得很複雜。此外,它們也不多能表示出關係的本質。分佈式

至少有3種方法可使得關聯更易於控制。性能

(1) 規定一個遍歷方向。優化

(2) 添加一個限定符,以便有效地減小多重關聯。設計

(3) 消除沒必要要的關聯。指針

儘量地對關係進行約束是很是重要的。雙向關聯意味着只有將這兩個對象放在一塊兒考慮才能理解它們。當應用程序不要求雙向遍歷時,能夠指定一個遍歷方向,以便減小相互依賴,並簡化設計。理解了領域以後就能夠天然地肯定一個方向。

我的理解:上面的內容技術人員不要看啦,很難理解,我告訴你是怎麼一回事。技術角度就是兩個對象的關聯關係以下:一對一(一我的一個鼻子),一對多(一我的兩個手臂),多對多(一我的報名多個課程,一個課程有多我的報名)。是否是很像數據庫設計模型?

ENTITY(又稱爲REFERENCE OBJECT)

開始講故事:能夠不聽,由於我會用一句話總結,很是簡單。

軟件系統中的大多數‚ENTITY‛並非人,也不是其一般意義上所指的‚實體‛或‚存在‛。ENTITY能夠是任何事物,只要知足兩個條件便可,一是它在整個生命週期中具備連續性,二是它的區別並非由那些對用戶很是重要的屬性決定的。ENTITY能夠是一我的、一座城市、一輛汽車、一張彩票或一次銀行交易。

一位女房東起訴了我,要求我賠償她房屋的大部分損失。訴狀上是這樣寫的:房間的牆上有不少小洞,地毯上盡是污漬,水池裏的髒物散發出的腐蝕性氣體致使廚房牆皮脫落。法庭文件認定我做爲承租人應該爲這些損失負責,依據就是個人名字和我當時的地址。這把我徹底搞糊塗了,由於我從未去過那個被損壞的房子。

過了一下子,我意識到這必定是認錯人了。我給原告打電話,告訴她這一點,但她並不相信我。幾個月以來,上一位租客一直在躲避她。如何才能證實我不是那個破壞她房屋的人呢?如今電話簿裏只有一個Eric Evans名字,那就是我。仍是電話簿成了個人救星。因爲我在這所公寓裏已經住了兩年,因而我問她是否還有去年的電話簿。她找到了電話簿,發現有與我同名的人(我就在那我的下面),她意識到我不是她要起訴的那我的,因而向我道歉,並答應撤銷起訴。

計算機可不會這麼‚神機妙算‛。軟件系統中的錯誤標識將致使數據破壞和程序錯誤。

主要由標識定義的對象被稱做ENTITY[。ENTITY(實體)有特殊的建模和設計思路。它們具備生命週期,這期間它們的形式和內容可能發生根本改變,但必須保持一種內在的連續性。爲了有效地跟蹤這些對象,必須定義它們的標識。它們的類定義、職責、屬性和關聯必須由其標識來決定,而不依賴於其所具備的屬性。即便對於那些不發生根本變化或者生命週期不太複雜的ENTITY,也應該在語義上把它們做爲ENTITY來對待,這樣能夠獲得更清晰的模型和更健壯的實現。

固然,軟件系統中的大多數‚ENTITY‛並非人,也不是其一般意義上所指的‚實體‛或‚存在‛。ENTITY能夠是任何事物,只要知足兩個條件便可,一是它在整個生命週期中具備連續性,二是它的區別並非由那些對用戶很是重要的屬性決定的。ENTITY能夠是一我的、一座城市、一輛汽車、一張彩票或一次銀行交易。

當一個對象由其標識(而不是屬性)區分時,那麼在模型中應該主要經過標識來肯定該對象的定義。使類定義變得簡單,並集中關注生命週期的連續性和標識。定義一種區分每一個對象的方式,這種方式應該與其形式和歷史無關。要格外注意那些須要經過屬性來匹配對象的需求。在定義標識操做時,要確保這種操做爲每一個對象生成惟一的結果,這能夠經過附加一個保證惟一性的符號來實現。這種定義標識的方法可能來自外部,也多是由系統建立的任意標識符,但它在模型中必須是惟一的標識。模型必須定義出「符合什麼條件纔算是相同的事物」。

在現實世界中,並非每個事物都必須有一個標識,標識重不重要,徹底取決於它是否有用。實際上,現實世界中的同一個事物在領域模型中可能須要表示爲ENTITY,也可能不須要表示爲ENTITY。

我的理解:一句話,設計實體的時候最好有一個全局惟一id的屬性。相信作技術的會以爲,上面說了這麼多就是這個意思,太簡單了,沒錯,就是這麼簡單,關鍵是,咱們有本事寫那麼多的字來表述(瞎扯)嗎?

模式:VALUE OBJECT

不少對象沒有概念上的標識,它們描述了一個事務的某種特徵。當一個小孩畫畫的時候,他注意的是畫筆的顏色和筆尖的粗細。但若是有兩隻顏色和粗細相同的畫筆,他可能不會在乎使用哪一支。若是有一支筆弄丟了,他能夠從一套新筆中拿出一支一樣顏色的筆來繼續畫,根本不會在乎已經換了一支筆。

問問孩子冰箱上的畫都是誰畫的,他會很快辨認出哪些是他畫的,哪些是他姐姐畫的。姐弟倆有一些實用的標識來區分本身,與此相似,他們完成的做品也有。但設想一下,若是孩子必須記住哪些線條是用哪支筆畫的,狀況該有多麼複雜?若是這樣的話,畫畫將再也不是小孩子的遊戲了。

因爲模型中最引人注意的對象每每是ENTITY,並且跟蹤每一個ENTITY的標識是極爲重要的,所以咱們很天然地會想到爲每一個領域對象都分配一個標識。實際上,一些框架確實爲每一個對象分配了一個惟一的ID。

這樣一來,系統就必須處理全部這些ID的跟蹤問題,從而致使許多原本可能的性能優化不得不被放棄。此外,人們還須要付出大量的分析工做來定義有意義的標識,還須要開發出一些可靠的跟蹤方式,以便在分佈式系統或在數據庫存儲中跟蹤對象。一樣重要的是,盲目添加無實際意義的標識可能會產生誤導。它會使模型變得混亂,並使全部對象看起來千篇一概。

我的理解:VALUE OBJECT 能夠理解entity去掉惟一性的id,變成了無狀態的一個對象。

VALUE OBJECT能夠是其餘對象的集合。在房屋設計軟件中,能夠爲每種窗戶樣式建立一個對象。咱們能夠將‚窗戶樣式‛連同它的高度、寬度以及修改和組合這些屬性的規則一塊兒放到‚窗戶‛對象中。這些窗戶就是由其餘VALUE OBJECT組成的複雜VALUE OBJECT。它們進而又被合併到更大的設計元素中,如‚牆對象。

VALUE OBJECT常常做爲參數在對象之間傳遞消息。它們經常是臨時對象,在一次操做中被建立,而後丟棄。VALUE OBJECT能夠用做ENTITY(以及其餘VALUE)的屬性。咱們能夠把一我的建模爲一個具備標識的ENTITY,但這我的的名字是一個VALUE。

當咱們只關心一個模型元素的屬性時,應把它歸類爲VALUE OBJECT。咱們應該使這個模型元素可以表示出其屬性的意義,併爲它提供相關功能。VALUE OBJECT應該是不可變的。不要爲它分配任何標識,並且不要把它設計成像ENTITY那麼複雜。

SERVICE

有時,對象不是一個事物。在某些狀況下,最清楚、最實用的設計會包含一些特殊的操做,這些操做從概念上講不屬於任何對象。SERVICE是做爲接口提供的一種操做,它在模型中是獨立的,它不像ENTITY和VALUE OBJECT那樣具備封裝的狀態。SERVICE是技術框架中的一種常見模式,但它們也能夠在領域層中使用。所謂SERVICE,它強調的是與其餘對象的關係。與ENTITY和VALUE OBJECT不一樣,它只是定義了可以爲客戶作什麼。SERVICE每每是以一個活動來命名,而不是以一個ENTITY來命名,也就是說,它是動詞而不是名詞。SERVICE也能夠有抽象而有意義的定義,只是它使用了一種與對象不一樣的定義風格。SERVICE也應該有定義的職責,並且這種職責以及履行它的接口也應該做爲領域模型的一部分來加以定義。操做名稱應來自於UBIQUITOUS LANGUAGE,若是UBIQUITOUS LANGUAGE中沒有這個名稱,則應該將其引入到UBIQUITOUS LANGUAGE中。參數和結果應該是領域對象。

好的SERVICE有如下3個特徵。

(1) 與領域概念相關的操做不是ENTITY或VALUE OBJECT的一個天然組成部分。

(2) 接口是根據領域模型的其餘元素定義的。

(3) 操做是無狀態的。

我的理解:就是面向接口的設計,提供的就是服務。

MODULE(也稱爲PACKAGE)

MODULE是一個傳統的、較成熟的設計元素。每一個人都會使用MODULE,但卻不多有人把它們當作模型中的一個成熟的組成部分。代碼按照各類各樣的類別進行分解,有時是按照技術架構來分割的,有時是按照開發人員的任務分工來分割的。甚至那些從事大量重構工做的開發人員也傾向於使用項目早期造成的一些MODULE。MODULE之間應該是低耦合的,而在MODULE的內部則是高內聚的。耦合和內聚的解釋使得MODULE聽上去像是一種技術指標,彷彿是根據關聯和交互的分佈狀況來機械地判斷它們。然而,MODULE並不只僅是代碼的劃分,並且也是概念的劃分。一我的一次考慮的事情是有限的(所以纔要低耦合)。不連貫的思想和「一鍋粥」似的思想一樣難於理解(所以纔要高內聚)。

低耦合高內聚做爲通用的設計原則既適用於各類對象,也適用於MODULE,但MODULE做爲一種更粗粒度的建模和設計元素,採用低耦合高內聚原則顯得更爲重要。這些術語由來已久,早在[Larman 1998]中就從模式角度對其進行了解釋。

我的理解:包,關注高內聚低耦合就對了。

相關文章
相關標籤/搜索