13

Is it not bad practice to pass DTO object to service layer?

For now my service layer method look like this:

public save(MyEntity entity);

Mapping values from DTO to business entity (MyEntity) is done on presentation layer

But I want to change method signature to this:

public save(MyEntityDTO dto, String author);

And after it mapping from DTO to business entity will occur on service layer.

EDIT: I want it because I need opened hibernate session when mapping from DTO to business object, so all changes on entity will be automatically flushed.

WelcomeTo
  • 19,843
  • 53
  • 170
  • 286

3 Answers3

17

Is it not bad practice to pass DTO object to service layer?

Not only you could pass DTO objects to Service Layer, but you should pass DTO objects instead of Business Entities to Service Layer.

Your service should receive DTOs, map them to business entities and send them to the repository. It should also retrieve business entities from the repository, map them to DTOs and return the DTOs as reponses. So your business entities never get out from the business layer, only the DTOs do.

See the full answer to a similar question here.

Community
  • 1
  • 1
Lightman
  • 1,078
  • 11
  • 22
  • this is how I always thought about it. However in certain examples I've seen online (namely in the case of REST API servers) the service layer accepts DTOs but returns Models with I find rather perturbing (eg. Client add(ClientDTO client)). Any idea what could be the rationale here ? Cheers! – ChambreNoire Mar 28 '19 at 13:05
  • 1
    I know I'm a bit late to this, but what if I'm calling a service from another service? – Morgan Jun 06 '21 at 20:56
  • 3
    Wrong answer. Bottom layers should not know about layers on the top of your architecture. They should have their own api to provide the ability to communicate between each other inside layer. For communication between services you will use only service layer objects without any mapping to controller (client) level dtos. For communication between controller and service you have to do some basic validations and mapping to service layer objects and then call actual service methods. – user3435425 Oct 25 '21 at 13:13
  • 4
    This answer is so wrong, that it shows how SO can be misleading and it must not be considered to be only valid developer resource at all costs and in all cases. It is WRONG. Service layer should not have any idea about your DTOs, it is a business layer and it should only deal with business. In controller you should deal with DTOs. – Mejmo Sep 15 '22 at 10:46
  • 1
    However maybe it would be wise to define what is your DTO object? To be it is an object on presentation layer, thus REST controller. Just imagine you are changing something in REST layer... why should I change the service/business layer as well? Did business logic change somehow? No, probably just change in the mapper entity -> DTO and that mapping is done in controller. – Mejmo Sep 15 '22 at 10:50
  • @user3435425 The answer author has 34k reputation, and I see similar answer all around stackoverflow, for instance https://stackoverflow.com/a/67625653/4759176. – parsecer Jun 03 '23 at 17:42
5

It's debatable. (As evidenced in comments to the accepted answer) On the one hand, DTOs are belong to the layer of the application that deals with Data Transfer, which is your presentation layer apparently.

On the other hand, your domain object (business entity), which is properly dealt with in the service layer, probably has properties in it - like, say an Id, a LastUpdated or such that are not passed into the save method. So what do you pass in? Well, you pass in just the properties you need. And it just so happens, that the request MyEntityDTO for save() will happen to encapsulate all and only those properties!...

So you now have the unfortunate choice between:

  1. Passing in the business object from the presentation layer

    (Breaks the layering model too, and forces you to ignore properties like Id and LastUpdated, which are not in the "request")

  2. Breaking up the DTO into properties and passing them in:

    service.save(Dto.Property_One, Dto.Property_Two)

    which you then have to put back together in the save() method.

  3. Creating some new object to encapsulate Property_One, Property_Two etc

  4. Accepting that the DTO is for transferring between layers too

None of these is ideal imo, which is why I think #4 is okay. Probably the most correct is #2 - but again.. not ideal.

Sometimes naming my ease the pain: "MyEntityRequest" instead of "DTO"

Rhubarb
  • 34,705
  • 2
  • 49
  • 38
  • If the service layer returns entities i guess we have another problem regarding transactions. If the entity returned by the serivce has some lazy collection ,we should open the transaction in the Controller to acces the data right? Is ok to open the transaction from the controller? – Al Xx Jun 14 '22 at 13:05
0

It's ok, all standard 3 layer architectures do that. Dataaccess gets the data, business maps and manipulates it, presentation presents it. It is not ok - but, as said no crime - to pass dataaccess models to presentation - to this point u should pass business models. Btw. "DTO" can mean anything, business layer models can be DTO's, data access model can be DTO's. DTO's are usually POCO's in C#. Usually you have your dataaccess models, representing your database entities and your domain models wich pass the data around your application. The domain models are usually DTO's (or call it POCO). That means, in Microsoft speech, they are completly serializable, so you can pass them to any microsoft .net component. You can serialize them also to xml, json and so on ...