DTO vs Domain Models

Note: read Part II of this post here.

A Data Transfer Object (DTO) is an object intended to carry data, for example between the client and the server or between the UI and the domain layer. It exposes fields or properties (getters and setters) publicly. Sometimes a DTO could be seen as an anemic model. DTOs are mostly used out of the hexagon, in the delivery mechanism.

On the other hand domain models should promote a good object oriented design with proper encapsulation. They belong in the hexagon.

However it's not always clear where to use a DTO and a domain model, where and how to convert one into the other. None of the approaches we have tried are working for us in all the cases, there are always exceptions. But there are some principles that are helping me:

Principle: Domain models may travel out of the hexagon but... do not bind domain models to the GUI directly.
Reason: Data mappers like XAML binding need public setters and getters. We don't want public setters in our domain models. When the GUI is defined with XAML, the data binding is declared in this XML. Changing the visibility of a getter from public to private will compile but as soon as the user enters some data in a bound field it will throw a runtime exception that we can't reproduce with automated tests, it's hard to discover.

Principle: Apply data transformations out of the core hexagon 
Usually objects start with one or two fields and no logic on them, they are anemic models. At that stage there is no difference with a DTO.

Later on, as we learn about the domain and the objects grow, we need to apply transformations to carry data over to the view or through the network.  Our first approach was to populate the DTO from the model:

  1. var dto = domainModel.ToDto(); // model to dto
  2. var model = DomainModel.From(dto); // model from dto


But as many people commented on this post and as we saw later, it's not a good idea because we are coupling the domain models to the way data is exported and sent out of the hexagon. Coupling is unavoidable, what matters is the direction of the coupling. It's OK that the outside world knows the model but it's not that good to pollute our core domain with external concerns like GUIs or serialization.

Our current approach is to have an "adapter" class that knows both worlds and connect them:

  1. var dto = adapter.ToDto(model); // model to dto
  2. var model = adapter.ToModel(dto); // model from dto

 

Thanks everyone for the comments

Enjoyed reading this post?
Subscribe to the RSS feed and have all new posts delivered straight to you.
  • Antonio Vilar

    Nice post, Carlos!

    The only thing I would suggest is to extract the responsibilities of building the DTO (and recreating the domain object back from the DTO) from the domain object into a specific DTOAssembler/Disassembler.

    Besides SRP, we might need different data for the same domain object depending on the context. Imagine the scenario where you have an aggregate with some entities. To render a specific view in the GUI or to return a JSON response in an API you might not need to build a full DTO containing all the entities information. Having different assemblers for different representations could be an approach to avoid this overhead.

    Thanks for your post!

  • Pedro Vicente Gómez Sánchez

    Another interesting approach to offer DTOs to the delivery mechanism is to declare an immutable interface implemented by your domain models. This approach is not always valid, but if your domain model has a similar structure doing this you avoid to write a class declaring the DTO and also perform the mapping between the domain model and the DTO.

    When you say “Usually objects start with one or two fields and no logic on them. We consider them DTOs” don’t you want to say Value Objects and not about DTOs? The DTO motivation is to offer an element containing data to abstract the model used inside your system. A Value Object can be part of your domain model but a DTO no.

  • http://www.carlosble.com/ Carlos Ble

    Good point Antonio, I think that is a useful resource in some cases. There is one problem though. I want my domain models to have no setters and getters because I want a good object oriented design, tell don’t ask. This is not always possible but it’s were I want to go. If the data fields a private, the DTOAssembler will not be able to get data from the domain model. However, I like the idea of this kind of Adapter to transform one form of DTO to many others DTO formats. Thank you 🙂

  • http://www.carlosble.com/ Carlos Ble

    I try to avoid getters and setters in my domain models as much as I can. Implementing an interface will force me to expose those getters/setters in my domain model. On the other hand, a DTO can be used carry data from an Entity or a Value Object, I don’t understand the relationship between Value objects and Dtos that you say. Perhaps we have a different understanding of what “Value Object” means? To me it’s an object without identify that is immutable, for example a Color.
    Thanks 🙂

  • https://twitter.com/pasku1 Guillermo Pascual

    I accept your premise, it’s all about separation of concern – decoupling domain model and presentation layer. For me that’s enough good reasons to have some kind of abstraction between view and domain. But I don’t want the trade off traditional DTO implementation implies. I don’t want to code potentially n data transfer objects AND their corresponding transformations for (maybe only) one domain object. And I don’t want to put transformation logic into domain objects or pollute my repositories with toDTO(…) and fromDTO(…) methods. I prefer design a view model as a thin wrapper around the domain model and expose just the properties and functionality that I care about and that is valid for my specific use case. Changes can be applied to GUI components and the view model such that view layer and domain model can evolve independently. Although both models are strongly related to each other (the view model is mainly a custom representation (=view) of the domain model ) they do vary in different aspects. Since the design of the view layer aligns with the steps of user interactions required by the usecases, its model tends to have a different granularity than the domain model. Additionally data types in both models may be different and the view model might provide access to other functionality like syntactical validation, internationalization, transformation steps like data type mapping, string mutations, formatting etc. and even technology specific properties.

    This approach would allow me to initially define the view model analogous to the domain model and then have the view model evolve over time as it gets tailored to the specific usecase requirements. There would be no mapping overhead, no additional transformations and I could reuse some of the functionality of the domain model that is also valid in the context of the view layer.

  • expendable

    I like to give as an example of DTO the form in a web-page, It is just carrying info into the application but it is not part of the business model behind. (You can also say a form is a business object for the presentation layer of course, but it is not for the main purpose of the application)
    What I usually do for complex representation of models in the presentation layer is hide them in a decorator strategy.
    For example, let’s say you have some params for a user and you have to translate them with some extra logic, it is not just a part of the i18n responsability of the page. You could have a DTO I18NUserParams(params, userLocale) and pass it to the presentation layer. So, the changes between what is shown and what is computed are usually behind just a class, not spread all over the presentation layer.

  • Antonio Vilar

    That sounds absolutely right. We should avoid building anemic domain models as they’re not proper OOP.

    What I don’t see is the need to expose the object privates through a DTO (unless what you want is to serialize your domain object to be able to send it over the wire to reconstruct it at the other end). Imho we should keep encapsulation and a DTO shouldn’t expose anything we can’t get from a public method. What kind of private fields would be of interest for anyone outside the domain object?

    And in case you really needed them you could still use black magic, I mean, reflection 🙂

  • http://www.carlosble.com/ Carlos Ble

    We are using ViewModels too and they are often a wrapper around DTOs. What happens in our current scenario is that we didn’t know much about the domain model and we had to pull data out from the legacy system. That system has the logic within store procedures that return data structures which are the models in the old system. We don’t have a proper domain model yet as we would like to. It’s time for us to stop and refactor towards a consistent and meaningful domain model, now that we understand the business better. So currently our DTOs are actually domain models that want to emerge. The C# layer looks like a CRUD system sometimes and several models ended up bound to the UI unfortunately.
    If you have some references to related articles you recommend, they’d be appreciated, thanks 🙂

  • http://www.carlosble.com/ Carlos Ble

    Serialization is one of the primary reasons for us to do that. It’s often the same with JavaScript and JSON.parse and JSON.stringify.
    The problem we are struggling with, is the fact that we don’t have a consistent and well-designed domain model in place as we are learning from the legacy system.
    It’s refactor time 😉

    Thank you!

  • http://www.carlosble.com/ Carlos Ble

    Sounds interesting man, could you please provide a code example?

    Thank you!

  • elazotadordecopiones

    Very bad Guillermo, at least when you copy a blog post, please refer to the owner http://codeblock.engio.net/lightweight-view-model-pragmatic-approach-to-dto-implementation/

  • http://www.carlosble.com/ Carlos Ble

    Post updated, thank you for your feedback 🙂

  • Cherif BOUCHELAGHEM

    Thank you Carlos, I can know change my EntityReconstituter to Adapter, sounds more familiar in the haxagonal world, I have one question:
    Do you have an adapter for each entitydto or just one adapter to handle them all?

  • Ian Worthington

    Isn’t this basically what Automapper does

  • Dragan Stepanovic

    But Carlos, how do you extract private, encapsulated, properties from domain object in order to create DTO object? Exactly, what is the code in ToDto(ModelClass modelObject) method?
    var dto = adapter.ToDto(model); // model to dto

  • http://www.carlosble.com/ Carlos Ble

    Yeah, pretty much

  • http://www.carlosble.com/ Carlos Ble

    Recently I don’t mind having getters to be able to export data. I avoid setters. But yes, there are always situations where you might even want to use reflection.

  • http://www.carlosble.com/ Carlos Ble

    As far as they are easy to find and to reason about, it’s fine to have a single file or a single module. Whatever you find intuitive when you search for it.