问题描述
我们当前的 O/RM 工具并没有真正支持丰富的域模型,因此我们被迫在任何地方使用贫血 (DTO) 实体.这工作得很好,但我仍然在纠结将基本的基于对象的业务逻辑和计算字段放在哪里.
Our current O/RM tool does not really allow for rich domain models, so we are forced to utilize anemic (DTO) entities everywhere. This has worked fine, but I continue to struggle with where to put basic object-based business logic and calculated fields.
当前层:
- 介绍
- 服务
- 存储库
- 数据/实体
我们的存储库层有大部分基本的获取/验证/保存逻辑,尽管服务层做了很多更复杂的验证和验证.保存(因为保存操作还进行日志记录、权限检查等).问题是把这样的代码放在哪里:
Our repository layer has most of the basic fetch/validate/save logic, although the service layer does a lot of the more complex validation & saving (since save operations also do logging, checking of permissions, etc). The problem is where to put code like this:
Decimal CalculateTotal(LineItemEntity li)
{
return li.Quantity * li.Price;
}
或
Decimal CalculateOrderTotal(OrderEntity order)
{
Decimal orderTotal = 0;
foreach (LineItemEntity li in order.LineItems)
{
orderTotal += CalculateTotal(li);
}
return orderTotal;
}
有什么想法吗?
推荐答案
让我们回归基础:
服务有 3 种风格:域服务、应用服务和基础设施服务
Services come in 3 flavours: Domain Services, Application Services, and Infrastructure Services
- 域服务:封装不自然的业务逻辑适合域对象.就您而言,所有业务逻辑.
- 应用服务:由外部消费者用来与您的系统对话
- 基础设施服务:用于抽象技术问题(例如MSMQ、电子邮件提供商等)
- Domain Services : Encapsulates business logic that doesn't naturallyfit within a domain object. In your case, all of your business logic.
- Application Services : Used by external consumers to talk to your system
- Infrastructure Services : Used to abstract technical concerns (e.g.MSMQ, email provider, etc)
这是您的数据访问和一致性检查的地方.在纯 DDD 中,您的 Aggregate Roots 将负责检查一致性(在持久化任何对象之前).在您的情况下,您将使用来自域服务层的检查.
This is where your data-access and consistency checks go. In pure DDD, your Aggregate Roots would be responsible for checking consistency (before persisting any objects). In your case, you would use checks from your Domain Services layer.
建议的解决方案:拆分现有服务
Proposed solution: Split your existing services apart
使用新的域服务层来封装 DTO 的所有逻辑,以及一致性检查(也许使用规范?).
Use a new Domain Services layer to encapsulate all logic for your DTOs, and your consistency checks too (using Specifications, maybe?).
使用应用服务公开必要的获取方法(FetchOpenOrdersWithLines
),这些方法将请求转发到您的存储库(并使用泛型,正如杰里米所建议的那样).您也可以考虑使用查询规范来包装您的查询.
Use the Application Service to expose the necessary fetch methods (FetchOpenOrdersWithLines
), which forward the requests to your Repository (and use generics, as Jeremy suggested). You might also consider using Query Specifications to wrap your queries.
在您的存储库中,在您的域服务层中使用规范来检查对象一致性等,然后再持久化您的对象.
From your Repository, use Specifications in your Domain Services layer to check object consistency etc before persisting your objects.
您可以在 Evans 的书中找到支持信息:
You can find supporting info in Evans' book:
- 服务和隔离域层"(第 106 页)
- 规格"(第 224 页)
- 查询规范"(第 229 页)
- "Services and the Isolated Domain Layer" (pg 106)
- "Specifications" (pg 224)
- "Query Specifications" (pg 229)
这篇关于如果您被迫使用 Anemic 域模型,您将业务逻辑和计算字段放在哪里?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!