1

I would like to understand what's the benefits to create DTO objects when you already have POJO object (as Entity).

In my project I have both :

  • DTO classes are used to communicate between Web Service and the application
  • POJO entity classes (JPA) are used for communication between database and the application

If I look at a DTO object class (let's call it MyObjDTO) and the same class but POJO side (let's call it MyObjPOJO) there is no difference at all except MyObjPOJO as annotation due to the fact it's an @Entity.

So in fact, I got in my project 2 classes who look the same (same attributes, same methods) but for different puprose.

IMO, in this case the DTO class is useless and increase application complexity because all I do with DTO class I can do it with my POJO class and moreover, for a single type of object I have to maintain at least 2 classes (the DTO and POJO), for instance if I add an attribute I have to add this attribute in both classes.

I'm not an expert and I'm questionning about my thoughts; what do you think about it ?

Ashbay
  • 1,621
  • 12
  • 19
  • you're not the first one [to ask](https://softwareengineering.stackexchange.com/questions/171457/what-is-the-point-of-using-dto-data-transfer-objects). Looks like another software ideology playground. I personally used DTOs once because the shop always used them but in this case also had different structure than the Entities. – Nikolai Dmitriev Nov 16 '20 at 07:46
  • Google diff b/w POJO and DTO – vels4j Nov 16 '20 at 07:57

4 Answers4

3

This answer is a replica of what can be found on stack exchange. IMHO the OP should be closed for being posted in the wrong forum. It's currently also attracting opinionated answers, though not necessarily so, and isn't tied to java in any particular way.

DTO is a pattern and it is implementation (POJO/POCO) independent. DTO says, since each call to any remote interface is expensive, response to each call should bring as much data as possible. So, if multiple requests are required to bring data for a particular task, data to be brought can be combined in a DTO so that only one request can bring all the required data. Catalog of Patterns of Enterprise Application Architecture has more details.

DTO's are a fundamental concept, not outdated.

What is somewhat outdated is the notion of having DTOs that contain no logic at all, are used only for transmitting data and "mapped" from domain objects before transmission to the client, and there mapped to view models before passing them to the display layer. In simple applications, the domain objects can often be directly reused as DTOs and passed through directly to the display layer, so that there is only one unified data model. For more complex applications you don't want to expose the entire domain model to the client, so a mapping from domain models to DTOs is necessary. Having a separate view model that duplicates the data from the DTOs almost never makes sense.

However, the reason why this notion is outdated rather than just plain wrong is that some (mainly older) frameworks/technologies require it, as their domain and view models are not POJOS and instead tied directly to the framework.

Most notably, Entity Beans in J2EE prior to the EJB 3 standard were not POJOs and instead were proxy objects constructed by the app server - it was simply not possible to send them to the client, so you had no choice about haing a separate DTO layer - it was mandatory.

Although DTO is not an outdated pattern, it is often applied needlessly, which might make it appear outdated.

From Java guru Adam Bien:

The most misused pattern in the Java Enterprise community is the DTO. DTO was clearly defined as a solution for a distribution problem. DTO was meant to be a coarse-grained data container which efficiently transports data between processes (tiers). ~ Adam Bien

From Martin Fowler:

DTOs are called Data Transfer Objects because their whole purpose is to shift data in expensive remote calls. They are part of implementing a coarse grained interface which a remote interface needs for performance. Not just do you not need them in a local context, they are actually harmful both because a coarse-grained API is more difficult to use and because you have to do all the work moving data from your domain or data source layer into the DTOs. ~ Martin Fowler

Here is a Java EE specific example of a common but incorrect use of the DTO pattern. If you're unfamiliar with Java EE, you just need to know the MVC pattern: a "JSF ManagedBean" is a class used by the View, and a "JPA Entity" is the Model in the MVC pattern.

So, for example, say you have a JSF ManagedBean. A common question is whether the bean should hold a reference to a JPA Entity directly, or should it maintain a reference to some intermediary object which is later converted to an Entity. I have heard this intermediary object referred to as a DTO, but if your ManagedBeans and Entities are operating within the same JVM, then there is little benefit to using the DTO pattern.

Futhermore, consider Bean Validation annotations (again, if you're unfamiliar with Java EE, know that Bean Validation is an API for validating data). Your JPA Entities are likely annotated with @NotNull and @Size validations. If you're using a DTO, you'll want to repeat these validations in your DTO so that clients using your remote interface don't need to send a message to find out they've failed basic validation. Imagine all that extra work of copying Bean Validation annotations between your DTO and Entity, but if your View and Entities are operating within the same JVM, there is no need to take on this extra work: just use the Entities.

The Catalog of Patterns of Enterprise Application Architecture provides a concise explanation of DTOs, and here are more references I found illuminating:

Nikolai Dmitriev
  • 2,825
  • 1
  • 13
  • 23
1

Most of this comes down to Clean Architecture and a focus on separation of concerns

My biggest use-case for the entities is so i don't litter the DTO's with runtime variables or methods that i've added in for convenience (such as display names / values or post-calculated values)

If its a very simple entity then there isn't so much of a big deal about it, but if you're being extremely strict with Clean then there becomes a lot of redundant models (DTO, DBO, Entity)

Its really a preference in how much you want to dedicate to strict Clean architecture

https://medium.com/android-dev-hacks/detailed-guide-on-android-clean-architecture-9eab262a9011

Brandon
  • 538
  • 6
  • 16
  • Thank you for you answer dear but it looks like clean architecture VS simple code. I want to think it's deeper. In my case I think DTO was implemented without thinking about it; developer think "DTO is to transfer object, then I'm making DTO" instead of thinking he could use the POJO class in place of DTO (for my case at least) – Ashbay Nov 16 '20 at 08:07
  • No, it doesn't. The link provided says nothing about DTOs. You're notion of DTO doesn't match their stated purpose, once you care to take notice of that. Not everything on the planet is done for the purpose of cleanness, at least for some people, uncle Bob Martin among them. Btw we're in the wrong forum and the question should be closed. – Nikolai Dmitriev Nov 16 '20 at 08:39
0

There is an advantage, even if very small, to having a separation of layers in your architecture, and having objects "morph" as they travel through the layers. this decoupling allows you to replace any layer in your software with minimal change, just update the mapping of fields between 2 objects and your all set.

If the 2 objects have the same members...well, then that's what Apache Commons BeanUtils.copyProperties() is for ;)

Tom Elias
  • 361
  • 3
  • 9
0

Other people have already informed you of the benefits of DTO, here I will talk about how to solve the trouble of maintaining one more DTO version object. I deveploy a library beanKnife to automatically generate a dto. It will create a new class base the original pojo. You can filter the inherited properties, modify existing properties or add new properties. All you need is just writing a configuration class, and the library will do the left things for you. The configuration support inheritance feature, so you can extract the common part to simpify the configuration even more. Here is the example

@Entity
class Pojo1 {
   private int a;
   @OneToMany(mappedBy="b")
   private List<Pojo2> b;
}

@Entity
class Pojo2 {
   private String a;
   @ManyToOne()
   private Pojo1 b;
}

// Include all properties. By default, nothing is included.
// To change this behaviour, here use a base configuration and all other final configuration will inherit it.
@PropertiesIncludePattern(".*")
// By default, the generated class name is the original class name append with "View",
// This annotation change the behaviour. Now class Pojo1 will generate the class Pojo1Dto
@ViewGenNameMapper("${name}Dto")
class BaseConfiguration {
}

// generate Pojo1Dto, which has a pojo2 info list b instead of pojo2 list
@ViewOf(value = Pojo1.class)
class Pojo1DtoConfiguration extends BaseConfiguration {
    private List<Pojo2Info> b;
}

// generate Pojo1Info, which exclude b
@ViewOf(value = Pojo1.class, genName="Pojo1Info", excludes = "b")
class Pojo1InfoConfiguration extends BaseConfiguration {}

// generate Pojo2Dto, which has a pojo1 info b instead of pojo1
@ViewOf(value = Pojo2.class)
class Pojo2DtoConfiguration extends BaseConfiguration {
    private Pojo1Info b;
}

// generate Pojo2Info, which exclude b
@ViewOf(value = Pojo2.class, genName="Pojo2Info", excludes = "b")
class Pojo2InfoConfiguration extends BaseConfiguration {}

will generate

class Pojo1Dto {
   private int a;
   private List<Pojo2Info> b;
}

class Pojo1Info {
   private int a;
}

class Pojo2Dto {
   private String a;
   private Pojo1Info b;
}

class Pojo2Info {
   private String a;
}

Then use it like this

Pojo1 pojo1 = ...
Pojo1Dto pojo1Dto = Pojo1Dto.read(pojo1);
Pojo2 pojo2 = ...
Pojo2Dto pojo2Dto = Pojo2Dto.read(pojo2);
vipcxj
  • 402
  • 2
  • 8