A colleague of mine is against using DTOs and rather feels we should just return Entity / Domain objects serialized for a REST api. He feels DTO is an anti pattern and sited this article Data Transfer Object is a Shame. Although the article sited has a different approach to solving the "DTO Problem" as my colleague is proposing. Personally I've always preferred to use DTO for three reasons.

  1. My API is not tied to my domain layer, so I have flexibility. Domain layer can change without impacting the API, and vise versa.
  2. When using ORMs like JPA/Hibernate I don't accidentally issue tons of queries to build the object graph to serialize, or have to put logic / annotations in my entity layer to control serialization, which is really a view concern not a domain concern.
  3. I can easily control what and how much information goes over the wire, IE send the handful of fields the client wants rather than 30 fields.

Point 2 is not a big deal if an ORM is not being used. I can still see can issue though if you had something like the following

class Order {

    private Long orderId;

    // additional fields go here

    private List<LineItem> lineItems;

class LineItem {

    private Long id;
    private BigDecimal amount;
    private int qty;

Lets say the client only wanted a list of orders and didn't care about the line items. If there wasn't a DTO involved you could populate the Order object and leave the lineItems as an empty List but that would be awkward and confusing to populate it in some cases, and not others. Or all the data could be loaded and transferred but that seems wasteful and potential performance impact.

Is there every an appropriate time to skip DTOs and just return the domain object? Or am I thinking wrong and DTO is not a pattern that should be used. Is there another approach?

  • You described benefits of using DTO. If those benefits are more valuable then caveat of having mapping functions then use it.
    – Fabio
    Apr 23, 2018 at 3:39
  • 2
    A common misconception around ORMs is thinking you can put such model from DB to the elsewhere without caring about "boundaries". The same way DTOs are meant to work on the edge of the application boundaries. Row mappers are meant to work as close to the DAL as possible. But no further. Persistence model, domain model and the representation model are (or could be) as different each other as day and night. Your colleague leaks on perspective (IMO). The ORMs data model was never conceived to reach the outer layers of the application unless there was no overhead on it.
    – Laiv
    Apr 23, 2018 at 6:38
  • 4
    I have read most of Yegor's articles and found pretty much all of those I have read quite stupid. His reasoning is limited by his subjective outlook on programming, rather than taking a bigger picture into consideration. Having DTOs is completely fine. The read layer shouldn't be loading your domain models anyway, because they can grow very heavy. Read side should be done using regular database queries (with joins, aggregations, selective properties,...).
    – Andy
    Apr 23, 2018 at 8:37
  • 2
    I do agree with Yegor that objects shouldn't expose properties on a regular basis, but that rule should not be applied to all objects. It should be applied to your domain, where you want your logic to be encapsulated and protected by the objects. As @Laiv has said, your applications boundaries, i.e. exposing an entity through an API, saving an entity to a database? Not, so, much. At a certain place in your app you will simply be required to expose some internals of an objects, e.g. to show it to a user. Even a true OO design becomes kind of procedural on the application boundary.
    – Andy
    Apr 23, 2018 at 8:45
  • Food for thought: the whole premise of CQRS (Command Query Responsibility Segregation) is based on the fact that data reads don't require the logic of a backing domain systems that issuing commands does - thus, why not keep them as lightweight as possible (e.g., DTOs)?
    – jleach
    Apr 23, 2018 at 17:51

2 Answers 2


First of all, merely citing someone's article on the Internet does not constitute sufficient justification for changing a practice. You have to weigh the pros and cons, and make up your own mind.

Note that the author of the article you cited hates ORM's. He follows a strict principle of encapsulating code with its data, which is sort of the foundational principle of object-orientation. He strongly dislikes ORM because it strips classes of their intelligence, and he's not wrong about that.

In his ORM hate article, he writes (more or less) that classes should be responsible for saving themselves to the database, a practice that violates a principle called "persistence ignorance." Persistence ignorance simply means that classes shouldn't know anything about their database overlord, and it's difficult to achieve this in any realistic manner with ORM's. He gets around the persistence ignorance problem by using interfaces, making his data ignorant of its underlying implementation.

To be fair, I write code that looks a lot like his under the hood, albeit a bit more streamlined than his (Java has a reputation for being very verbose, and I don't bother with the DTO interfaces). After wrestling with Entity Framework for awhile, I began using Dapper and writing SQL queries instead. I get better performance, less complexity and finer targeting of the database.

The class that implements your so-called "data transfer object" is a nice place to put this code; all you have to do is hand it an IdbConnection object, and the class has all it needs to read from and persist itself to the database.

I guess my question is, why does this have to be an either/or choice? If you need something from the database that requires a DTO, then use a DTO. If you want what you're calling a "domain object," then use that instead.


I think Data Domain Objects (DTOs) should be separated from Presentation Layer's Objects.

Regarding "Data Transfer Objects are Shame", I read such articles about anti-pattern and so on, I think people are just being lazy to say so, because they wanna write fewer codes and might not really understands why the design pattern is there in the first place.

Firstly for security reasons, which is you do not want to expose your inner data structure to the outside world and you shouldn't, and presentation layer object gives you the opportunity to limit the response data to what is REQUIRED ONLY.

Secondly, security aside, if you are in a world of microservices or distributed services, or your application is designed in modular, then segregation of responsibility and data objects are making more sense.

Imagine this: you have 3 libraries for restful,

  • A. user api (the service interface) - depends on B
  • B. user data objects
  • C. user provider (the real implementation) - depends on A & B

and 3 libraries for data storage layer (there should be a business layer in place, but I skip that for simplicity)

  • D. user data service (interface) - depends on E
  • E. user data objects (DTOs)
  • F. user data service provider (implementation) - depends on D & E

So imagine you are having another data service module which wanna use user data object only, it should depend on library E only; then if there another restful service that wants to borrow user data objects, they can just depend on B only. And so on, things should be transparent and as atomic as possible, and that promotes code reusability.

Even some might say my application is small, and I just want to get it out fast without all the boilerplates, well you can, but I'll not advise, that's the experience telling me not to do so. We have seen a lot of these examples in the past, RoR, NodeJS, ... you named it.

The thing is, they'll get you somewhere really fast, but only resolving simple things in a simple way, but complex things will be made unpractically complex.

So for me, I'll say rather follow the best practices from the beginning, and worry less later than to scrap the whole thing and redo, and trust me you'll gonna spend the same (if not more) amount of time to get it right later.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.