Why use DTOs (Data Transfer Objects)?

Data Transfer Objects

Should you really use DTOs (Data Transfer Objects)? Seem like a lot of work mapping your database entities to another object? Why Bother? The simple answer is coupling.

Data Transfer Objects

First, what are DTOs? When people refer to Data Transfer Objects, what they mean are objects that represent data structures that generally do not contain any business logic or behavior. If they do contain behavior, it’s generally trivial.

Data Transfer Objects are often used to be serialized by the producer and then deserialized by the consumer. Often times these consumers may live in another process being used by an entirely different language and/or platform.

YouTube

I’ve recorded a short video explaining this with some sample code. Check out the video and make sure to subscribe to my YouTube Channel.

Crossing Boundaries

The most common example of this is creating an HTTP API using ASP.NET Core that returns an object from its Controller actions that are ultimately serialized to JSON. The consumer is oftentimes JavaScript that uses those JSON responses in displaying the browser using a Component or SPA Framework.

Internals

If you’re not using DTOs, then you’re likely exposing internal data structures.

The biggest culprit of this is simple TODO demo applications that expose the database entities directly. Meaning they output a serialized list of TODOs to the javascript frontend. And when you want to create a new record, they often times take the TODO object to insert directly into the database. This is leaking internals.

This is my biggest complaint with simple demo applications are they often don’t implement or follow some practices, because rightly so, they aren’t applicable to a simple TODO application. However, people take the example of a simple TODO and use the same patterns into a much large application.

The problem is when internal data objects are serialized and consumed by a client you either down own or cannot change easily. Or, which happens more often, the application itself gets very large.

Contracts

The moment you want change internal data objects, you now have to update the clients.

Take this simple example of a Customer that is an internal data structure we use through the system and likely use to persist using an ORM.

If we are serializing this structure and clients are consuming this, if we change this structure, we’re likely going to break out clients.

This change would require a change to all of our clients. We could easily make this change in our own codebase and have all our own usages be correct, but we would be breaking all of our decoupled clients that get a serialized representation.

Representation

When creating an HTTP API, it’s all about representations. Most often times clients need a rich representation of a resource, not a just serialized version of a database entity. They often times need related data.

Having your API return rich representations means you must do some level of composition to create an object, not just a database entity, that will get serialized. This is where a DTO comes into play.

I actually don’t often use the term DTO, but rather use the word Representation or ViewModel. The purpose is still the same, it’s a data structure that is a contract between the producer and the consumer. That contract should remain stable (through backwards compatibility) or have a versioning strategy.

Coupling

The reason you want to use DTOs is that you want clients to couple to that contract, not to your internal data structures. This allows you to modify and evolve your internals freely without breaking clients.

Links

Enjoy this post? Subscribe!

Subscribe to our weekly Newsletter and stay tuned.

CQRS: Refactoring Queries without Repositories

CQRS: Refactoring Queries without Repositories

This question posted on Twitter (and the subsequent thread) caught my attention. I had to pipe in with my own opinion on having queries without repositories.

To summarize, the question is about using Aggregate Roots with an ORM like Entity Framework. Should you eager load all navigation properties or alternatively I guess, use lazy loading?

My answer is if you’re only using an aggregate root for commands (to change state) and you generally have a higher read to write ratio, then eager load the navigation properties. As a general rule of thumb.

eShopOnWeb

I recently heard about eShipOnWeb from Steve Smith. It’s a reference application using ASP.NET Core 3.1 using a layered monolithic architecture.

I decided to take a look around and try and refactor a spot that was using a repository for a query.

There is a query to return all of the orders for a signed-in user. It’s pretty simple but is a good example of it using the OrderRepository along with a specification to fetch out the relevant orders. From there it creates a ViewModel that is used in a Razor view.

Here’s the razor view for reference

Looking at the Razor view, you can see that it doesn’t use some of the properties on OrderViewModel. The OrderItems or ShippingAddress properties are never used.

The Repository with the specification is retrieving the entire Order Aggregate Root and eager loading the OrderItems. We’re fetching in a lot of data that we simply aren’t using.

Refactoring Queries without Repositories

The refactor is rather simple. Just remove the repository and instead inject the Entity Framework DbContext (CatalogContext). The second part is creating a separate ViewModel (MyOrdersViewModel ) that only contains the data we need for our Razor view. Then use this new ViewModel as a projection in our EF Query.

Side Notes

In many situations, I prefer to create a SQL Database View that I will create a new class to represent and use that as a DbSet in my DbContext. And most often I have a completely different DbContext for writes vs reads. My Reads DbContext is what will have a model that represents the SQL view. This allows you to do that projection as an SQL View rather than doing the projection in your code.

If you were using a SQL Database View and created an OrderSummary class that was on your DbContext, that now might look like this:

Live Coding Session

I did a live coding session on my YouTube and Twitch channels. You can check out the recording here of doing this exact refactor.

GitHub

If you want to take a look a the full sample, you can also find my refactor changes on my fork of eShipOnWeb on GitHub.

Links

Enjoy this post? Subscribe!

Subscribe to our weekly Newsletter and stay tuned.

Loosely Coupled Show: Software Architecture and Design

Loosely Coupled Show

I’m excited to announce the Loosely Coupled Show, a new project I’m working on with James Hickey. Check out the YouTube Channel and subscribe!

The premise is simple. To have discussions about software architecture and design. The target audience is intermediate to senior software developers.

Episode #000

We recorded a quick video to kind of describe what the plan is for the show, check out our “first” episode for more about the show and us and our backgrounds.

Loosely Coupled Show

I’ve also posted a short video on my CodeOpinion YouTube channel to elaborate a bit more on the announcement, which you can check out as well.

Software Architecture and Design

I think at no matter what level you are in terms of experience in software development, architecture and design are something you already do. To what degree is what varies.

From how you organize code, define dependencies and even naming. They’re all different aspects of design.

There are many more advanced topics we’d like to talk about such as:

  • Top-level Architectures
  • Event Driven Architecture
  • Domain Driven Design
  • Service Boundaries
  • Microservices
  • Messaging
  • Concurrency
  • Fault Tolerance

And we can’t leave out the cloud. Yes, it’s just someone else’s computer but it’s a real enabler for new ways to build and deploy applications.

If you have any recommendations for specific topics you would like us to cover, or to recommend a guest, let me know on Twitter or in the comments!

Related Links

Enjoy this post? Subscribe!

Subscribe to our weekly Newsletter and stay tuned.