33

I am considering to use DTOs instead of passing around my domain objects. I have read several posts here as well as elsewhere, and i understand there are several approaches to getting this done.

If i only have about 10 domain classes in all, and considering that i want to use DTOs rather than domain objects for consumption in my Views (WPF front ends), what is the recommended approach. I think using tools like automapper etc maybe an overkill for my situation. So i am thinking of writing my custom mapper class that will have methods for converting a domain type to a DTO type.

What is the best way to do this, are there any sample to get me started to do this?

Second question: When writing those methods that will create DTOs, how do i deal with setting up all the data, especially when the domain type has references to other domain objects? Do i write equivalent properties in the DTO for mapping to those refernece types in the domain class? Please ask if i have not put my second question in proper words. But i think you understand what i am trying to ask.

Thrid question: When writing DTOs, should i write multiple DTOs, each containing partial data for a given domain model, so that each of it can be used to cater to a specific View's requirement, or should the DTO have all the data that are there in the corresponding model class.

  • Be prepared to also write multiple specific Data Transfer Objects for specific Service Methods, not only for specific Domain Models. – Lightman Dec 29 '15 at 11:27

7 Answers7

15

I've been reading a few posts here regarding DTO's and it seems to me that a lot of people equate them to what I would consider a ViewModel. A DTO is just that, Data Transfer Object - it's what gets passed down the wire. So I've got a website and services, only the services will have access to real domain/entity objects, and return DTO's. These may map 1:1, but consider that the DTO's may be populated from another service call, a database query, reading a config - whatever.

After that, the website then can take those DTO and either add them to a ViewModel, or convert into one. That ViewModel may contain many different types of DTO's. A simple example would be a task manager - the ViewModel contains both the task object you are editing, as well as a group of Dto.User objects that the task can be assigned to.

Keep in mind that the services returning DTO's maybe used by both a website, and maybe a tablet or phone application. These applications would have different views to take advantage of their displays and so the ViewModels would differ, but the DTO's would remain the same.

At any rate, I love these types of discussions, so anyone please let me know what you think.

Matt

Matt Klinker
  • 773
  • 5
  • 18
  • 1
    Just to clarify a DTO is not a ViewModel. Its not a DisplayModel its a TransferModel agnostic of the UI. Even more when you do REST Services transfering DTOs they should know nothing of the UI structure. – Elisabeth Dec 10 '13 at 15:40
4

I'm kind of using DTOs in a project. I tend to make the DTOs only to show the data I need for an specified view. I fetch all the data shown in the view in my data access class. For example, I may have an Order object which references a Client object:

public class Client{
    public int Id{get;set;}
    public string Name{get;set;}
}

public class Order{
    public int OrderID{get;set;}
    public Client client{get;set;}
    public double Total{get;set;}
    public IEnumerable<OrderLine> lines {get;set;}
}

Then in my OrderListDTO I may have something like:

public class OrderListDTO{
    public int OrderId{get;set;}
    public string ClientName{get;set;}
    ...
 }

Which are the fields I want to show in my view. I fetch all these fields in my Database access code so I don't have to bother with entity asociations in my view or controller code.

Carles Company
  • 7,118
  • 5
  • 49
  • 75
  • How do you handle the "lines" property in your DTO objects? Do you make OrderListDTO flat or do you load the "lines" collection some how? – PPC-Coder Jun 06 '11 at 00:01
  • Depends on the context. If I need the lines in the view, I load them; if not, I don't. Sometimes I may have a LineCount property on my OrderListDTO and I do LineCount=order.lines.Count(), or I show a total: LineSum=order.lines.Sum(t=>t.Quantity)... – Carles Company Jun 06 '11 at 06:06
3

Best Way to develop DTOs

The way to start developing DTOs is to understand that their sole purpose is to transfer subset of data of your business entities to different clients(could be UI, or an external service). Given this understanding you could create seperate packages for each client...and write your DTO classes. For mapping you could write your own mapper defining interfaces to be passed to a factory creating DTO objects based on which data from the entity for which the DTO is being created would be extracted. You could also define annotations to be placed on your entity fields but personally given the number of annotations used I would prefer the interface way. The main thing to note about DTOs is that they are also classes and data among the DTOs should be reused, in other words while it may seem tempting to create DTOs for each use case try to reuse existing DTOs to minimize this.

Getting started

Regarding getting started as stated above the sole purpose of the DTO is to give the client the data it needs....so you keeping in mind you could just set data into the dto using setters...or define a factory which creates a DTO from an Entity based on an interface.....

Regarding your third question, do as is required by your client :)

prashant
  • 1,382
  • 1
  • 13
  • 19
1

I come to project with spring-jdbc and there are used DAO layer. Some times existing entities doesn't cover all possible data from DB. So I start using DTO.

By applying '70 structure programming rule I put all DTOs into separate package:

package com.evil.dao;     // DAO interfaces for IOC.
package com.evil.dao.impl; // DAO implementation classes.
package com.evil.dao.dto; // DTOs

Now I rethink and decide to put all DTO as inner classes on DAO interfaces for result-sets which have no reuse. So DAO interface look like:

interface StatisticDao {
    class StatisticDto {
        int count;
        double amount;
        String type;

        public static void extract(ResultSet rs, StatisticDto dto) { ... }
    }

    List<StatisticDto> getStatistic(Criteria criteria);
}


class StatisticDaoImpl implements StatisticDao {
    List<StatisticDto> getStatistic(Criteria criteria) {
        ...
        RowCallbackHandler callback = new RowCallbackHandler() {
            @Override
            public void processRow(ResultSet rs) throws SQLException {
                StatisticDao.StatisticDto.extract(rs, dto);
                // make action on dto
            }
        }
        namedTemplate.query(query, queryParams, callback);
    }
}

I think that holding related data together (custom DTO with DAO interface) make code better for PageUp/PageDown.

gavenkoa
  • 45,285
  • 19
  • 251
  • 303
1

Question 1: If the DTO's you need to transfer are just a simple subset of your domain object, you can use a modelmapper to avoid filling your codebase with logic-less mapping. But if you need to apply some logic/conversion to your mapping then do it yourself.

Question 2: You can and probably should create a DTO for each domain object you have on your main DTO. A DTO can have multiple DTO's inside of it, one for each domain object you need to map. And to map those you could do it yourself or even use some modelmapper.

Question 3: Don't expose all your domain if your view does not require it to. Also you don't need to create a DTO for each view, try to create DTO's that expose what need to be exposed and may be reused to avoid having multiples DTO's that share a lot of information. But it mainly depend's on your application needs.

If you need clarification, just ask.

gutors
  • 43
  • 7
0

I'm going to assume that your domain model objects have a primary key ID that may correspond to the ID's from the database or store they came from.

If the above is true, then your DTO will overcome type referecning to other DTO's like your domain objects do, in the form of a foreign key ID. So an OrderLine.OrderHeader relationship on the domain object, will be OrderLine.OrderHeaderId cin the DTO.

Hope that helps.

Can I ask why you have chosen to use DTO's instead of your rich domain objects in the view?

Martin Blore
  • 2,125
  • 4
  • 22
  • 34
  • 2
    Can the DTOs have ID properties in them? - i.e. OrderlineID in your sample. I thought DTOs are fully self contained data objects which won;t have any reference to database,and other external dependencies. As for why DTOs, my project will eveolve into a large system in future, and i want to ensure I build it now to adhere to being able to expose data over web service requests etc in future. Beeter to follow good practise from day 0 i suppose. Do you have any idea for my 3rd question (which i added only a few minute back). –  Sep 06 '09 at 14:02
0

We all know what Dtos are (probably). But the important thing is to overuse DTOs or not.

Transfering data using Dtos between "local" services is a good practice but have a huge overhead on your developer team.

There is some facts:

  1. Clients should not see or interact with Entities (Daos). So you always need Dtos for transferig data to/from remote (out of the process).
  2. Using Dtos to pass data between services is optional. If you don't plan to split up your project to microservices there is no need to do that. It will be just an overhead for you.

And this is my comment: If you plan to distribute your project to microservices in long future. or don't plan to do that, then DON'T OVERUSE DTOs

You need to read this article https://martinfowler.com/bliki/LocalDTO.html

Manoochehr Dadashi
  • 715
  • 1
  • 10
  • 28