Domain driven design DDD中服务的对与错
如果我错了,请纠正我(并添加您认为正确的其他内容): 应用程序服务Domain driven design DDD中服务的对与错,domain-driven-design,Domain Driven Design,如果我错了,请纠正我(并添加您认为正确的其他内容): 应用程序服务 域的(面向公众的)api 负责装载和保存骨料 可以访问存储库和其他基础结构服务 不是通用语言的一部分 应该/可能是域顶部非常薄的一层(主要处理聚合的加载/保存,并将其余部分委托给域) 可以包含纯读取操作 域服务 域的“真实”api 包含域逻辑 仅适用于域对象(不适用于基础结构服务,如repos和电子邮件发件人服务) 通常包含编排不同聚合的代码 是通用语言的一部分 可以依赖于其他域服务 只包含修改操作 我相信您对域服务的理解
- 域的(面向公众的)api
- 负责装载和保存骨料
- 可以访问存储库和其他基础结构服务
- 不是通用语言的一部分
- 应该/可能是域顶部非常薄的一层(主要处理聚合的加载/保存,并将其余部分委托给域)
- 可以包含纯读取操作
- 域的“真实”api
- 包含域逻辑
- 仅适用于域对象(不适用于基础结构服务,如repos和电子邮件发件人服务)
- 通常包含编排不同聚合的代码
- 是通用语言的一部分
- 可以依赖于其他域服务
- 只包含修改操作
域服务的理解是不正确的
正确的起点将是Eric Evans的域驱动设计的第5章,他在其中定义了值对象
、实体
和域服务
据我所知,Evans的模式基于2003年左右使用Java编写领域模型的经验。在Java中,任何不是域不可知原语的东西都是“对象”;虽然可以实现静态函数,但没有任何特别好的方法来传递它们。相反,您需要将函数包装在对象内部
所以“域服务”是“无状态对象”;对象,因为这是传递它们时的一个约束,而无状态,因为底层数据的所有变化都是管理该数据的实体的责任
在本文中,我相信他使用了税收表的例子;发票需要能够正确计算税款,但税款代码不由发票实例拥有或管理;相反,该数据在别处管理,并且只读副本由模型中的所有发票共享
在Cargo shipping示例中,需要将货物指定给路线,但货物实体不管理自己的装运计划副本。相反,“RoutingService”支持对这些表的查询
罗伯特·马丁(Robert Martin)所说的实体协调是一个应用程序问题,而不是由域服务(如Evans所述)管理的问题。您对应用程序服务的定义是正确的。我将应用程序服务更多地视为命令处理程序。接收命令,加载聚合,调用聚合方法并保存机会。一个命令在单个事务中处理
域服务用于执行聚合需要但无法执行的操作。典型的例子可能是从外部世界检索额外的信息或进行一些计算。应用程序服务不一定知道聚合是否需要这个或那个信息,但它可以解决必要的依赖关系,并在调用聚合时将域服务传递给聚合
在我的实践中,域服务通常作为函数实现。请记住,域服务并非仅由聚合使用。复杂值对象可以完美地将域服务用于相同的目的
在我的书中,我使用了一个域服务来允许a来确保它不会被包含亵渎内容的文本实例化
public static DisplayName FromString(
string displayName,
CheckTextForProfanity hasProfanity)
{
if (displayName.IsEmpty())
throw new ArgumentNullException(nameof(FullName));
if (hasProfanity(displayName).GetAwaiter().GetResult())
throw new DomainExceptions.ProfanityFound(displayName);
return new DisplayName(displayName);
}
因此,域服务契约(在这种情况下为命名委托)在域中定义
namespace Marketplace.Domain.Shared
{
public delegate Task<bool> CheckTextForProfanity(string text);
}
namespace Marketplace.Domain.Shared
{
公共委托任务检查文本是否亵渎(字符串文本);
}
但它的实现是基础设施方面的问题,并且正在应用程序端进行连接
namespace Marketplace.Infrastructure
{
/// <summary>
/// PurgoMalum is a simple, free, RESTful web service for filtering and removing content of profanity, obscenity and other unwanted text.
/// Check http://www.purgomalum.com
/// </summary>
public class PurgomalumClient
{
private readonly HttpClient _httpClient;
public PurgomalumClient() : this(new HttpClient()) { }
public PurgomalumClient(HttpClient httpClient) => _httpClient = httpClient;
public async Task<bool> CheckForProfanity(string text)
{
var result = await _httpClient.GetAsync(
QueryHelpers.AddQueryString("https://www.purgomalum.com/service/containsprofanity", "text", text));
var value = await result.Content.ReadAsStringAsync();
return bool.Parse(value);
}
}
}
名称空间市场.基础架构
{
///
///PurgoMalum是一个简单、免费、RESTful的web服务,用于过滤和删除亵渎、淫秽和其他不需要的文本内容。
///检查http://www.purgomalum.com
///
公共类PurgomalumClient
{
私有只读HttpClientu HttpClient;
public PurgomalumClient():这个(新的HttpClient()){}
公共PurgomalumClient(HttpClient HttpClient)=>\u HttpClient=HttpClient;
公共异步任务检查亵渎(字符串文本)
{
var result=await\u httpClient.GetAsync(
QueryHelpers.AddQueryString(“https://www.purgomalum.com/service/containsprofanity“,”文本“,”文本“);
var value=wait result.Content.ReadAsStringAsync();
返回bool.Parse(值);
}
}
}