Language agnostic 贫血领域模型:优缺点
我想知道使用贫血领域模型的利弊(见下面的链接)Language agnostic 贫血领域模型:优缺点,language-agnostic,design-patterns,Language Agnostic,Design Patterns,我想知道使用贫血领域模型的利弊(见下面的链接) 在我看来,福勒的主要反对意见是,从以下意义上讲,ADM不是OO。如果一个人“从头开始”围绕被动数据结构设计一个系统,而被动数据结构是由其他代码段操纵的,那么这显然更像是过程设计,而不是面向对象的设计 我建议至少有两种力可以产生这种设计: 仍然认为需要在面向对象的环境中工作(或假设他们可以…)以生成新系统的设计师/程序员,以及 开发人员致力于将类似“face”的服务放在以非面向对象方式设计的遗留系统上(不考虑语言) 例如,如果要构建一组服务来公开现有
在我看来,福勒的主要反对意见是,从以下意义上讲,ADM不是OO。如果一个人“从头开始”围绕被动数据结构设计一个系统,而被动数据结构是由其他代码段操纵的,那么这显然更像是过程设计,而不是面向对象的设计 我建议至少有两种力可以产生这种设计:
- 你可以声称它是一个域模型 并向您的开发人员朋友吹嘘 把它写在你的简历上
- 它很容易自动生成 从数据库表
- 它映射到数据传输对象 出人意料地好
- 您的域逻辑存在于某个地方 否则,可能是在一个充满 类(静态)方法。或者你的GUI 代码。或者在多个地方,都有冲突的逻辑
- 这是一种反模式,所以其他 开发者会问你 理解对象的概念 面向对象的设计
如果您想到许多LOB应用程序,这些遗留系统通常不会使用与您相同的域模型。贫血域模型通过在服务类中使用业务逻辑来解决这个问题。您可以将所有这些接口代码放在您的模型中(在传统的OO意义上),但您通常会失去模块性。这与大多数反模式的优点相同:它允许您让很多人长时间忙碌。当管理者管理更多的人时,他们往往会得到更多的报酬,因此有一种强烈的不改进的动机。由于“贫血领域模型”是反模式的,为什么会有这么多系统来实现这一点 我认为有几个原因 1。系统的复杂性 在一个简单的系统中(这几乎是您在internet上找到的所有示例和示例代码),如果我想实现: 向订单添加产品 我把这个函数放在订单上
public void Order.AddOrderLine(Product product)
{
OrderLines.Add(new OrderLine(product));
}
很好,超级面向对象
现在让我们假设我需要确保我需要验证产品是否存在于库存中,如果不存在,则抛出异常
我真的不能再下订单了,因为我不希望我的订单依赖于库存,所以现在它需要继续服务
public void OrderService.AddOrderLine(Order order, Product product)
{
if (!InventoryService.Has(product)
throw new AddProductException
order.AddOrderLine(product);
}
我还可以将IInventoryService传递给Order.AddOrderLine,这是另一个选项,但这仍然使订单依赖于InventoryService
Order.AddOrderLine中仍然有一些功能,但通常它仅限于Order范围,而根据我的经验,有很多业务逻辑超出了Order范围
当系统不仅仅是基本的CRUD时,您将以OrderService中的大部分逻辑和很少的顺序结束
2。开发者对OOP的看法
互联网上有很多关于哪些逻辑应该在实体上进行的激烈讨论
差不多
命令,保存
秩序是否应该知道如何拯救自己?假设我们有这样的存储库
现在可以添加订单行了吗?如果我试图用简单的英语来理解它,它也没有真正意义。用户将产品添加到订单中,我们也应该这样做User.AddOrderLineToOrder()?这似乎太过分了
OrderService.AddOrderLine()怎么样。现在有点道理了
我对OOP的理解是,对于封装,将函数放在类上,函数需要访问类的内部状态。如果我需要访问Order.OrderLines集合,我会将Order.AddOrderLine()放在Order上。这样类的内部状态就不会暴露
3。国际奥委会集装箱
使用IoC容器的系统通常是完全贫血的
这是因为您可以测试具有接口的服务/存储库,但无法(轻松地)测试域对象,除非您将接口放在所有这些对象上
由于“IoC”目前被誉为解决所有编程问题的解决方案,许多人盲目地遵循它,最终导致领域模型贫乏