服务层应该接受来自控制器的DTO还是自定义请求对象? [英] Should service layer accept a DTO or a custom request object from the controller?

查看:1546
本文介绍了服务层应该接受来自控制器的DTO还是自定义请求对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

标题表明设计服务层时的最佳实践是什么?我确实知道服务层应始终返回DTO,以便将域(实体)对象保留在服务层内。但是,控制器对服务层的输入应该是什么?

As the title suggests what is the best practice when designing service layers?. I do understand service layer should always return a DTO so that domain (entity) objects are preserved within the service layer. But what should be the input for the service layer from the controllers?

我在下面提出了三个建议:

I put forward three of my own suggestions below:

方法1:
在这种方法中域对象(项)保留在服务层中。

Method 1: In this method the domain object (Item) is preserved within the service layer.

class Controller
{
    @Autowired
    private ItemService service;

    public ItemDTO createItem(IntemDTO dto)
    {
        // service layer returns a DTO object and accepts a DTO object
        return service.createItem(dto);
    }
}

方法2:
服务层接收自定义请求对象。我已经在AWS Java SDK和Google Cloud Java API中广泛地看到了这种模式。

Method 2: This is where the service layer receives a custom request object. I have seen this pattern extensively in AWS Java SDK and also Google Cloud Java API

class Controller
{
    @Autowired
    private ItemService service;

    public ItemDTO createItem(CreateItemRequest request)
    {
        // service layer returns a DTO object and accepts a custom request object
        return service.createItem(request);
    }
}

方法3:
服务层接受一个DTO并返回一个域对象。我不喜欢这种方法。但是它已在我的工作场所广泛使用。

Method 3: Service layer accepts a DTO and returns a domain object. I am not a fan of this method. But its been used extensively used at my workplace.

class Controller
{
    @Autowired
    private ItemService service;

    public ItemDTO createItem(CreateItemRequest request)
    {
        // service layer returns a DTO object and accepts a DTO object
        Item item = service.createItem(request);
        return ItemDTO.fromEntity(item);
    }
}

以上三种方法是否正确最好的方法,请给我最佳实践的建议。

If all 3 of the above methods are incorrect or not the best way to do it, please advise me on the best practice.

推荐答案

我来自 C#背景,但此处的概念保持不变。

I'm from C# background but the concept remains same here.

在这种情况下,我们必须将参数/状态从应用程序层传递到服务层,然后从服务层返回结果,我倾向于遵循关注点分离。服务层不需要知道应用程序层/控制器的 Request 参数。同样,从服务层返回的内容不应与从控制器返回的内容相结合。这些是不同的层,不同的要求,不同的关注点。我们应该避免紧密耦合。

In a situation like this, where we have to pass the parameters/state from application layer to service layer and, then return result from service layer, I would tend to follow separation-of-concerns. The service layer does not need to know about the Request parameter of you application layer/ controller. Similarly, what you return from service layer should not be coupled with what you return from your controller. These are different layers, different requirements, separate concerns. We should avoid tight coupling.

对于上面的示例,我将执行以下操作:

For the above example, I would do something like this:

class Controller
{
     @Autowired
     private ItemService service;

     public ItemResponse createItem(CreateItemRequest request)
     {
        var creatItemDto = GetDTo(request);
        var itemDto = service.createItem(createItemDto);
        return GetItemResponse(itemDto);
    }
}

由于您现在需要编写附加代码以转换不同的对象。但是,这为您提供了极大的灵活性,并使代码更易于维护。例如:与 CreateItemRequest 相比, CreateItemDto 可能具有其他/计算字段。在这种情况下,您无需在 Request 对象中公开那些字段。您只需将数据合同向客户公开,仅此而已。同样,您只将相关字段返回给客户端,而不是返回从服务层返回的相关字段。

This may feel like more work since now you need to write addional code to convert the different objects. However, this gives you a great flexiblity and makes the code much easier to maintain. For example: CreateItemDto may have additional/ computational fields as compared to CreateItemRequest. In such cases, you do not need to expose those fields in your Request object. You only expose your Data Contract to the client and nothing more. Similarly, you only return the relevant fields to the client as against what you return from service layer.

如果要避免在 Dto之间进行手动映射请求 对象 C#具有像 AutoMapper 。在Java世界中,我确定应该有一个等效项。可能是 ModelMapper 可以提供帮助。

If you want to avoid manual mapping between Dto and Request objects C# has libaries like AutoMapper. In java world, I'm sure there should be an equivalent. May be ModelMapper can help.

这篇关于服务层应该接受来自控制器的DTO还是自定义请求对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆