基于ABP落地领域驱动设计-04.领域服务和应用服务的最佳实践和原则

围绕DDDABP Framework两个核心技术,后面还会陆续发布核心构件实现综合案例实现系列文章,敬请关注! ABP Framework 研习社(QQ群:726299208) ABP Framework 学习及实施DDD经验分享;示例源码、电子书共享,欢迎加入!

领域服务

领域服务实现领域逻辑,它:

•依赖于服务仓储。•需要多个聚合,以实现单个聚合无法处理的逻辑。

领域服务与领域对象一起使用,其方法可以获取和返回实体值对象、原始类型等。然而,它并不获取/返回DTOs,DTOs属于应用层。

示例:将问题分配给用户

回想一下,我们之前是如何实现将问题分配给用户的

public class Issue:AggregateRoot<Guid>
{//..//问题关联的用户IDpublic Guid? AssignedUserId{get;private set;}//分配方法public async Task AssignToAsync(AppUser user,IUserIssueService userIssueService){var openIssueCount = await userIssueService.GetOpenIssueCountAsync(user.Id);if(openIssueCount >=3 ){throw new BusinessException("IssueTracking:CanNotOpenLockedIssue");}AssignedUserId=user.Id;}public void CleanAssignment(){AssignedUserId=null;}
}

现在,我们将逻辑迁移到领域服务中。首先,修改 Issue 类:

public class Issue:AggregateRoot<Guid>
{//...public Guid? AssignedUserId{get;internal set;}
}

•在聚合中移除 AssignToAsync 方法(因为需要在对应的领域服务中实现该方法。)•将 AssignedUserId 属性设置器从私有改为内部internal,以允许从领域服务中设置它。

接下来,创建一个领域服务 IssueManager 定义方法 AssignToAsync 将指定 Issue 分配给指定用户。

public class IssueManager:DomainService
{private readonly IRepository<Issue,Guid> _issueRepository;public IssueManager(IRepository<Issue,Guid> issueRepository){_issueRepository=issueRepository;}public async Task AssignToAsync(Issue issue,AppUser user){//获取关联用户处于打开状态问题的数量var openIssueCount=await _issueRepository.CountAsync(i=>i.AssingedUserId==user.Id && !i.IsClosed);//超过3个,则抛出异常if(openIssueCount>=3){throw new BusinessException("IssueTracking:ConcurrentOpenIssueLimit");}issue.AssignedUserId=user.Id;}
}

IssueManager在构造函数中注入需要的仓储,用于查询分配给用户处于打开状态的Issue。

建议使用Manager后缀命名来命名领域服务。

这种设计的唯一问题是:Issue.AssignedUserId现在是 public ,可以在任何外部类中设置。然而,它不应该是公共的,访问范围应该是程序集内部internal,只有在同一个程序集(IssueTracking.Domain)项目中才可以调用。

这个例子的解决方案就是如此,我们认为这很合理:

•领域层开发者在使用 IssueManager 时,已经熟知领域规则。•应用层开发者强制使用 IssueManager,因此无法直接修改实体。

以上我们展示了将问题分配给用户的两种实现方式,两种方式权衡之下,我们更加推荐当业务逻辑需要与外部服务协同工作时,创建领域服务

如果没有一个充分的理由,我们认为没有必要去为领域服务创建接口,比如:为 IssueManager 创建 IIssueManger 接口。

应用服务

应用服务是无状态服务,实现应用程序用例。一个应用服务通常使用领域对象实现用例,获取或返回数据传输对象DTOs,被展示层调用。

应用服务通用原则:

•实现特定用例的应用逻辑,不能在应用服务中实现领域逻辑(需要理清应用逻辑和领域逻辑二者的区别)。•应用服务方法不能返回实体,因为这样会打破领域层的封装性,始终只返回DTO。

示例:分配问题给用户

using System;
using System.Threading.Tasks;
using IssueTracking.Users;
using Microsoft.AspNetCore.Authorization;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;namespace IssueTracking.Issues
{public class IssueAppService :ApplicationService.IIssueAppService{private readonly IssueManager _issueManager;private readonly IRepository<Issue,Guid> _issueRepository;private readonly IRepository<AppUser,Guid> _userRepository;public IssueAppService(IssueManager issueManager,IRepository<Issue,Guid> issueRepository,IRepository<AppUser,Guid> userRepository){_issueManager=issueManager;_issueRepository=issueRepository;_userRepository=userRepository;}[Authorize]public async Task AssignAsync(IssueAssignDto input){var issue=await _issueRepository.GetAsync(input.IssueId);var user=await _userRepository.GetAsync(inpu.UserId);await _issueManager.AssignToAsync(issue,user);await _issueRepository.UpdateAsync(issue);//没有对issue做任何修改,为什么要更新?在IssueManager中进行了状态修改。}}
}

一个应用服务方法通常有三个步骤:

•从数据库获取关联的领域对象•使用领域对象(领域服务、实体等)执行业务逻辑•在数据库中更新实体(如果已修改)

当时使用EF Core时,最后的 Update 更新操作并不是必须的,应为有 状态变更跟踪。但是建议显式调用,适配其他数据库提供程序。

示例中 IssueAssignDto 是一个简单的 DTO 类:

using System;
namespace IssueTracking.Issues
{public class IssueAssignDto{public Guid IssueId{get;set;}public Guid UserId{get;set;}}
}

学习帮助

围绕DDDABP Framework两个核心技术,后面还会陆续发布核心构件实现综合案例实现系列文章,敬请关注!

ABP Framework 研习社(QQ群:726299208) 专注 ABP Framework 学习及DDD实施经验分享;示例源码、电子书共享,欢迎加入!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/301228.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

嗓子痛引发大抢救!33岁程序员的垂死经历,为所有人敲响警钟!

全世界只有3.14 % 的人关注了数据与算法之美最近广州天气多变&#xff0c;再加上不规律的饮食、作息&#xff0c;数据汪的扁桃体已经肿痛两三天了。在一大杯“凉茶”下肚后&#xff0c;最终我还是选择去医院做一次检查。万幸的是&#xff0c;检查结果出来后&#xff0c;医生说只…

.NET也内卷了,BAT大厂近日上演抢人大战!

这两年到处都流行“内卷”这个词&#xff0c;而IT互联网行业则是内卷重灾区。还不太明白什么是内卷&#xff1f;看看这个段子&#xff1a;关于内卷&#xff0c;网上有个比喻&#xff0c;说如果葵花宝典被公开了&#xff0c;就会变成一个灾难。因为如果只有一个人拥有的话&#…

EFDC水模型 初学者入门 及软件下载学习指导

EFDC模型有三个不同的版本&#xff0c;它们分别代表了计算机不同的操作菜单和功能。其中的两个版本功能齐全&#xff0c;包括了EFDC 所有的产品版本。另外一个是简化版&#xff0c;涵盖了水动力学&#xff08;包括盐度和温度的影响&#xff09;&#xff0c;毒物&#xff0c;沉积…

每日一笑 | 在地铁上被老奶奶让座是一种什么样的体验?

全世界只有3.14 % 的人关注了数据与算法之美&#xff08;图源网络&#xff0c;侵权删&#xff09;

java access dbq_Java-Access汇总

http://www.doczj.com/doc/3b7b55100b4e767f5acfce38.html/view/d1c01b43a8956bec0975e33e.html在网上看了一些资料&#xff0c;基本上都是一样的。怎么试也行不通。于是我怀疑为什么那些错误的技术文章如此大张旗鼓的到处都是。今天有人问我如果把主机托管出去&#xff0c;也就…

一个IT人的非典型职场十年 (5)

2019独角兽企业重金招聘Python工程师标准>>> 对于非资深IT人来讲&#xff0c;IT咨询(IT Consulting)显得是比较高帅富一些&#xff0c;各种衣着光鲜的咨询报告&#xff0c;各种西装革履的顾问。 这先随便说两句什么是IT咨询&#xff0c;IT顾问究竟是在做啥工作。 I…

基于ABP落地领域驱动设计-01.全景图

什么是领域驱动&#xff1f;领域驱动设计&#xff08;简称&#xff1a;DDD&#xff09;是一种针对复杂需求的软件开发方法。将软件实现与不断发展的模型联系起来&#xff0c;专注于核心领域逻辑&#xff0c;而不是基础设施细节。DDD适用于复杂领域和大规模应用&#xff0c;而不…

伦敦科学博物馆用百年智慧打造的一套探索书,拓展孩子的科学、数学和艺术思维...

▲数据汪特别推荐点击上图进入玩酷屋说到素质教育&#xff0c;我们应该比较熟悉。不过&#xff0c;这几年&#xff0c;比素质教育更火的一个概念是——STEAM教育。教育家们普遍认为&#xff1a;在科学、技术、工程、艺术、数学之间存在着一种相互支撑、相互补充、共同发展的关系…

java中事务特性_「java三分钟」事务的传播特性详解

关注我&#xff0c;每天三分钟&#xff0c;带你轻松掌握一个Java相关知识点。事务传播行为就是多个事务方法相互调用时&#xff0c;事务如何在这些方法间传播。换言之&#xff0c;一个带事务的方法调用了另一个带事务的方法&#xff0c;被调用的方法它怎么处理自己事务和调用方…

基于ABP落地领域驱动设计-02.聚合和聚合根的最佳实践和原则

前言上一篇 基于ABP落地领域驱动设计-01.全景图 概述了DDD理论和对应的解决方案、项目组成、项目引用关系&#xff0c;以及基于ABP落地DDD的通用原则。从这本篇开始&#xff0c;会更加深入地介绍在基于 ABP Framework 落地DDD过程中的最佳实践和原则。围绕DDD和ABP Framework两…

每日一笑 | 实名举报校长拿两份工资!

全世界只有3.14 % 的人关注了数据与算法之美&#xff08;图源网络&#xff0c;侵权删&#xff09;

159个故事串起三千年大历史!这套“儿童版史记”太无敌了!

▲数据汪特别推荐点击上图进入玩酷屋17世纪英国哲学家培根说“读史使人明智”&#xff0c;意思是真实、鲜活的历史&#xff0c;不仅能极大拓宽孩子眼界&#xff0c;更能让孩子以古人为鉴&#xff0c;树立远大的志向&#xff0c;对成长大有助益。在我们的学生时代&#xff0c;认…

再见,REST,你好,gRPC

gRPC是一个开源的远程过程调用框架&#xff0c;用于服务之间的高性能通信。服务之间的通信可以使用各种语言&#xff0c;通过可插拔的负载均衡、追踪、健康检查和身份验证&#xff0c;这让它被认为是一种非常高效的方法。在默认情况下&#xff0c;gRPC使用协议缓冲&#xff08;…

全校师生放6天春假;清华大学设立天文系;郭守敬望远镜光谱数突破千万;《自然》发表最新发现;百度败诉需道歉;这就是今天的大新闻...

今天是3月29日农历二月廿三今天星期五早上上班等了N趟车愣是没挤上去下面是今天的大新闻全校师生放6天“春假”&#xff08;中国青年网&#xff09;3月28日&#xff0c;四川西南航空职业学院发布了《关于“泛美春假”的放假通知》&#xff0c;要求在放假时间总量不变的情况下&a…

jenkins java反序列化_Jenkins “Java 反序列化”过程远程命令执行漏洞

###漏洞原理反序列化是指特定语言中将传递的对象序列化数据重新恢复为实例对象的过程&#xff0c;而在这个过程中会执行一系列的字节流解析和对象实例化操作用于恢复之前序列化时的对象。在原博文所提到的那些 Java 应用里都有特定的接口用于传递序列化对象数据&#xff0c;而在…

WPF DataGrid 在Header中显示行号

在Datagrid中显示行号&#xff0c;如果你绑定的datacontext中没有序号&#xff0c;又想要显示序号的时候&#xff0c;可以按照本文的方法显示喽~效果如下图&#xff1a;来看看代码吧~MainWindow.xaml<Window x:Class"wpfcore.MainWindow"xmlns"http://schema…

每日一笑 | 爱的魔力转圈圈~

全世界只有3.14 % 的人关注了数据与算法之美&#xff08;素材源网络&#xff0c;侵权删&#xff09;

怎样维护成功的开源项目

开源可不仅仅是将代码扔到网上就万事大吉了&#xff0c;将开源项目变成能让自己引以为豪的东西才算成功。那么&#xff0c;你需要注意哪些方面呢&#xff1f; 写好指导性文字 每一个开源项目有三样东西是少不了的&#xff1a;项目目标和方法的简要说明、如何参与和授权许可。最…

技术管理中的手段——奖励和惩罚

对于技术出身的同学来说&#xff0c;一旦晋升为管理岗&#xff0c;则意味着面临很多棘手的问题&#xff0c;例如&#xff1a;手下的人不听管教&#xff0c;无法按时完成任务等等。一般凭技术晋升的同学&#xff0c;自然是技术中的佼佼者&#xff0c;作为团队中的骨干&#xff0…

用科学实验玩“坏”二十四节气,中华传统还能这么学,科学、节气、民俗三重启蒙!...

▲数据汪特别推荐点击上图进入玩酷屋之前我们“迪比的冒险之旅”和“delightmom魔幻科学实验”做完团购活动之后&#xff0c;很多妈妈都跟小木说拿回去孩子特别喜欢&#xff0c;每个实验做了好几遍还不尽兴&#xff0c;经常追问小木有没有新的实验更新。看下图孩子玩的多么开心…