我一直在尝试构建一个基于 DDD 的应用程序,但我有一些问题。
我有一些层: - 表示层 - MVC - 应用层 - 域层 ...
首先,我想知道我是否可以在ApplicationLayer中执行此操作(获取家庭信息>获取默认消息信息>发送电子邮件>更新数据库):
public ApproveFamilyOutput ApproveFamily(ApproveFamilyInput input)
{
Family family = _familyRepository.GetFamily(input.Username);
family.Approve();
DefaultMessage defaultMessage = _defaultMessageRepository.GetDefaultMessage(MessageTypes.FamilyApproved);
_email.Send(family.GetEmail(), defaultMessage.Subject, defaultMessage.Message);
_familyRepository.Update(family);
bool isSaved = _familyRepository.Save();
return new ApproveFamilyOutput()
{
Errors = Helper.GetErrorIfNotSaved(isSaved)
};
}
我思考得好吗?应用程序层负责完成这项工作吗?
第二个问题是:我需要根据用户拥有的权限向表示层发送一些数据。这些权限在数据库中定义。例子: - 对象 Family 具有名称、姓氏、电话号码、电子邮件属性,用户可以显示/隐藏每个值。 我该如何处理这个问题?
我可以在应用层做类似的事情吗:
public GetFamilyOutput GetFamily(GetFamilyInput input)
{
Family family = _familyRepository.GetFamily(input.Username);
FamilyConfiguration familyConfiguration = _familyConfigurationRepository.GetConfigurations(family.Id);
//ProcessConfiguration will set to null the properties that I cannot show
family.ProcessConfiguration(familyConfiguration);
return new GetFamilyOutput
{
//Map Family Object to the GetFamilyOutput
};
}
注意:Family、DefaultMessage 和 FamilyConfiguration 是在域层内创建的域对象。
你的意见是什么?
谢谢:)
编辑: 注意:我喜欢下面的所有答案,并且我使用了其中的一些答案:)(我无法将所有答案标记为可接受)
最佳答案
您的应用程序服务在 #1 中所做的事情是完全有效的:它协调工作流程,几乎不需要业务逻辑知识。
但是,确实可以进行一些改进,例如:
我没有看到任何交易?仅应在成功提交交易后发送电子邮件。
发送电子邮件可以被视为家人批准的副作用。我想业务专家可能会说:“当一个家庭获得批准后,通过电子邮件通知感兴趣的各方”。因此,明智的做法是发布
FamilyApproved
域事件并在事件处理程序中移动电子邮件发送逻辑。请注意,您希望仅异步调用处理程序 当域事件被持久化到磁盘并且你想要持久化之后 同一事务中的事件作为聚合。
您可能可以将邮寄过程进一步抽象为
emailService.send(MessageTypes.FamilyApproved, family.getEmail())
之类的内容。应用程序服务不必了解默认消息。存储库通常专用于聚合根 (AR),如果
DefaultMessage
不是 AR,那么我会考虑以不同的方式命名DefaultMessageRepository
服务。
对于#2,虽然授权检查可以在域中完成,但更常见的做法是将域从此类任务中解放出来并在应用程序层中强制执行权限。您甚至可以拥有支持限界上下文 (BC) 的专用身份和访问权限。
"//ProcessConfiguration will set to null the properties that I cannot show"
该解决方案不会那么好(就像实现 IFamilyProperty
解决方案一样),因为您的域模型会受到技术授权问题的污染。如果您希望应用 DDD,那么模型应该尽可能忠实于通用语言 (UL),并且我怀疑您的领域专家会提及甚至理解 IFamilyProperty
。允许属性变为 null
也可能会违反一些不变量。
至少出于这些原因,我认为最好在域外实现授权检查。在那里,您可以自由使用您想要的任何实现并适合您的需求。例如,我认为从 DTO 中剥离值可能是合法的。
关于c# - DDD(领域驱动设计)应用层,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42882053/