基于ABP落地领域驱动设计-05.实体创建和更新最佳实践

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

数据传输对象

DTO 是简单对象,用于在应用层和展示层传递状态数据。所以,应用服务方法返回 DTO。

DTO原则和最佳实践:

•DTO应该可序列化,因为大多数时候,需要网络传输。•应该有一个无参构造函数•不能包含任何业务逻辑•不能继承或引用实体

输入DTO输出DTO在本质上不同:一个用于给应用服务方法传递参数,一个作为应用服务方法的返回值,根据业务需要区别对待。

输入DTO最佳实践

不要在输入DTO中定义不使用的属性

只定义需要用的属性,否则,无用的属性只会让客户端在使用应用服务方法时感到困惑。当然可以定义可选属性,但是确保当客户端在使用时,不应该影响到用例的工作方式。

这条规则看起来没什么必要,谁会为方法仓储(输入DTO)添加不使用的属性呢?但是,它经常发生,尤其是当你想重用输入DTO对象时,会将多个DTO属性放在一个DTO对象中。

不要重用输入DTO

为每个用例(应用服务方法)定义特定的输入DTO,否则,在某些情况下不会添加一些不被使用的属性,这就违反了上面定义的规则。

有时候,在两个不同的用例中使用相同的DTO似乎很有吸引力,因为他们如此相似。甚至,当前是一模一样,可能后面随着业务变化才会有可能不同,此时也应该不要重用输入DTO。因为和用例间的耦合相比,代码复制可能是更好的做法。

重用DTO的另一种方式是:DTO继承,这同样会产生上面描述的问题.。

示例:用户应用服务

public interface IUserAppService:IApplicationService
{Task CreateAsync(UserDto input);Task UpdateAsync(UserDto input);Task ChangePasswordAsync(UserDto input);
}

IUserAppService 在所有方法(用例)使用 UserDto 作为输入DTO,UserDto定义如下:

public class UserDto
{public Guid Id{get;set;}public string UserName{get;set;}public string Email{get;set;}public string Password{get;set;}public DateTime CreationTime{get;set;}
}

Id 在 Create 方法中不被使用,因为 Id 由服务器生成。•Password 在 Update 方法中不使用,因为有修改密码的单独方法。•CreationTime 未被使用,且不应该由客户端发送给服务端,应该在服务端设置创建时间。

正确的实现,如下:

public interface IUserAppService:IApplicationService
{Task CreateAsync(UserCreationDto input);Task UpdateAsync(UserUpdateDto input);Task ChangePasswordAsync(UserChangePasswordDto input);
}

然后定义对应的DTO类:

public class UserCreationDto
{public string UserName {get;set;}public string Email{get;set;}public string Password{get;set;}
}public class UserUpdateDto
{public Guid Id{get;set;}public string UserName{get;set;}public string Email{get;set;}
}public class UserChangePasswordDto
{public Guid Id{get;set;}public string Password{get;set;}
}

尽管需要编写更多的代码,但是这是一种更易维护的方法。

特殊情况:举个例子,如果你有一个报表页,页面中有多个过滤条件,对应多个应用服务方法(显示报表、导出Excel、导出CSV),此时应该使用相同的输入DTO参数,返回不同的结果。因为当页面过滤条件改变时,修改一个DTO而对整个页面对应的应用服务方法参数生效。

输入DTO中验证逻辑

•仅在DTO内部执行简单验证,使用数据注解特性或实现 IValidatableObject 接口•不要执行领域验证,举个例子,不要在DTO中检测用户名是否唯一的验证。

示例:使用数据注解特性

using System.ComponentModel.DataAnnotations;namespace IssueTracking.Users
{public class UserCreationDto{[Required][StringLength(UserConsts.MaxUserNameLength)]public string UserName {get;set;}[Required][EmailAddress][StringLength(UserConsts.MaxEmailLength)]public string Email{get;set;}[Required][StringLength(UserConsts.MaxEmailLength,MinimumLength=UserConsts.MinPasswordLength)]public string Password{get;set;}}
}

ABP框架自动验证输入DTO,验证失败则抛出AbpValidationException异常,返回 400 HTTP 状态码。

某些开发者认为将验证规则和DTO类分离可能会更好。我们认为声明式(数据注解)是实用的,不会导致任何设计问题。当然,ABP支持 FluentValidation集成。

输出DTO最佳实践

•保持输出DTO数量最小,尽可能重用,但是不能将输入DTO作为输出DTO使用。•输出DTO可以包含比用例需要的更多属性•Create 和 Update 方法中返回DTO

以上建议的主要原因是:

•使客户端代码易于开发和扩展

•在客户端端处理不同但相似的DTO容易混淆•输入DTO中的更多属性可能未来会在UI/客户端中被使用,返回实体的所有属性(已经考虑过安全性和特殊情况)使客户端代码易于改进,而不需要修改后端代码。•如果是通过API暴露给第三方客户端,避免不同需求返回不同DTO

•使服务端代码易于开发和扩展

•更少的类,易于理解和维护•可以重用实体到DTO(AutoMapper)的对象映射代码•不同方法返回相同类型,使添加新方法变得简单明了。

示例:从不同方法返回不同DTO

public interface IUserAppService:IApplicationService
{UserDto Get(Guid id);List<UserNameAndEmailDto> GetUserNameAndEmail(Guid id);List<string> GetRoles(Guid id);List<UserListDto> GetList();UserCreateResultDto Create(UserCreationDto input);UserUpdateResultDto Update(UserUpdateDto input);
}

示例中没有使用异步方法,在实际开发时应该是异步方法。

上面的示例代码中,为每个方法返回不同DTO类型,这样会导致我们需要处理非常多的数据查询,映射实体到DTO的重复代码。

按照以下方式定义就简单多了:

public interface IUserAppService:IApplicationService
{UserDto Get(Guid id);List<UserDto> GetList();UserDto Create(UserCreationDto input);UserDto Update(UserUpdateDto input);
}

使用一个输出DTO:

public class UserDto
{public Guid Id{get;set;}public string UserName{get;set;}public string Email{get;set;}public DateTiem CreationTime{get;set;}public List<string> Roles{get;set;}
}

•移除 GetUserNameAndEmail 和 GetRoles 方法,因为 Get 方法已经返回足够需要的信息。•GetList 返回对象与 Get 相同•Create 和 Update 同样返回 UserDto

由此可见,返回相同DTO更加简洁。

为什么创建或更新之后要返回DTO? 想象一个用例场景,在页面中显示表格数据,当更新之后,获取返回对象,并对表格数据源进行更新,这样就不需要再次调用 GetList 方法,这是我们建议在 Create 和 Update 方法中返回 DTO 的原因。

讨论

以上关于输出DTO的建议,并不适用所有场景。

出于性能考虑,这些建议可以被忽略,特别是当存在大型数据集返回结果时,或者用户界面需要发起很多并发请求时,此时应该创建特定的输出DTO,只包含尽可能少的信息。

可维护性和性能,需要开发者权衡,上面的建议适用于性能损失可忽略不计的应用。

对象映射

自动对象映射是一个非常有用的工具,两个对象的属性相同或相似,将一个对象的值复制给另一个对象。

DTO和实体类通常具有相同或相似的属性,通常需要根据实体和业务需求来创建DTO对象。ABP框架对象映射基于 AutoMapper,相比手动赋值,效率更高。

•仅对实体到输出DTO使用自动对象映射。•输入DTO到实体不适用自动对象映射。

不使用输入DTO到实体自动映射的原因:

1.实体类通常有构造函数,接收参数并在创建时,进行参数验证。自动对象映射操作通常需要无参构造函数创建对象。2.实体属性设置器大多是私有的,应该使用方法设置属性值。3.通常需要仔细验证和处理用户/客户端输入,而不是盲目地映射到实体属性。

虽然其中一些问题可以通过映射配置来解决(例如,AutoMapper允许定义自定义映射规则),但它使你的业务逻辑隐含/隐藏,并与基础设施紧密耦合。我们认为业务代码应该是明确的、清晰的、容易理解的。

学习帮助

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

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

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

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

相关文章

mysql isam 食物_MySQL常用存储引擎之MyISAM

1. mysql 5.5之前版本默认存储引擎1.1 因为这个原因现在还有大量服务器在使用这myisam引擎的表1.2 myisam是mysql大部分系统表和临时表使用的存储引擎2. myisam存储引擎表由myd和myi组成2.1 myd存储数据信息2.2 myi存储索引信息2.3 frm记录表结构的&#xff0c;所有存储引擎都有…

每日一笑 | 史上最贴心的骗子

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

基于ABP落地领域驱动设计-06.正确区分领域逻辑和应用逻辑

系列文章基于ABP落地领域驱动设计-01.全景图基于ABP落地领域驱动设计-02.聚合和聚合根的最佳实践和原则基于ABP落地领域驱动设计-03.仓储和规约最佳实践和原则基于ABP落地领域驱动设计-04.领域服务和应用服务的最佳实践和原则基于ABP落地领域驱动设计-05.实体创建和更新最佳实践…

基于ABP落地领域驱动设计-03.仓储和规约最佳实践和原则

dotNET兄弟会 专注.Net开源技术及跨平台开发&#xff01;致力于构建完善的.Net开放技术文库&#xff01;为.Net爱好者提供学习交流家园&#xff01;公众号 围绕DDD和ABP Framework两个核心技术&#xff0c;后面还会陆续发布核心构件实现、综合案例实现系列文章&#xff0c;敬请…

我国最新十大黑科技发布,颠覆你的想象!

全世界只有3.14 % 的人关注了数据与算法之美人工智能的飞速发展&#xff0c;让“黑科技”一词深入人心。目不暇接的各种前沿技术&#xff0c;一再刷新人们的认知世界。所谓“黑科技”&#xff0c;不仅仅要够炫酷&#xff0c;更要有足够的“生活温度”&#xff0c;实现真正的人性…

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

围绕DDD和ABP Framework两个核心技术&#xff0c;后面还会陆续发布核心构件实现、综合案例实现系列文章&#xff0c;敬请关注&#xff01; ABP Framework 研习社&#xff08;QQ群&#xff1a;726299208&#xff09; ABP Framework 学习及实施DDD经验分享&#xff1b;示例源码、…

嗓子痛引发大抢救!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…