DTO is fine? DTO have any alternatives?
Hello,
I read on some blog that DTO should not be used in production. Is it true ?
Are there any alternatives to DTO?
Having a Product model and ProductDto just because it needs to be trimmed down by a few fields looks pretty dirty.
Thank you in advance!
16 Replies
Those blogposts are bullshit, then
DTOs should be used liberally
Data you receive from a request should be a DTO
Data you send back should be a DTO
@ZZZZZZZZZZZZZZZZZZZZZZZZZ thank you 🙂 Is there any other approach than DTO?
You can do weird stuff like adding
[JsonIgnore]
attributes to your EF entity properties
But it's neither secure nor clean
It's best to just use DTOs
And if you don't feel like mapping between them and models manually, use something like Riok.Mapperly
to map them for youThnaks. I do not like stuff like automapper. I will do it manually 🙂 Have a nice day!
Thing about dtos is that if some consumer needs more data, you've gotta go modify your api to return it. Where I work, we specifically don't use dtos to try to keep that to a minimum, we use the same db entities for everything. The idea is kinda not knowing or caring about which other services consume your api, return whatever you've got and if someone needs it, it's there
Now, to be clear, it's awful for a lot of reasons and I don't suggest it at all but, it is technically an alternative and some reasonably smart people seem to like it for some reason
"Hey API, can I get a blogpost?"
"Sure, here's the blogpost, the tags, the tag authors and their password hashes and emails, the blogpost author and their password hash and email, here's the category as well, and other blogposts in that category, their authors with their pass—"
It's worse than that, here's a blog post, the tags might or might not be null depending on the endpoint, and so might everything on a blog post, arbitrarily with no way to find out which ones are truly null or we just didn't select them
POOP at its worst
it lazy and bad design, I don't think those people are smart in that decision. Savvy, maybe.
I would not call on those choices at work to be smart.
I didn't say the choices were smart, just that smart people decided they're a good idea, there's a difference. lol
And to be fair I think it offers some other advantages that I don't quite understand, which are contingent on other practices we do (that I also don't really agree with but it is what it is)... like for example, if multiple services all deal with the same type of entity, those services share the same entity definition, so we don't have a dozen different Shipment entities. And if an API returns a Shipment entity, you can use it directly in another service without having to map it, and there's no confusion about whether a TrackingNumber it returns is the carrier's tracking number or ours, because it would be returned in the specific property for one or the other, whereas a DTO that returns just 'TrackingNumber' is ambiguous
But also we only do that stuff internally, if it's public facing or for clients, DTOs
I don't know why there would be a distinction to draw
I stopped arguing with them about it after a while, but tbh it does help to have me on this side, trying to 'defend' these decisions :lul:
Services exposing schemas to one another, internal or not, violates SRP and leaks detail
coupling individual services to the "right" version of a schema is even worse.
I agree, and our databases are often full of a lot of nonsense that we never use or just a bunch of nulls as a result. But it does make sense from the perspective of centralizing business definitions, keeping multiple dev teams in sync and aware of things like that there are two different types of tracking numbers
Changing a DTO is already a big deal, and you would already need to coordinate with all of the teams that use it in order to do so, so it's not really any more effort to maintain or change with or without DTOs. But it does get awkward when you want to make an internal change to your db structure, and it's kinda forced to be a public facing change - but, if you're changing something like making this bool into an enum, other teams that use it need to know about that and (eventually) do the same thing
But, the more I try to justify it the more it seems clear that it's only possibly beneficial in a very specific situation and very unlikely to be a good idea unless you're working in a big org doing other dumb things that make it worthwhile when you combine them all
If you want the client to decide what they need, you use GraphQL
Not just say "here's everything, whatever"
I think I was wrong about that actually, because we don't really do "here's everything, whatever", we do still specifically select things into it and still generally have to make changes if consumers need new things. I think the advantages are just from the other weird stuff we're doing that some guy decided was a good idea 20 years ago and it's too late to change it all now, and if you happen to have made those same bad decisions, then maybe you don't want DTOs
But yeah, TLDR, use DTOs, but technically it is an option to not use them. But I can tell you from experience that it really sucks to not use them
Oh, actually now I realize what I was trying to say with that; it's not that you don't have to touch your code if some consumer needs new data (and you're not using DTOs, you're returning db entities from your API) - you do still have to modify the query and include that new data in your output - it's that if you do that, you don't have to change your DTO and mess up all your other consumers
Though... most or all deserializiation of your API response is going to ignore any data that isn't in the class they're deserializing to, so even if you updated your DTO, as long as it's just adding a new property instead of modifying one, it's still backwards compatible. So even that isn't really an advantage
Thnak you guys for that discusion 🙂