Should the Repository Layer Return Data-Transfer-Objects (Dto)

Should the repository layer return data-transfer-objects (DTO)?

Short answer: No.

Long answer: repository is responsible for turning persisted data back to entities (models) and vice versa.

Model is a business Model representing a business entity. DTO on the other hand - while looks like Model - is concerned with transfer of the object between various environment and in essence is a transient object. Usually mappers are responsible for turning model into DTO.

Should Data Transfer Objects (DTOs) be used to bind UI too?

The DTO should be converted to a local model class. This does remove the coupling of your endpoints and your UI and allows a more flexible architecture.

Translating a DTO can be done in something like a Repository, which in turn uses your datasource that returns the DTO.

Since the question looks to be targeted at Android (Android-mvvm), you can have a look at this guide here as well https://developer.android.com/topic/architecture

Should I convert an entity to a DTO inside a Repository object and return it to the service layer?

It's more clear now after your comment. Let's try again:

First, some clarifications:
Your RestaurantOwnerRepository implements the repository pattern. Your @Entity annotated objects are hibernate entities and also DAO proxies. Your RestaurantOwnerService is a GWT-Service which can only return a DTO shared with the client and server.

So in a very simple server-side setup, you have a DB-Backend, access to the data via hibernate as a persistence layer, and a service layer as rest-service. In such a setup your hibernate entities are shared among the whole server side code. Your service layer is converting the entities to json format, for example. Deal?

Your "advanced" setup

  • Persistence layer

    • with Hibernate (delivering @Entity-Annotated objects)
    • maybe other stuff, too
  • Repository Layer (unclear for you what to return)
  • Service Layer (GWT Servlets, delivering DTOs which are shared with the client side)

Definition of Repository-Layer: In my opinion, it's an abstraction for different data/persistence layers. It doesn't provide business logic, which is more the purpose of a further business layer. The business layer compiles the outputs of the upper layer together, makes computations and returns the results. But looking according to your comment, this may also be the case in your repository layer. But it's ok for our clarification.

Your question: Is it okay to return DTO objects from the Repository Layer?

Answer: No, it is not really okay to return a DTO from the "repository" layer.

Why: 1. Your DTO is a domain entity transferred into a format which can be sent to the client side. It has limitations so that some server side libraries cannot be used in them. 2. Consider the case that you also want to provide other service layers. A REST-Interface maybe, another GUI-Framework maybe. They all have their own limitations for transferring the domain entities. Do you really want to duplicate the repository layer for each service layer? 3. Consider the case where you want to extend your repository/business layer so that it will use the output of your RestaurantOwnerRepository. Do you really want to work on DTOs there?

These are why the creation of a DTO is the purpose of a service layer. So the DTO is shared among the client side, and your service layer. In the same sense, you need objects, shared among the service layer and your repository layer. I call these domain entities. These are returned from the repository layer and used by the service layer. Again the same between the repository layer and persistence layer. The persistence layer for example returns the Hibernate entities which are used on the repository layer.

In most cases, it is ok to propagate your objects from multiple layers downwards. So you can return your hibernate entites from the repository layer to the service layer. Newer versions of GWT even allow to use JPA-entities on the client side with a special setup. So your service layer can further return your persistence entities.

Should services always return DTOs, or can they also return domain models?

it doesn't feel right when domain model leaves business layer (service layer)

Makes you feel like you are pulling the guts out right? According to Martin Fowler: the Service Layer defines the application's boundery, it encapsulates the domain. In other words it protects the domain.

Sometimes service needs to return data object that wasn't defined in the domain

Can you provide an example of this data object?

If we should strictly stick to DTOs, should they be defined in service layer?

Yes, because the response is part of your service layer. If it is defined "somewhere else" then the service layer needs to reference that "somewhere else", adding a new layer to your lasagna.

is it ok to return domain models all the way to controllers, or should we always use DTOs for communication with service layer?

A DTO is a response/request object, it makes sense if you use it for communication. If you use domain models in your presentation layer (MVC-Controllers/View, WebForms, ConsoleApp), then the presentation layer is tightly coupled to your domain, any changes in the domain requires you to change your controllers.

it seems it wouldn't make much sense to create DTO that is the same as domain model)

This is one of the disadvantage of DTO to new eyes. Right now, you are thinking duplication of code, but as your project expands then it would make much more sense, specially in a team environment where different teams are assigned to different layers.

DTO might add additional complexity to your application, but so are your layers. DTO is an expensive feature of your system, they don't come free.

Why use a DTO

This article provides both advantage and disadvantage of using a DTO, http://guntherpopp.blogspot.com/2010/09/to-dto-or-not-to-dto.html

Summary as follows:

When to Use

  • For large projects.
  • Project lifetime is 10 years and above.
  • Strategic, mission critical application.
  • Large teams (more than 5)
  • Developers are distributed geographically.
  • The domain and presentation are different.
  • Reduce overhead data exchanges (the original purpose of DTO)

When not to Use

  • Small to mid size project (5 members max)
  • Project lifetime is 2 years or so.
  • No separate team for GUI, backend, etc.

Arguments Against DTO

  • Duplication of code.
  • Cost of development time, debugging. (use DTO generation tools http://entitiestodtos.codeplex.com/)
  • You must synchronize both models all the time. (personally, I like this because it helps know the ripple effect of the change)
  • Cost of developement: Additional mapping is necessary. (use auto mappers like https://github.com/AutoMapper/AutoMapper)
  • Why are data transfer objects (DTOs) an anti-pattern?

Arguments With DTO

  • Without DTO, the presentation and the domain is tightly coupled. (This is ok for small projects.)
  • Interface/API stability
  • May provide optimization for the presentation layer by returning a DTO containing only those attributes that are absolutely required. Using linq-projection, you don't have to pull an entire entity.
  • To reduce development cost, use code-generating tools

How to use DTOs in the Controller, Service and Repository pattern

In today programming with Spring MVC and interactive UIs, there are really 4 layers to a web application:

  • UI Layer (Web Browser, JavaScript)

  • MVC Controller, i.e. Spring components annotated with @Controller

  • Service Layer, i.e. Spring components annotated with @Service

  • Data Access Layer, i.e. Spring components annotated with @Repository

Every time one of these layers interact with the underlying layer, they need to send/receive data, which generally are POJOs, to transfer the data between layers. These POJOs are DTOs, aka Data Transfer Objects.

Only DTOs should be used between layers, and they are not necessarily the same, e.g. the Service Layer may apply business logic to DTOs received from the Data Access Layer, so the DTOs of the Service Layer API is different from the Data Access Layer API. Similarly, the Controller may rearrange the data to prepare it for presentation (grouping, summaries, ...), so the data sent to the web browser is different from the data received from the Service Layer.

With full abstraction, the Data Access Layer's API should not reflect the technology of the Data Access, i.e. whether it is using JDBC, JPA, NoSQL, a web service, or some other means of storing/retrieving the data. This means that Entity classes shouldn't make it outside the Data Access Layer.

Most projects don't need that level of abstraction, so it is common for a DTO to be an Entity class, and to flow all the way from the Data Access Layer to the Controller, where it is used either by a View, or is send to the web browser, encoded as JSON.

It depends on the size and complexity of the project. The bigger the project, the more important it becomes to make each layer as abstract/standalone as possible.

Where Should Data Transfer Objects (DTOs) be declared in a layered application using DDD

As DTOs are used for transferring data from your application to e.g. client applications, they should be declared in the layer that handles the service calls to your application (the outermost layer). Whether you call it application layer or something else (at my company we call it 'service layer') is up to you.



Related Topics



Leave a reply



Submit