5 Rules for DTOs

Date Published: 06 April 2024

5 Rules for DTOs

If you don't like reading, here's my YouTube video with samples that covers why these 5 rules will help you write better DTOs:

What's a DTO?

A DTO is a Data Transfer Object. Its job is to transfer data, and it can be used both to send data and to receive it. Often, data transferred will use different types (possibly even different programming languages and technology stacks) on each end of the transfer. The only thing you can count on transferring is the data - nothing else. Which leads to the first rule for DTOs.

Rule 1. DTOs only contain data. No logic or behavior.

DTOs should be super easy to work with, as well as to author. They do not benefit from encapsulation and typically they should avoid using inheritance as well (hiding things isn't something we want with DTOs, and reuse is overrated, too). Which leads us to the second rule.

Rule 2. DTOs do not enforce encapsulation. They don't need private/protected members.

Now, even though DTOs don't need encapsulation, it's still generally preferred to use C# properties rather than fields. By default, serializers and other language features work on properties but not fields (though you can configure this). Rule 3:

Rule 3. DTOs should use properties (not fields).

But what should you name them? An obvious naming convention is simply to add "DTO" (or "Dto") to the end of whatever sort of thing is being described. While this works and is fine for the most basic representation, there are many cases where you should use a more descriptive name.

Many common types used in modern dotnet apps can (and usually should) be modeled as DTOs. These include API request and response objects, commands and queries, events, and more. In such cases, suffix the type with the more specific name (e.g. "CreateUserRequest" instead of just "UserDTO"). See rule 4.

Rule 4. DTOs should only use "-DTO" suffix as a last resort. Prefer more descriptive names.

Here are some of the things that should be DTOs, and should be named according to their particular use, rather than naming them "FooDTO", as rule 5:

Rule 5. These should be modeled as DTOs: API Request/Response types, MVC ViewModel objects, Database query result objects, Messages like commands, events, and queries.

Summary

There's actually quite a bit more to say about DTOs, like how to map them, where they should live, and what types they should reference, but I'll save that for a follow-up article/video.

Watch the full video on YouTube with samples here. Thanks!

Keep Up With Me

If you're looking for more content from me in your inbox subscribe to my weekly tips newsletter and be sure to follow me on YouTube.

Steve Smith

About Ardalis

Software Architect

Steve is an experienced software architect and trainer, focusing on code quality and Domain-Driven Design with .NET.