8

From what I've read and implemented, DTO is the object that hold a subset of value from a Data model, in most cases these are immutable objects.

What about the case where I need to pass either new value or changes back to the database?

Should I work directly with the data model/actual entity from my DAL in my Presentation layer?

Or should I create a DTO that can be passed from the presentation layer to the business layer then convert it to an entity, then be updated in the DB via an ORM call. Is this writing too much code? I'm assuming that this is needed if the presentation layer has no concept of the data model. If we are going with this approach, should I fetch the object again at the BLL layer before committing the change?

aggietech
  • 978
  • 3
  • 16
  • 38

3 Answers3

24

A few thoughts :

  • DTO is a loaded term, but as it stands for Data Transfer Object, I see it more as a purely technical, potentially serializable container to get data through from one point to another, usually across tiers or maybe layers. Inside a layer that deals with business concerns, such as the Domain layer in DDD, these little data structures that circulate tend to be named Value Objects instead, because they have a business meaning and are part of the domain's Ubiquitous Language. There are all sorts of subtle differences between DTO's and Value Objects, such as you usually don't need to compare DTO's, while comparison and equality is an important concern in VO's (two VO's are equal if their encapsulated data is equal).

  • DDD has an emphasis on the idea of rich domain model. That means you usually don't simply map DTO's one-to-one to domain entities, but try to model business actions as intention-revealing methods in your entities. For instance, you wouldn't use setters to modify a User's Street, City and ZipCode but rather call a moveTo(Address newAddress) method instead, Address being a Value Object declared in the Domain layer.

  • DTO's usually don't reach the Domain layer but go through the filter of an Application layer. It can be Controllers or dedicated Application Services. It's Application layer objects that know how to turn DTO's they got from the client, into the correct calls to Domain layer Entities (usually Aggregate Roots loaded from Repositories). Another level of refinement above that is to build tasked-based UIs where the user doesn't send data-centric DTO's but Commands that reflect their end goal.

So, mapping DTO's to Entities is not really the DDD way of doing things, it denotes more of a CRUD-oriented approach.

guillaume31
  • 13,738
  • 1
  • 32
  • 51
  • This should be the accepted answer. I cannot recall off the top of my head references to DTO in Evans Blue Book (https://www.amazon.co.uk/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215) or Vernon's Red Book (https://www.amazon.co.uk/Implementing-Domain-Driven-Design-Vaughn-Vernon/dp/0321834577/ref=pd_lpo_sbs_14_img_0?_encoding=UTF8&psc=1&refRID=YTEGVFAYABVGK85V70VD) - but not got these at hand. And a quick search through Distilled DDD ebook by Vernon yields no mention of a DTO. – Andez Jan 11 '19 at 21:20
6

Should I work directly with the data model/actual entity from my DAL in my Presentation layer?

This is okay for small to medium projects. But when you have a large project with more than 5 developers where different layers are assigned to different teams, then the project benefits from using a DTO to separate the Data Layer from the Presentation Layer.

With a DTO in the middle, any changes in the presentation layer won't affect the data layer (vice versa)

Or should I create a DTO that can be passed from the presentation layer to the business layer then convert it to an entity, then be updated in the DB via an ORM call. Is this writing too much code? I'm assuming that this is needed if the presentation layer has no concept of the data model. If we are going with this approach, should I fetch the object again at the BLL layer before committing the change?

For creating a new entity, then that is the usual way to go (for example "new user"). For updating an existing entity, you don't convert a DTO to an entity, rather you fetch the existing entity, map the new values then initiate an ORM update.

UpdateUser(UserDto userDto)
{
    // Fetch
    User user = userRepository.GetById(userDto.ID);

    // Map
    user.FirstName = userDTO.FirstName;
    user.LastName = userDTO.LastName;

    // ORM Update
    userRepository.Update(user);
    userRepository.Commit();
}

For large projects with many developers, the disadvantage of writing too much code is minimal compared to the huge advantage of decoupling it provides.

See my post about Why use a DTO

Community
  • 1
  • 1
Yorro
  • 11,445
  • 4
  • 37
  • 47
  • 2
    "For updating an existing entity, you don't convert a DTO to an entity, rather you fetch the existing entity, map the new values" wouldn't you be writing the same mapping code twice this way? – uylmz Nov 25 '15 at 16:30
2

My opinion is that DTOs represent the contracts (or messages, if you will) that form the basis for interaction between an Aggregate Root and the outside world. They are defined in the domain, and the AR needs to be able to both handle incoming instances and provide outgoing instances. (Note that in most cases, the DTO instances will be either provided by the AR or handled by the AR, but not both, because having one DTO that flows both ways is usually a violation of separation of concerns.)

At the same time, the AR is responsible for providing the business logic through which the data contained in the DTOs are processed. The presentation layer (or any other actor including the data access layer, for that matter) is free to put whatever gibberish it wants into a DTO and request that the AR process it, and the AR must be able to interpret the contents of the DTO as gibberish and raise an exception.

Because of this requirement, it is never appropriate to simply map a DTO back to its Entity counterpart.

The DTO must always be processed through the logic in the AR in order to affect changes in the Entity that may bring it to the state described by the DTO.

Matt Mills
  • 8,692
  • 6
  • 40
  • 64
  • I'd also add that if you're doing DDD/CQRS, the Aggregate Root would not ever provide a DTO, because those would come from the view model. However, since the question is **not** about DDD/CQRS, I'm assuming you are using the AR to get the data which is presented by the presentation layer. – Matt Mills Jan 22 '15 at 14:43
  • 1
    I agree with your statement in bold, but not with the part about DTO interfaces. A DTO has no behavior by definition, and the purpose of an interface is to provide a behavioral contract, so why a DTO interface ? Also, Domain Entities don't accept raw DTO's from the client, most of the time it goes through an Application layer first. Application layer services know how to call Entity/AR methods, passing them value objects or simple primitive values (but not DTO's in the "data transfer" sense of the term). – guillaume31 Jan 23 '15 at 11:00
  • I suppose I'm using a somewhat specialized understanding of the term *interface* - I'm thinking of the C# language, in which the notion of a "read-only property" can be exposed at the interface level. In the strictest sense, this gives the DTO "behavior": "I have a value, and you're welcome to look at it, but you may not change it". My intent was more that the **interfaces** allow the DTOs to be immutable to the receiving code. In any case, the specification of *interfaces* in the answer is irrelevant, so I will remove it. – Matt Mills Jan 23 '15 at 22:01