Domain Services 领域服务
Domain Services implement domain logic which;
领域服务实现了领域逻辑,其中:
- Depends on services and repositories.
- 取决于服务和存储库。
- Needs to work with multiple aggregates, so the logic doesn't properly fit in any of the aggregates.
- 需要与多种聚合体一起工作,所以逻辑不适合在任一个聚合体中使用。
Domain Services work with Domain Objects. Their methods can get and return entities, value objects, primitive types... etc. However, they don't get/return DTOs. DTOs is a part of the Application Layer.
领域服务与领域对象一起工作。他们的方法可以获取和返回实体、值对象、原始类型......等等。然而,它们并不获取/返回DTOs。DTOs是应用层的一部分。
Example: Assigning an issue to a user 示例:将问题分配给用户
Remember how an issue assignment has been implemented in the Issue
entity:
记住在Issue
实体中是如何实现问题分配的。
Here, we will move this logic into a Domain Service.
在这里,我们将把这个逻辑移到域服务中。
First, changing the Issue
class:
首先,修改Issue
类:
- Removed the assign-related methods.
- 删除与分配有关的方法。
- Changed
AssignedUserId
property's setter fromprivate
tointernal
, to allow to set it from the Domain Service. - 将
AssignedUserId
属性的设置器从private
改为internal
,以允许从领域服务中设置它。
The next step is to create a domain service, named IssueManager
, that has AssignToAsync
to assign the given issue to the given user.
下一步是创建一个域名服务,名为IssueManager
,它有AssignToAsync
来将特定的问题分配给指定的用户。
IssueManager
can inject any service dependency and use to query open issue count on the user.
IssueManager
可以注入任何服务依赖并用于查询用户的未关闭问题数量。
We prefer and suggest to use the Manager
suffix for the Domain Services.
我们更喜欢并建议使用Manager后缀为领域服务进行命名。
The only problem of this design is that Issue.AssignedUserId
is now open to set out of the class. However, it is not public
. It is internal
and changing it is possible only inside the same Assembly, the IssueTracking.Domain
project for this example solution. We think this is reasonable;
这种设计的唯一问题是,Issue.AssignedUserId
现在是开放的,可以从类中设置。然而,它并不是 public
。它是internal
,只有在程序集内部IssueTracking.Domain
项目中才可以改变它,这个例子的解决方案就是如此。我们认为这很合理。
- Domain Layer developers are already aware of domain rules and they use the
IssueManager
. - 领域层的开发者已经意识到了领域规则,他们使用
IssueManager
。 - Application Layer developers are already forces to use the
IssueManager
since they don't directly set it. - 应用层开发者已强制使用
IssueManager
,因为他们不能直接设置它。
While there is a tradeoff between two approaches, we prefer to create Domain Services when the business logic requires to work with external services.
虽然在两种方法之间需要进行权衡,但当业务逻辑需要与外部服务合作时,我们更愿意创建领域服务。
If you don't have a good reason, we think there is no need to create interfaces (like IIssueManager
for the IssueManager
) for Domain Services.
如果你没有很好的理由,我们认为没有必要为领域服务创建接口(如为IssueManager
而创建的IIssueManager
)。