筆記 Anaemic Domain Model (ADM) 與 Rich Domain Model 的優缺點。
說明
Anaemic Domain Model
Anaemic Domain Model (ADM) 是一種將業務邏輯與資料庫操作分離的程式設計模式,通常是將所有的業務邏輯都放在 Service 層中,而 Entity 或 DTO 則只是一個純資料容器。以下是 ADM 的優點與缺點:
✔️ 優點
- 簡單易學:ADM 模式簡單,不需要太多的概念,對於新手來說比較容易上手。
- 易於測試:由於業務邏輯都放在 Service 層中,業務邏輯和資料操作分離,因此容易進行單元測試。
❌ 缺點
- 違反 OOP:ADM 中的 Entity 或 DTO 只是純資料容器,而所有的業務邏輯都在 Service 層中,這導致了 ADM 違反了 OOP 或者是說不那麼地符合 OOP 😗
- 維護困難:由於業務邏輯都放在 Service 層中,當業務邏輯變得複雜時,Service 層會變得越來越龐大,維護困難。
Entity.cs / DTO.cs
public class Product {
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
Service.cs
public class ProductService {
private readonly DbContext _dbContext;
public ProductService(DbContext dbContext) {
_dbContext = dbContext;
}
public List<Product> GetAllProducts() {
return _dbContext.Products.ToList();
}
public void CreateProduct(Product product) {
_dbContext.Products.Add(product);
_dbContext.SaveChanges();
}
}
public class ProductController : Controller {
private readonly ProductService _productService;
public ProductController(ProductService productService) {
_productService = productService;
}
public IActionResult Index() {
var products = _productService.GetAllProducts();
return View(products);
}
[HttpPost]
public IActionResult Create(Product product) {
_productService.CreateProduct(product);
return RedirectToAction("Index");
}
}
Rich Domain Model
✔️ 優點
- 符合 OOPRDM 能夠將業務邏輯與資料庫操作整合在同一個類別中,符合 OOP,也有助於提高程式碼的可讀性和可維護性。
- 降低耦合度:由於 RDM 中的類別具有業務邏輯和資料操作的功能,因此不需要像 ADM 一樣依賴 Service 層,降低了系統中各個模組之間的耦合度。
❌ 缺點
- 學習曲線較高:相較於 ADM,RDM 需要更多的 OOP 學習與設計。
- 單元測試較難:RDM 中的類別具有業務邏輯和資料操作的功能,因此測試需要涵蓋更多的層次,較難進行單元測試。
Domain.cs
public class Product {
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public void Create() {
// Business Logic
}
public void Update() {
// Business Logic
}
public void Delete() {
// Business Logic
}
}
Controller.cs
// Controller
public class ProductController : Controller {
private readonly DbContext _dbContext;
public ProductController(DbContext dbContext) {
_dbContext = dbContext;
}
public IActionResult Index() {
var products = _dbContext.Products.ToList();
return View(products);
}
[HttpPost]
public IActionResult Create(Product product) {
product.Create();
_dbContext.Products.Add(product);
_dbContext.SaveChanges();
return RedirectToAction("Index");
}
[HttpPost]
public IActionResult Edit(Product product) {
product.Update();
_dbContext.Products.Update(product);
_dbContext.SaveChanges();
return RedirectToAction("Index");
}
[HttpPost]
public IActionResult Delete(int id) {
var product = _dbContext.Products.Find(id);
product.Delete();
_dbContext.Products.Remove(product);
_dbContext.SaveChanges();
return RedirectToAction("Index");
}
}
參考資料
Anemic data models (ADM) VS Rich Data Models (RDM) in C#
Anaemic Domain Model vs. Rich Domain Model