140

I've recently overheard people saying that data transfer objects (DTOs) are an anti-pattern.

Why? What are the alternatives?

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
ntownsend
  • 6,884
  • 9
  • 35
  • 34
  • 14
    Perhaps because business objects are themselves capable of transporting their own data thank you very much! – Zoidberg Sep 17 '09 at 19:52
  • 14
    "Anti-pattern" may well be my nominee for "phrase whose 15 minutes were up a long time ago." It's synonymous with "I don't care to bother justifying my thinking" by now, like "It's well-known that..." – Craig Stuntz Sep 17 '09 at 19:54
  • 6
    Zoidberg, sending objects with methods over the wire gave us CORBA, DCOM, and other experiences I try erase my memory of. The trouble is, sooner or later people want to *call* those methods. – Craig Stuntz Sep 17 '09 at 19:55
  • 12
    DTOs embody the DRY principle, which unfortunatly in J2EE stands for *do* repeat yourself. – joeforker Sep 17 '09 at 19:58
  • You may want to read this: [Data Transfer Object Is a Shame](https://www.yegor256.com/2016/07/06/data-transfer-object.html) – yegor256 Jan 30 '20 at 15:07

11 Answers11

149

Some projects have all data twice. Once as domain objects, and once as data transfer objects.

This duplication has a huge cost, so the architecture needs to get a huge benefit from this separation to be worth it.

Jim Ferrans
  • 29,162
  • 12
  • 52
  • 83
KLE
  • 22,211
  • 4
  • 51
  • 60
  • 6
    Please elaborate on the "huge cost". Also, say why the cost can't be eliminated by using code generation techniques to generate the DTO classes. – John Saunders Sep 17 '09 at 20:05
  • 76
    +1. Twice? Only if you're lucky :-) Projects that duplicate domain entities as DTO also tend to have almost-the-same-but-oh-so-subtly-different UI beans to complement them. That's 3. And if, god forbid, there's some sort of remoting (web services / xml-rpc / whatever) going on, you can easily get to 4 or 5. – ChssPly76 Sep 17 '09 at 20:20
  • 2
    Let's see the first cost is converting them from the domain object to the DataDto. Then you convert the DataDto to a WebDto (or a UiDto), for the second cost. Then later on down the road, you have to add a field. So you have to add the field to the domain and 2 Dtos, and the conversion routines. Since very often WebDtos are all strings, now you have to do some calculations on a number field. So now you have to change the WebDto, and it's conversion routine. There's another cost. So you have costs in development time, debugging time, and of course the overhead of the conversions. – Jim Barrows Sep 17 '09 at 22:48
  • 19
    I am currently working with a enterpricy 14 layer lasagna architecture (NOT KIDDING). I can assure you that the 11-or so layers that is mainly for data-transer does not come for free. – KarlP Sep 18 '09 at 07:15
  • 11
    Also, while I absolutely love code generators when working with stupid designs, they are a) a sure thing that you are doing it wrong to begin with. b) they do not come for free. – KarlP Sep 18 '09 at 07:17
  • @John By costs, I mean development time, and runtime object creation and copies. I agree, development time could be alleviated by code generation techniques, if well-mastered ... but they sometimes have problems on their own. – KLE Sep 18 '09 at 07:31
  • @Karlp thanks for you real-life input. Your situation seem incredible. Is there a place where you could give us more details (maybe something more readeable that some comments?). – KLE Sep 18 '09 at 07:33
  • 8
    Sorry, but this is just incorrect and the wrong answer got voted high and accepted. First of all you can use reflection to generate DTOs on the fly. Second you can use a "root definition" e.g. in a CASE system or in oAW and generate the BO and DTO(s). Third of all you can use an XSD and JAXB to generate DTOs and use the DTO as base for an BO, or you can generate both from the XSD ... anyway, if anyone would dare to transfer an EJB freshly fetched from the DB over wire to a client program ... in the environments I work, his head would be on a silver plate pretty soon ... – Angel O'Sphere Sep 28 '11 at 12:38
  • ... not to mention that he likely will pay the rest of his live for the damge he might have caused with this. – Angel O'Sphere Sep 28 '11 at 12:40
  • 3
    Hehe, rep comes from activity and activity is related to age ... I only post here sometimes since the last 4 monthes or so. Also you get rep if your answers get upvoted or accepted ... I'm mainly correcting errors. Like the wrong upvoting of this answer. I don't care if I get rep for that or not. – Angel O'Sphere Nov 03 '11 at 12:30
  • What do you think about Dto and Inheritance? – ramon_salla Jan 08 '13 at 07:26
  • I can relate with the pain here...my application heavily used State Objects which was ancient name of Transfer Objects and we have data in hibernate entities as well as in state objects...legacy system architecture...phew !!! – Rachel Mar 11 '13 at 18:48
  • 1
    Just sad that the accepted answer doesn't answer the part "What are the alternatives" – Snicolas Sep 07 '15 at 20:31
  • 2
    @AngelO'Sphere To me it sounds like your cure is worse than the illness., at least for not very enterprisey projects. Sure, you can use some boilerplate generator to get even more boilerplate, and it usually works well, but with any problem you'll lose more time than you've saved. – maaartinus Sep 09 '15 at 20:00
  • The use of code generators sometimes hinta at missing language features. Sadly, Java does not support representing simple data structures out of the box, unlike Haskell, Scala, Swift... Lombok is also a code generator btw., with the only difference that it does not generate source code. – yeoman May 24 '17 at 07:24
131

DTOs are not an anti-pattern. When you're sending some data across the wire (say, to an web page in an Ajax call), you want to be sure that you conserve bandwidth by only sending data that the destination will use. Also, often it is convenient for the presentation layer to have the data in a slightly different format than a native business object.

I know this is a Java-oriented question, but in .NET languages anonymous types, serialization, and LINQ allow DTOs to be constructed on-the-fly, which reduces the setup and overhead of using them.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Gabe Moothart
  • 28,997
  • 13
  • 73
  • 98
  • I'm going to have to downvote this answer because of your mention of serializing anonymous types. You can't even _return_ an anonymous type, much less serialize it in the same way you could serialize a DTO. – John Saunders Sep 17 '09 at 20:06
  • 15
    @John, This is incorrect. I do it all the time. Serialization uses reflection, which works just fine on anonymous types. Just pass it to the serializer as an object. And once it is serialized (to xml or json, for example) of course you can return it from a method. – Gabe Moothart Sep 17 '09 at 20:24
  • 8
    Um, John, that's just not true. You can serialize anonymous types to JSON just fine. Try it in an MVC app: return Json(new { Foo = "Hi there! } ); I promise you it works just fine. Better, perhaps, than non-anonymous types, since anonymous types generally have no cycles in their object graphs, which break the JSON serializer. – Craig Stuntz Sep 17 '09 at 20:24
  • 2
    Json serialization is not a DTO in this sense, and therefore doesn't apply. Then of course, my arguments above apply as well, at some point, they just stop being worth it. – Jim Barrows Sep 17 '09 at 22:50
  • 1
    Gabe is right, DTO is not an anti-pattern per se (but can be if used incorrectly!) when there is no data duplication. For example, BO can aggregate data from different sources into a DTO. – a.s.t.r.o Jan 23 '11 at 12:36
  • 3
    +1. And there are plenty of other reasons besides bandwidth conservation that you'll want DTOs. Are you even ALLOWED (by company policy or law) to send every field across the wire? Also, in our company our DAO is very complex because it needs to make all these optimizations -- working in the service-layer, I'm really glad they use a DTO and don't make us worry about the relationship that Object X has to some other n-to-n table. – user64141 Aug 29 '14 at 15:08
27

DTO an AntiPattern in EJB 3.0 says:

The heavy weight nature of Entity Beans in EJB specifications prior to EJB 3.0, resulted in the usage of design patterns like Data Transfer Objects (DTO). DTOs became the lightweight objects (which should have been the entity beans themselves in the first place), used for sending the data across the tiers... now EJB 3.0 spec makes the Entity bean model same as Plain old Java object (POJO). With this new POJO model, you will no longer need to create a DTO for each entity or for a set of entities... If you want to send the EJB 3.0 entities across the tier make them just implement java.io.Serialiazable

aem
  • 3,790
  • 22
  • 20
  • 7
    True when you're transferring objects between methods in the same JVM, in memory. Not true when you are actually serializing over the wire and want control over how deep to serialize, and/or preserve lazy loading. – wrschneider Nov 07 '12 at 19:51
  • Yes, and even in the same JVM, you should really take care to stay in the same thead if you use JEE/Spring transactional management. – Marc Apr 02 '14 at 13:40
23

I don't think DTOs are an anti-pattern per se, but there are antipatterns associated with the use of DTOs. Bill Dudney refers to DTO explosion as an example:

http://www.softwaresummit.com/2003/speakers/DudneyJ2EEAntiPatterns.pdf

There are also a number of abuses of DTOs mentioned here:

http://anirudhvyas.com/root/2008/04/19/abuses-of-dto-pattern-in-java-world/

They originated because of three tier systems (typically using EJB as technology) as a means to pass data between tiers. Most modern day Java systems based on frameworks such as Spring take a alternative simplified view using POJOs as domain objects (often annotated with JPA etc...) in a single tier... The use of DTOs here is unnecessary.

David Klempfner
  • 6,679
  • 15
  • 47
  • 102
Jon
  • 55,763
  • 30
  • 120
  • 149
  • 3
    You are completely right that DTO's are [a good pattern](http://martinfowler.com/eaaCatalog/dataTransferObject.html), not an anti-pattern, when used in their proper context. Your second link appears dead right now, but the greatest abuse I have seen is where every domain object had a corresponding "DTO" for database interaction which added no value and wasn't a DTO at all! – David Oct 23 '14 at 13:45
22

OO purists would say that DTO is anti-pattern because objects become data table representations instead of real domain objects.

Darin Dimitrov
  • 960,118
  • 257
  • 3,196
  • 2,876
9

Some consider DTOs an anti-pattern due to their possible abuses. They're often used when they shouldn't be/don't need to be.

This article vaguely describes some abuses.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Ben S
  • 65,441
  • 30
  • 165
  • 210
  • 1
    The article much more accurately describes DTOs as a pattern which can be abused. – Craig Stuntz Sep 17 '09 at 19:57
  • 1
    This amounts to a link-only answer, it really needs at least a quote from the article. don't know how this managed to not get flagged as Not An Answer. – Nathan Hughes Jan 17 '19 at 14:34
  • Link is dead, try https://web.archive.org/web/20110707143818/https://anirudhvyas.com/root/2008/04/19/abuses-of-dto-pattern-in-java-world/ – Davi Lima Dec 30 '19 at 15:54
7

If you're building a distributed system, then DTOs are certainly not an anti pattern. Not everyone will develop in that sense, but if you have a (for example) Open Social app all running off JavaScript.

It will post a load of data to your API. This is then deserialized into some form of object, typically a DTO/Request object. This can then be validated to ensure the data entered is correct before being converted into a model object.

In my opinion, it's seen as an anti-pattern because it's mis-used. If you're not build a distributed system, chances are you don't need them.

David Klempfner
  • 6,679
  • 15
  • 47
  • 102
Bealer
  • 855
  • 9
  • 16
5

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.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
javadev
  • 1,564
  • 2
  • 15
  • 35
5

The question should not be "why", but "when".

Definitively it's anti-pattern when only result of using it is higher cost - run-time or maintenance. I worked on projects having hundreds of DTOs identical to database entity classes. Each time you wanted to add a single field you ad to add id like four times - to DTO, to entity, to conversion from DTO to domain classes or entities, the inverse conversion, ... You forgot some of the places and data got inconsistent.

It's not anti-pattern when you really need different representation of domain classes - more flat, more rich, more narrow, ...

Personally I start with domain class and pass it around, with proper check in the right places. I can annotate and/or add some "helper" classes to make mappings, to database, to serialization formats like JSON or XML ... I can always split a class to two if I feel the need.

It's about your point of view - I prefer to look at a domain object as a single object playing various roles, instead of multiple objects created from each other. If the only role an object has is transporting data, then it's DTO.

Rostislav Matl
  • 3,781
  • 4
  • 23
  • 50
4

The intention of a Data Transfer Object is to store data from different sources and then transfer it into a database (or Remote Facade) at once.

However, the DTO pattern violates the Single Responsibility Principle, since the DTO not only stores data, but also transfers it from or to the database/facade.

The need to separate data objects from business objects is not an antipattern, since it is probably required to separate the database layer anyway.

Instead of DTOs you should use the Aggregate and Repository Patterns, which separates the collection of objects (Aggregate) and the data transfer (Repository).

To transfer a group of objects you can use the Unit Of Work pattern, that holds a set of Repositories and a transaction context; in order to transfer each object in the aggregate separately within the transaction.

MovGP0
  • 5,754
  • 2
  • 40
  • 37
1

I think the people mean it could be an anti-pattern if you implement all remote objects as DTOs. A DTO is merely just a set of attributes and if you have big objects you would always transfer all the attributes even if you do not need or use them. In the latter case prefer using a Proxy pattern.

David Klempfner
  • 6,679
  • 15
  • 47
  • 102
jdehaan
  • 19,108
  • 6
  • 54
  • 94