The problem
public Person AddPerson(string name, string lastName, string email)
public Person AddWorker(string name, string lastName, string email) public Person AddCustomer(string name, string lastName, string email)
The Good
public Worker AddWorker(Worker worker) public Customer AddCustomer(Customer customer)
One very simple reason is that the objects generated by these frameworks usually are not serialization friendly, because they are on top of proxy classes which are a pain to serialize for something that outputs JSON or XML. Another potential problem is when your entity doesn’t quite fit the response you want to give, what happens if your service has something like this?
public Salary CalculateWorkerSalary(Worker worker)
You could have a very simple method just returning a double, but let’s think of a more convoluted solution to illustrate the point, imagine salary being like this:
public class Salary { public double FinalSalary {get;} public double TaxDeducted {get;} public double Overtime {get;} }
So, this is our class, and Overtime means it’s coupled to a user because not everybody does the same amount of overtime. So, what happens now if we also need the Tax code for that salary? Or the overtime rate for the calculation? That is assuming these are not stored on the salary table. More importantly, what happens if we don’t want whoever is calling the API to see the Overtime the Worker is doing? Well, the entity is not fit for purpose and we need a DTO where we can put all of these, simple as that.
The Bad
However, DTOs are not all glory, there is a problem with them and it’s the fact they bloat your application, especially if you have a large application with many entities. If that’s the case, it’s up to you to decide when a DTO is worth it and when it’s not, like many things on software design, there is no rule of thumb and it’s very easy to get it wrong. But for most of things where you pass complex data, you should be using DTOs.
The Ugly
There is another problem with DTOs, and it’s the fact you end up having a lot of code like this:
var query = _workerRepository.GetAll(); var workers = query.Select(ConvertWorkerDTO).ToList(); return workers;
Where ConvertWorkerDTO is just a method looking pretty much like this:
public WorkerDTO ConvertWorkerDTO(Worker worker) { return new WorkerDTO() { Name = worker.Name, LastName = worker.LastName, Email = worker.Email }; }
Wouldn’t be cool if you could do something without a mapping method, like this:
var query = _workerRepository.GetAll(); var workers = query.Select(x => Worker.BuildFromEntity<Worker, WorkerDTO>(x)) .ToList(); return workers;
Happily, there is a simple way to achieve a result like this one, and it’s combining two very powerful tools, inheritance and reflection. Just have a BaseDTO class that all of your DTOs inherit from and make a method like that one, that manages the conversion by performing a mapping property to property. A fairly simple, yet fully working, version could be this:
public static TDTO BuildFromEntity<TEntity, TDTO>(TEntity entity) { var dto = Activator.CreateInstance<TDTO>(); var dtoProperties = typeof (TDTO).GetProperties(); var entityProperties = typeof (TEntity).GetProperties(); foreach (var property in dtoProperties) { if (!property.CanWrite) continue; var entityProp = entityProperties.FirstOrDefault(x => x.Name == property.Name && x.PropertyType == property.PropertyType); if (entityProp == null) continue; if (!property.PropertyType.IsAssignableFrom(entityProp.PropertyType)) continue; var propertyValue = entityProp.GetValue(entity, new object[] {}); property.SetValue(dto, propertyValue, new object[]{}); } return dto; }
And Finally…
What’s your view on this? Do you agree? Disagree? Share what you think on the comments!
EDIT: As a side note, it’s work checking this article that talks a lot about the subject.