language-agnostic - 贫血域模型 : Pros/Cons

标签 language-agnostic design-patterns

我想知道使用贫血域模型的优点和缺点(请参阅下面的链接)。

Fowler Article

最佳答案

既然“贫血领域模型”是反模式,为什么有这么多系统实现这个?

我认为有几个原因

<强>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/

相关文章:

c# - OOPS 和 ADO.Net

java - 避免在抽象类的子类上重复代码

python - 如何删除这些 keras 指标定义的重复?

algorithm - 找到线段上等距点的最大数量

math - float 学有问题吗?

ruby - 有效地处理数字数组的 "scale"或 "resize"的算法(音频重采样)

java - 从库中删除已弃用的功能

java - 对于泛型/与泛型有哪些有用的 API?

security - 桌面应用程序应该静默更新吗?

java - 存储库模式的优点和 Spring 实现