清洁架构中应用层应返回Entity还是DTO?
清洁架构下应用层返回值的最优方案
在清洁架构的约束下,应用层应返回核心业务实体(Entity),而非DTO,具体分析如下:
两种方案的利弊对比
方案1:应用层返回Entity,基础设施层映射为DTO
- 符合清洁架构的核心依赖原则:内层(应用层)不依赖外层(基础设施),外层依赖内层。Entity是纯业务对象,承载核心业务规则,应用层只负责输出业务处理后的结果,无需关心外层的传输/展示需求。
- 规避耦合风险:Entity的变更仅影响业务逻辑本身,不会直接波及基础设施层——只要业务规则不变,即使Entity的属性调整,基础设施层只需修改映射逻辑即可,无需改动应用层代码。
- 你担心的「向控制器暴露Entity」问题,核心在于Entity的设计:必须保证Entity是无基础设施依赖的纯业务对象,比如不要在Entity中添加JPA注解、JSON序列化注解等与持久化/传输相关的代码。这样控制器拿到的只是业务数据载体,不会触及业务规则,也不存在过度暴露的问题。
方案2:应用层返回DTO
- 直接违反清洁架构的隔离原则:应用层会被迫耦合外层的传输需求(比如REST的DTO格式、SSE的通知格式),一旦外层需求变更(比如API响应字段调整),应用层就得同步修改,违背了「应用层独立于基础设施」的核心设计思想。
- 多基础设施场景下的矛盾:如果一个业务用例需要服务多种基础设施(比如创建帖子后同时返回REST响应和SSE通知),应用层无法同时返回多种DTO,要么返回通用DTO导致部分基础设施冗余接收数据,要么在应用层中添加多分支逻辑处理不同DTO,进一步加剧耦合。
多基础设施场景的实现方式
以「创建帖子后同时提供REST响应和SSE通知」为例:
- 应用层执行创建帖子的业务逻辑,返回
PostEntity(包含帖子标题、内容、创建时间、作者等核心业务数据)。 - 基础设施层的REST控制器接收
PostEntity,将其映射为PostApiResponseDTO(仅包含API需要的字段,比如标题、作者、创建时间),返回给客户端。 - 基础设施层的SSE通知组件同时接收
PostEntity,将其映射为PostNotificationDTO(仅包含通知需要的字段,比如标题、创建时间),推送给订阅用户。
整个过程中,应用层完全不关心REST或SSE的需求,只专注于业务逻辑的正确性,新增其他基础设施(比如WebSocket推送、消息队列投递)时,只需在对应的基础设施层添加映射逻辑即可,无需修改应用层代码。
内容的提问来源于stack exchange,提问作者pham vu
相关产品推荐
相关产品推荐

