2009-08-26 88 views
9

比方說,我有典型的實體汽車DDD:亞類根實體

class Car : Entity 
{ 
    public double MaxSpeed { get; set; } 
    public Color Color { get; set; } 
    /* ... */ 
} 

這個實體,在我的域模型,將是一個聚合根實體

現在讓我們說我專注於汽車。我創建了一個法拉利,和法拉利的車主高興通過像一個綽號叫他們:

class Ferrari : Car 
{ 
    public string Nickname { get; set; } 
} 

比方說,我有另外一個實體,在公司實體。這將是根實體的另一個總計。有很多人在一家公司工作,由實體代表。人可能有汽車。但公司的總統通常是非常豐富,這樣的人,他們有法拉利:

class President : Person 
{ 
    public Ferrari Ferrari { get; set; } 
} 

在這種情況下,我有實體總統,誰是公司彙總,這是持有一個法拉利的參考,專業化的另一個聚合的根實體。

鑑於DDD,這是否正確?可以/我應該考慮將根實體本身作爲同一個聚合的根實體嗎?我的意思是,在我所描述的領域中,實體法拉利也是汽車總成的根本實體(因爲法拉利也是汽車)?


現在,讓我們說,我要堅持這個模型到數據庫。我認爲我的問題不依賴於我將使用的OR/M框架。

我應該如何建造桌上持有汽車?我是否應該建立一個帶有「CarType」列的Cars Cars(可能的值:「Car」,「Ferrari」)和一個可以爲空的暱稱列?

或者我應該爲Cars創建一張桌子,爲Ferraris創建一個桌子,後者的PK有FK的Cars?

謝謝!

回答

2

我認爲你通過創建這些實體的具體類型而開始喪失很多系統的靈活性。您暗示的關係類型通常是我通常使用的「類型」實體。例如,你有一輛車。法拉利是一種汽車。由此產生的兩個實體是Car和CarType。

你正在談論這樣做的方式,每次引入新類型時都必須添加新實體。如果你試圖捕捉的所有東西都是汽車的「綽號」,那麼我認爲那只是另一部分數據,而不是另一個實體。除非你有不同的數據(即不同的屬性名稱)和/或不同類型的汽車實體的行爲差異,這種方法不會獲得太多收益。我寧願使用像FindCarByType()這樣的存儲庫方法來處理一種類型的實體,以降低風險。

我絕不是DDD專家,而我正在爲一些概念而奮鬥(或者更像是在對一些概念的多重解釋中掙扎)。我發現沒有100%純粹的實現,並且我看到每個實現都有細微差別。

編輯遵循

我看到,我誤解你寫哪一部分。我看到這個綽號並非針對所有車輛,而是針對法拉利:車。我認爲答案確實「取決於」。你在模型的其餘部分有多少專業領域?擁有一個綽號可能在法拉利實體中流行,但是它是排他性的嗎?它不僅關於實際數據,而且關於要求。基本上,這取決於您在這些實體中期望的專業化程度。

+0

太棒了!謝謝!事實上,在我的「真實」系統中,「汽車」是非常重要的,但「法拉利」是我的領域中唯一最重要的東西,我不能疏忽跟蹤,我必須對其進行統計。 – 2009-08-29 21:55:43

4

您不應該使用繼承來爲您的域建模,因爲一旦模型開始變得複雜,您很快就會遇到麻煩。

總統只是一個角色,人和人可以有多個角色。也許總統只有一個角色,但選擇錯誤的例子只是偶然的。

法拉利不應該從汽車繼承。在法拉利的例子中並不明顯,因爲他們只做一種類型的汽車,但考慮製造各種類型的公司,如廂式貨車,轎車,掀背車,卡車等。您可能會想要爲從汽車類繼承的每種類型創建類。然後,你會做出五種豐富的類別,從每種類型繼承下來嗎?如...

Car -> Sedan -> ToyotaSedan 
Car -> Truck -> ToyotaTruck 
Car -> Hatchback -> ToyotaHatchback 

這將是荒謬的。

聲明:我對汽車一無所知。但是...

不要使用繼承來爲您的域建模。永遠。

嘗試沒有繼承,它也將成爲顯而易見的如何堅持你的域名。

+0

謝謝,盧博斯。但在這種情況下,在我的「真實」領域,我*有*「汽車」,並且有「通用」汽車和兩種特殊類型的汽車,「法拉利」和「保時捷」必須被追蹤,儘管它們是基本上是「汽車」。 – 2009-08-29 21:58:19

+3

還是要避免繼承。即使你不這樣做,你也需要在一兩年內完成,因爲你的模型未來可能會變得更加複雜以捕捉新的需求,並且繼承會給你的設計帶來很大的痛苦。教科書中解釋貓和狗的遺傳的例子都是動物和圓形和方形都是形狀給人錯誤的印象什麼是繼承真正的,程序員經常濫用這個強大的概念來建模域。閱讀更多在這裏:http://www.geocities.com/tablizer/oopbad.htm#overeng(我不是作者) – 2009-08-29 22:42:28

+0

非常好的文章!謝謝! – 2009-08-29 23:02:31

3

通常,當您跨越根集合邊界時,只允許引用是另一個根集合的ID。然後使用該ID在其存儲庫中查找另一個聚合。

所以在你的情況下,你會希望總統有一個車號,如果你需要對總統的車做些什麼,你可以使用車號到車庫去取車。總統不會提及汽車本身。

現在關於那輛法拉利。在標準的DDD術語中執行這種操作是很困難的。通常情況下,你會對分配給總統的汽車進行一些驗證。或者可能有一個只爲總統提供的CarBuyingService服務,以確保您的服務是正確的。通常在DDD專業本身並不是根本的總和。

+0

你是唯一真正回答問題的人 – 2017-11-27 22:55:53