Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DTOs: best practices

Tags:

dto

People also ask

Are DTOs good?

DTOs can be tailored to your needs and they are great when exposing only a set of attributes of your persistence entities. You won't need annotations such as @XmlTransient and @JsonIgnore to avoid the serialization of some attributes.

Are DTOs necessary?

DTO becomes a necessity and not an ANTI-PATTERN when you have all your domain objects load associated objects EAGERly. If you don't make DTOs, you will have unnecessary transferred objects from your business layer to your client/web layer. To limit overhead for this case, rather transfer DTOs.

Can DTOs have methods?

A data transfer object (DTO) is a collection of public fields. If there are any methods, they are constructors for quickly making the DTO. DTOs do NOT contain logic. DTOs are often used with a form of data mapper called a DTO assembler.


I've been reading a few posts here regarding DTO's and it seems to me that a lot of people equate them to what I would consider a ViewModel. A DTO is just that, Data Transfer Object - it's what gets passed down the wire. So I've got a website and services, only the services will have access to real domain/entity objects, and return DTO's. These may map 1:1, but consider that the DTO's may be populated from another service call, a database query, reading a config - whatever.

After that, the website then can take those DTO and either add them to a ViewModel, or convert into one. That ViewModel may contain many different types of DTO's. A simple example would be a task manager - the ViewModel contains both the task object you are editing, as well as a group of Dto.User objects that the task can be assigned to.

Keep in mind that the services returning DTO's maybe used by both a website, and maybe a tablet or phone application. These applications would have different views to take advantage of their displays and so the ViewModels would differ, but the DTO's would remain the same.

At any rate, I love these types of discussions, so anyone please let me know what you think.

Matt


I'm kind of using DTOs in a project. I tend to make the DTOs only to show the data I need for an specified view. I fetch all the data shown in the view in my data access class. For example, I may have an Order object which references a Client object:

public class Client{
    public int Id{get;set;}
    public string Name{get;set;}
}

public class Order{
    public int OrderID{get;set;}
    public Client client{get;set;}
    public double Total{get;set;}
    public IEnumerable<OrderLine> lines {get;set;}
}

Then in my OrderListDTO I may have something like:

public class OrderListDTO{
    public int OrderId{get;set;}
    public string ClientName{get;set;}
    ...
 }

Which are the fields I want to show in my view. I fetch all these fields in my Database access code so I don't have to bother with entity asociations in my view or controller code.


Best Way to develop DTOs

The way to start developing DTOs is to understand that their sole purpose is to transfer subset of data of your business entities to different clients(could be UI, or an external service). Given this understanding you could create seperate packages for each client...and write your DTO classes. For mapping you could write your own mapper defining interfaces to be passed to a factory creating DTO objects based on which data from the entity for which the DTO is being created would be extracted. You could also define annotations to be placed on your entity fields but personally given the number of annotations used I would prefer the interface way. The main thing to note about DTOs is that they are also classes and data among the DTOs should be reused, in other words while it may seem tempting to create DTOs for each use case try to reuse existing DTOs to minimize this.

Getting started

Regarding getting started as stated above the sole purpose of the DTO is to give the client the data it needs....so you keeping in mind you could just set data into the dto using setters...or define a factory which creates a DTO from an Entity based on an interface.....

Regarding your third question, do as is required by your client :)


I come to project with spring-jdbc and there are used DAO layer. Some times existing entities doesn't cover all possible data from DB. So I start using DTO.

By applying '70 structure programming rule I put all DTOs into separate package:

package com.evil.dao;     // DAO interfaces for IOC.
package com.evil.dao.impl; // DAO implementation classes.
package com.evil.dao.dto; // DTOs

Now I rethink and decide to put all DTO as inner classes on DAO interfaces for result-sets which have no reuse. So DAO interface look like:

interface StatisticDao {
    class StatisticDto {
        int count;
        double amount;
        String type;

        public static void extract(ResultSet rs, StatisticDto dto) { ... }
    }

    List<StatisticDto> getStatistic(Criteria criteria);
}


class StatisticDaoImpl implements StatisticDao {
    List<StatisticDto> getStatistic(Criteria criteria) {
        ...
        RowCallbackHandler callback = new RowCallbackHandler() {
            @Override
            public void processRow(ResultSet rs) throws SQLException {
                StatisticDao.StatisticDto.extract(rs, dto);
                // make action on dto
            }
        }
        namedTemplate.query(query, queryParams, callback);
    }
}

I think that holding related data together (custom DTO with DAO interface) make code better for PageUp/PageDown.


Question 1: If the DTO's you need to transfer are just a simple subset of your domain object, you can use a modelmapper to avoid filling your codebase with logic-less mapping. But if you need to apply some logic/conversion to your mapping then do it yourself.

Question 2: You can and probably should create a DTO for each domain object you have on your main DTO. A DTO can have multiple DTO's inside of it, one for each domain object you need to map. And to map those you could do it yourself or even use some modelmapper.

Question 3: Don't expose all your domain if your view does not require it to. Also you don't need to create a DTO for each view, try to create DTO's that expose what need to be exposed and may be reused to avoid having multiples DTO's that share a lot of information. But it mainly depend's on your application needs.

If you need clarification, just ask.