貧血領域模型(anemic domain model)是一種軟體開發的模型,是指其領域物件只有部份业务逻辑(例如資料驗證、計算、規則等),甚至沒有任何业务逻辑。像以下的模型就是貧血領域模型,有資料讀取和寫入的介面函式,但沒有其他函式。
class Rectangle
{
public int Height { get; set; }
public int Width { get; set; }
}
貧血領域模型的业务逻辑會放在程式的架構或是其他組件中,會讓重構和維護變得困難費時。在面向对象程序设计中將此視為反面模式。
簡介
此模式最早是由马丁·福勒提出,他當時就認為這是反面模式:
在貧血領域設計中,業務邏輯是另外用類別來實現,以此轉換領域物件的狀態。福勒將這些外部類別稱為事務腳本(transaction scripts),此模式常見於Java應用程式裡,像的早期版本也鼓勵此一作法。
福勒認為事務腳本模式是:
福勒在《Patterns of Enterprise Application Architecture》中提到事務腳本模式可能適合小的業務應用,省去了複雜了物件導向資料庫映射層。
貧血領域模型可能出現在受服務導向架構影響的系統中,其行為不會(或不傾向)跟著資料流動,像Messaging架構,pipeline架構,或SOAP/REST API,都屬於其行為不跟著資料流動的例子。像COM+和Remoting的架構允許有行為,但越來越多的網站傾向不連線,無狀態(stateless)的架構。
上述論點的批評
有關將貧血領域模型視為反面模式的看法,也有些人有不同的意見,有些人也看到其中的優點,例如:
- 清楚的區分邏輯和資料
- 在簡單的應用程式中運作良好
- 應用程式是無狀態的邏輯,有利於橫向擴展
- 不需要複雜的物件導向資料庫映射層
- 和映射和注入框架的相容性更高,這些框架期望使用靜態屬性,而不是特定的建構函數或屬性填充順序
不過,依照Robert C. Martin的觀點,這是對此原則的誤解:在所有SOLID的原則中,单一功能原则是最少人真正理解的。這可能是因為它有一個特別不適合的名稱,太容易讓程式設計者看到名稱,就假設每一個模組應該做一件事,沒錯,的確有這樣的原則,一個函式應該做一件事,而且只做一件事。我們在將大的函式重構成小函式時就是使用此原則:甚至用到最底層,但這不是SOLID原則中的一項,這不是单一功能原则(...)。单一功能原则的最終版本是:每一個模組應該對一個提出需求的角色(actor),提供服務,也只對這一個角色提供服務"
風險
若使用貧血領域模型,程式設計者需考慮以下的風險:
- 無法以真正物件導向的作法實現邏輯
- 違反物件導向的封裝和資訊隱藏的原則。
- 需要獨立的業務層來包括不在领域模型裡的邏輯,這也代表领域模型物件任何時候都無法確保其正確性,因為其驗證和變異邏輯都在其他模組裡(可能還分散在多處)
- 若要在物件模型的不同消費者中共享資料,需要服務層。
- 模型的表現力較低,無法清晰、直觀地傳達所代表的業務概念或邏輯。
範例
貧血領域模型可能會像以下的方式撰寫程式,程式本身沒有包括任何業務的考量(以此例中,包括高度和寬度不能是負數或是零,或是有其他有關正方形面積的需求。這表示這些機能是在其他模組中實現的,不在此程式的業務層,而是藏在架構其他的部份。
class Rectangle
{
public int Height { get; set; }
public int Width { get; set; }
}
非貧血領域模型的寫法如下。會將業務考量加到領域物件上,此時的架構可以更不受領域影響。這讓程式可以假設物件的一些屬性成立,不用在架構中的某處來實現此屬性的檢查程式。
class Rectangle
{
public Rectangle(int height, int width)
{
SetHeight(height);
SetWidth(width);
}
public int Height { get; private set; }
public int Width { get; private set; }
public void SetHeight(int height)
{
if (height
相關條目
- 一般Java物件(POJO)
- 領域驅動設計
- GRASP裡的資料專家
參考資料
外部連結
*[http://www.martinfowler.com/bliki/AnemicDomainModel.html Anemic Domain Model] by Martin Fowler
*[http://msdn.microsoft.com/en-us/library/ms978689.aspx Three-Layered Services Application]
*[https://web.archive.org/web/20070713065345/http://msdn2.microsoft.com/en-us/library/ms954595.aspx Application Architecture for .NET: Designing Applications and Services]
*[https://blog.inf.ed.ac.uk/sapm/2014/02/04/the-anaemic-domain-model-is-no-anti-pattern-its-a-solid-design Article on why anemic model may be considered good design]
*[https://msdn.microsoft.com/en-us/magazine/mt703433.aspx Writing Clean Code in ASP.NET]
*[https://medium.com/@wrong.about/how-to-avoid-anemic-domain-model-5e1c3e6fe4d0 How to Avoid Anemic Domain Model]
评论 (0)