应该使用哪个层从域对象转换为 DTO

Posted

技术标签:

【中文标题】应该使用哪个层从域对象转换为 DTO【英文标题】:Which layer should be used for conversion to DTO from Domain Object 【发布时间】:2018-05-29 02:36:32 【问题描述】:

我们正在使用 Spring Boot 创建 rest api。我们的项目中有三层(Repository、Service 和 Controller)。

假设我的控制器中有返回 UserDTO 对象的 GetUser api。

@GetMapping
public UserDTO getUser() 
   return userService.getUser();    

userService.getUser() 是返回UserDTO 对象还是返回User 对象并在控制器中转换为UserDTO 对象?哪个更好?

总之,域对象到DTO对象的转换,应该在服务层还是控制器层完成?

【问题讨论】:

服务层转换DTO的最佳实践,不要在控制器中放置任何逻辑。 自上而下。控制器应该知道服务,服务应该知道存储库。服务层不应该知道控制器、端点 dto 的。 【参考方案1】:

我认为将域对象转换为 DTO 对象没有“更好的方法”,这是一个品味问题。在我的项目中,我将域对象转换为服务层中的 DTO,作为我的“业务逻辑”的一部分。因此,您只能将域对象的可访问性降低到您的服务层。此外,我想减少控制器内部的“逻辑”,因为它们是应用程序层的一部分。

PS:如果您正在寻找将域对象转换为 DTO 的多种方法,请查看我最新的 *** 问题之一 (How to properly convert domain entities to DTOs while considering scalability & testability)

【讨论】:

【参考方案2】:

这取决于应用程序的需求和架构。想法是将dto转换保持在边缘。通常更喜欢在控制器级别进行 dto 和域转换。如果您想保持服务/业务逻辑独立于消费者,那么在 api 级别拥有总是更好。如果您的服务已被多个消费者使用,这一点会变得更加清楚。

【讨论】:

【参考方案3】:

根据我的经验,转换应该在控制器层上。这带来了一个优势,即能够以返回对象重用其他服务方法的来源。

这一点有时可能很重要,因为 DTO 对象通常会从源对象中减少字段。因此,我们需要更多的代码来获得这些缩减的字段,从而使我们的代码变得丑陋和重复。

我知道这会将逻辑转移到控制器层,但这是一个权衡。

【讨论】:

以上是关于应该使用哪个层从域对象转换为 DTO的主要内容,如果未能解决你的问题,请参考以下文章

我应该在哪里进行转换:域对象<-> DTO?

关于如何从域 (ORM) 对象映射到数据传输对象 (DTO) 的建议

我应该将 DTO 映射到客户端和服务器端的域实体/从域实体映射吗?

在 TypeScript 和 NestS 中将类转换为类/对象(实体到 DTO)

DO-DTO相互转换时的性能优化

具有业务对象、DTO 和实体/域对象的数据转换模式