Design

Data transfer object

Data transfer object(DTO) or transfer object as you find it under the CoreJ2EE patterns it’s used to bundle data from multiple places into one object which we send to a consumer. Usually we find this at the business and data layers of our applications. Its purpose is to decouple these layers from the presentation. For example in the onion architecture

the infrastructure should know nothing about the domain entities, so that means at some point we are gonna transforms the domain entities into data transfer object using the assembler pattern. We are doing these transformations in classed that we call mappers. You can see them as functions

public class Mapper implements Function<DataSource, DTO> {

  @Override
  public DTO apply(DataSource dataSource) {
    //TODO: implement me
    return null;
  }
}

where DataTransferObject is a POJO with no logic (I’m using lombok in this example).

@Data
@Builder
public class DTO {

  private String variable;
  private Integer number;
}

When we perform the mapping we can leverage the builder pattern and the function will look like

public class Mapper implements Function<DataSource, DTO> {

  @Override
  public DTO apply(DataSource dataSource) {
    return DTO.builder()
            .number(dataSource.getNumber())
            .variable(dataSource.getSomeValue())
            .build();
  }
}

Of course in some situations we wanna perform some transformations here. Also we have only have data source here. Although this is the most common situation there ca be more than one. Now the problem that we have here is that we need to write a lot of boiler plate code and we don’t want this. We need to get more with less. See Essence vs Ceremony. There are also devs whom do not like the idea of compile time code generation. I’ve heard also opinions where encapsulation was broken

public class DTO {

  public String variable;
  public Integer number;
}

In this case the mapper looks like

public class Mapper implements Function<DataSource, DTO> {

  @Override
  public DTO apply(DataSource dataSource) {
    DTO dto = new DTO();
    dto.number = dataSource.getNumber();
    dto.variable = dataSource.getSomeValue();
    return dto;
  }
}

This is of course an exaggeration since we can leverage a constructor with two variables. The thing is a DTO has usually more than two and we don’t want constructors with more than four(debatable) parameters. The only advantage of this is that we eliminate the possibility to alter the behaviour with is theoretically possible using getters and setters.

Another variant which I must admit I use it is to leverage a mapping library like mapstruct. Like lombok its also using reflection to generate compile time code.

@Mapper
public interface MyMapper {

  @Mapping(source = "number", target = "number")
  @Mapping(source = "someValue", target = "variable")
  DTO toDto(DataSource source);
}

DTO it’s also seen used in the ORM context where data is being mapped into objects. At this level we have the Row Data Gateway pattern, which basically uses this pattern in order to keep the domain entities isolated.

And then we have this. The author says the the data must never escape the object. I personally think the situations is not black and white, but grey. If we go back to the onion architecture example, and we need to display the data into a web page. Wouldn’t that mean that we need to expose the object to the upper level breaking the rules which are saying that the outer circle is only aware on the next inner circle? We should use the dependency inversion principle and if we change the inner layer we should impact only the next outer layer. If we break this we might not be able to control the situation and we may arrive in a high coupling scenario which we don’t want. So obviously we want to transfer somehow the data without exposing implementation details.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.