C
C#2y ago
D.Mentia

❔ DTOs Pros and Cons

Backstory: At work, we use models that contain DB entities, and we expect them to be partial; they should be Selected from the DB with only the minimal required data. I'm trying to convince them to use real DTOs instead, and what I'm hoping to do here is list my arguments, and see if anyone has any arguments against them that I should consider To be clear, instead of
class PatchMyEntityModel
{
MyEntity Entity {get; set;}
}
class PatchMyEntityModel
{
MyEntity Entity {get; set;}
}
I want
class PatchMyEntityModel
{
required Guid EntityGlobalId {get; init;}
string? Name {get; init;}
DateTime? Date {get; init;}
// ... etc
}
class PatchMyEntityModel
{
required Guid EntityGlobalId {get; init;}
string? Name {get; init;}
DateTime? Date {get; init;}
// ... etc
}
(Especially because the endpoint only supports updating a few specific properties, not all of them; entities might still be used in DTOs when they are actually needed, but ideally only internally) If I'm confused about what a 'DTO' is, let me know, though. I just want them to have explicit properties so I don't have to hunt through a chain of 12 methods that will be called with my model, to see what they all expect me to pass And yeah I'd rather use records, but there are some reasons we can't do that just yet DTO Pros: 1. Explicit properties that clearly show what data is required for this endpoint 2. Explicit return values - consumers don't have to wonder if a null might just mean we didn't Select that column 3. The capabilities of the endpoint are clearer 4. The caller can't include more data than necessary; reduces network overhead 5. Compile time errors instead of runtime errors, if giving the wrong arguments to an endpoint or trying to use return values that are not supplied from it - Runtime errors are a HUGE problem, the main thing I'm trying to solve here, and they are common when using entities because callers may not include the correct data in the entity, or may expect data in the returned entity that isn't actually populated 6. Decouples MyEntity from the API, MyEntity can be freely modified without affecting clients or endpoints using DTOs (as long as it can still fit existing DTOs) 7. Allows specific intellisense-capable documentation comments on each property DTO Cons: 1. Maintenance; if a DB entity is changed, in some cases, all DTOs using the changed column must be updated alongside the logic. This may (at most) double the number of places in the code you need to modify for an entity change (But even with entities, the logic still has to be updated, and all consumers must update their logic and your package - even if the change was superficial like a rename, which DTOs could allow without making the clients aware of it. Plus, updating the DTO is no different from updating a method signature, or updating an interface; it's not hard, the compiler tells you where and what to do, and it's worth it to have a contract) And... that's it, I think. Thoughts?
Clearly I seem to be underestimating the cost of maintenance, https://learn.microsoft.com/en-us/archive/msdn-magazine/2009/august/pros-and-cons-of-data-transfer-objects seems to imply that it's significant, but I just can't imagine a scenario where maintenance for DTOs is significantly more work than without.
Any time a DTO would have to be modified, the logic using an entity would also have to be modified. It's not at all hard, while you're there, to F12 to the DTO and update that too - that may even be the first thing you do, it's no different from updating a method signature if you're changing what that method takes. DTOs also allow some of those changes to the entity without changing the DTOs or forcing clients to update, whereas passing around entities does not allow that in any case
6 Replies
Saber
Saber2y ago
sounds about right to me. I don't really agree that dtos add much maint cost, if you rename an entities property, your going to have to rename it anywhere its used anyways
Angius
Angius2y ago
Regarding the cons, unless you're using Automapper or something, maintenance is made easier thanks to the IDE. Changing the name of a property will change it everywhere else as well, and it'll still be mapped to the correct DTO property But, yeah, you got it all right IMHO For the pros, you can also add less database overhead. You won't be generating SELECT * FROM t queries, but rather SELECT prop1, prop2 FROM t
D.Mentia
D.Mentia2y ago
Yeahhh we're using automapper. That's my next project, get rid of that... And yeah, I didn't mention that pro because we already expect callers to not do select *, which is sort of the source of the problem because who knows what's really going to be in one of those entity models
Angius
Angius2y ago
Ah, you just have everything nullable in the database models? If so, that's an oof and a half
D.Mentia
D.Mentia2y ago
Yeah...
Accord
Accord2y ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.