我想知道使用贫血域模型的优点和缺点(请参阅下面的链接)。
最佳答案
既然“贫血领域模型”是反模式,为什么有这么多系统实现这个?
我认为有几个原因
<强>1。系统的复杂性
在一个简单的系统中(几乎是您在互联网上找到的所有示例和示例代码)如果我想实现:
将产品添加到订单
我把这个功能放在订单上
public void Order.AddOrderLine(Product product)
{
OrderLines.Add(new OrderLine(product));
}
优秀且 super 面向对象。
现在假设我需要确保我需要验证该产品是否存在于库存中,如果不存在则抛出异常。
我不能再把它放在订单上,因为我不希望我的订单依赖于库存,所以现在它需要放在服务上
public void OrderService.AddOrderLine(Order order, Product product)
{
if (!InventoryService.Has(product)
throw new AddProductException
order.AddOrderLine(product);
}
我还可以将 IInventoryService 传递给 Order.AddOrderLine,这是另一种选择,但这仍然使 Order 依赖于 InventoryService。
Order.AddOrderLine 中仍然有一些功能,但通常仅限于订单范围,而根据我的经验,还有很多业务逻辑超出订单范围。
当系统不仅仅是基本的 CRUD 时,您最终将在 OrderService 中得到大部分逻辑,而在 Order 中得到很少的逻辑。
<强>2。开发者对 OOP 的看法
互联网上有很多关于实体应该采用哪种逻辑的激烈讨论。
类似于
订单.保存
Order是否应该知道如何拯救自己?假设我们有相应的存储库。
订单现在可以添加订单行吗?如果我尝试用简单的英语来理解它,它也没有真正的意义。用户将产品添加到订单中,那么我们应该执行 User.AddOrderLineToOrder() 吗?这似乎有点矫枉过正。
OrderService.AddOrderLine() 怎么样。现在看来有点道理了!
我对 OOP 的理解是,为了封装,你将函数放在类上,函数需要访问类的内部状态。如果我需要访问 Order.OrderLines 集合,我会将 Order.AddOrderLine() 放在 Order 上。这样类的内部状态就不会暴露。
<强>3。 IoC 容器
使用 IoC 容器的系统通常是完全贫乏的。
这是因为您可以测试具有接口(interface)的服务/存储库,但无法(轻松)测试域对象,除非您将接口(interface)放在所有这些对象上。
由于“IoC”目前被誉为解决所有编程问题的解决方案,因此很多人盲目遵循它,这种方式最终导致贫血领域模型。
<强>4。面向对象很难,过程很容易
我在这个上有一点“Curse of Knowledge”,但我发现 对于新开发人员来说,拥有 DTO 和服务比 Rich Domain 容易得多。
可能是因为使用 Rich Domain 更难知道将逻辑放在哪些类上。什么时候创建新类?使用哪些模式?等等..
使用无状态服务,您只需将其放入名称最接近的服务中即可。
关于language-agnostic - 贫血域模型 : Pros/Cons,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/258534/