04.19.08
Abuses of DTO pattern in Java world
Basics
I have to go on a detour for bit (from elegant visitor to strategy pattern to DI … ) to something that most of the Java people are familiar with; Data Transfer Object, or most commonly known as a DTO. The reasons for this detour are related to something i have been playing with for a while (i’ll ellaborate in later posts). First of all keeping with my tradition of referring definitions, here’s what wikipedia has to say about a DTO :
Data Transfer Objects (DTO), formerly known as Value Objects or VO, are a design pattern used to transfer data between software application subsystems. DTOs are often used in conjunction with Data Access Objects to retrieve data from a database.
The difference between Data Transfer Objects and Business Objects or Data Access Objects is that DTOs do not have any behavior except for storage and retrieval of its own data (accessors and mutators).
Not much insight but still, it explains it in a nutshell. A data transfer object was born to reduce the number of calls through wire in an atypical multi tiered architecture. Usually at the server end there would be an assembler which takes care population of data etc. If anyone of you have ever worked with pre EJB 3.0 days, you would know why they used DTOs. Basically the idea was that an Entity bean would typically expose a method that would copy its entire state into an object that could be serialized. Now this object could be used
by any client in whatever manner needed. Typically code would be something like :
public class CustomerEntityBean implements javax.ejb.EntityBean{
public CustomerDTO getCustomerDTO( ){
// prepare a customer DTO with First Name.
return new CustomerDTO(this.getFirstName());
}
}
Nothing special going on in there, except that customer DTO constructor is called with getFirstName( ) method of the bean being called to allow for populating the customer DTO. In EJB 3 you are saved from doing all this (or so they say
) because your entities are detachable (in the sense that they are not ALWAYS managed by the container), so essentially they behave like DTOs when in “detached state. There are DTOs and then there are something called Value objects. Often both are used interchangeably. Although this is not true. For two DTOs the equality is based on object identity, whereas two value objects are equal in terms of their state. By this i mean for example two customers are equal if : their customer id AND OR customer Name is equal. For two value objects to be equal you can have all properties or subset of properties that uniquely identify each of them dictate the equality. (overriding equals)
A good example of Value object would be Date, for example something like 11/11/2011 is value object, as you can make out it is:
- Immutable
- If i have multiple copies of this date, all the copies would be equal
A value object should always override equals method. ( refer to : Value Object for more details ) . A DTO on the other hand is just used as a mutable object. Their equality is based on object identity rather than state identity as stated earlier. (CustomerVO vs CustomerDTO, VO = Value Object). Although this example is admittedly lousy because ideally i would want to keep my value objects very simple, like a Date for example (as opposed to a Customer).
Apart from all of this lets keep things even more clear, throughout the course of this blog I would be using the term Model for representation of “actual” data to be retrieved or persisted. In Hibernate terms the Model is a “Model” of what lies in database or what will lie in database (Talk about puns
).
Abuses
Throughout its long history DTO has been utilized for all kinds of purposes. In EJB days usually the mantra was to use them for making expensive three tiered calls easier, but times have changed since pre-historic EJB 1.x days. While it does make a lot of sense today why DTOs were needed originally, in today’s world people are simply abusing the term and pattern in their projects mostly. (I am speaking from experience off course, I don’t claim that everyone is doing this, before someone jumps a gun on me
). Some of the common blunders / mistakes / abusive usage is :
- Using DTOs to pass the data within the tier
- Using DTOs inter changeably with Value Objects
- Using DTOs to compose other DTOs and finally using one huge DTO for display (it sounds horrifying and dreamy, but i have seen this happen)
Lets tackle each one of those abuses one by one, as first one says, there is quite often the case for passing DTOs around simply because parameters are too much in one method call. While this might be a more object oriented approach, but it doesn’t justify the usage of a DTO for this. If there are two many parameters sitting independently, may be it is required that they all be composed into One Model class and then passed around. If the method that is being called exists in a separate tier (lets assume that tiers are not even in different VMs for now) only THEN should a DTO be considered for usage.
The second one is pretty self explanatory; Value objects being immutable are often used interchangeably with DTOs, while this is not a pain for much of the time, but still as a purist you’d want to see Value objects being used for what they are.
Finally, In couple of cases I have seen people do this : They compose DTOs with a DTO to transfer some data and retrieve it as a matter of convenience, Although it is not harmful in any sense, One should refrain from composing DTOs within a DTO (as opposed to a Model within a DTO) a DTO can have n number of models, it can have n number of lists, but if we are adding DTOs within a DTO, it tells me that we want to use Outer DTO as a shuttle to transfer Inner DTO because of some stringent need. I don’t think that plays out really well with a good design.
It is sometimes hard to point out why DTO can be such an anti pattern sometimes (I know a lot of folks believe that it is, but unfortunately i am not one of them.) I have been working on a project that uses a very interesting commons framework, that glorifies the DTO pattern to its most simple, most elegant and pure roots (Which is why I am proud to be part of this project
). I’ll elaborate on this later. Its a matter of personal taste as to how we write our code, however thinking what is intended use for what you are doing can go a long way in simplifying things for us.
Regards
Vyas, Anirudh