When to use DTOs (Data Transfer Objects) in MVC4 A

2019-04-12 06:24发布

问题:

This question already has an answer here:

  • What is Data Transfer Object? 7 answers

I've read a lot about using patterns only when they're needed. I'm currently writing a pretty simple app that's implemented the repository and service patterns - I'm now debating whether or not to pass my domain objects to the view using DTOs. It's a single page application.

I started to create the DTO classes in my model but still can't understand what benefit they provide. It feels like I'm just duplicating everything for no reason.

When is it appropriate to use DTOs? At what point does it become necessary or beneficial? Any examples/samples would be awesome.

回答1:

I started to create the DTO classes in my model but still can't understand what benefit they provide.

Then it may very well be the case in this situation that they don't provide a benefit. Sticking with the simplest approach is always best, so you may be trying to unnecessarily add complexity.

I would say that DTOs are useful when you just need to pass around some flat data without needing complex domain objects. It seems to me that it would be preferable to bind your views directly to your business objects where possible. If nothing else, it provides a sanity check that your business objects are in line with your usage scenarios. Indeed, this is the approach advocated by the CSLA framework (among others) which focuses on the business objects.

The most common scenarios where I find myself translating domain objects into DTOs are:

  1. When I have an abstracted dependency on an external service (which itself doesn't align with my internal domain objects) and I want to make the service interface itself very simple. Rather than do all the translation within the service layer, I have the layer itself use DTOs and build a translation layer between the two.
  2. When I'm returning serialized objects to JavaScript via AJAX calls and don't want all the extra overhead of my domain objects going over the wire. Keeping the JavaScript itself simpler, not transmitting unnecessary data over the external network connection, etc.
  3. When I have a view which uses a composite of various domain objects' data, but not a superset thereof. In some cases this may indicate that this view represents a use case which merits its own domain object (possibly a composite of the other objects, or perhaps all of the objects involved should be composites of smaller non-aggregate-root objects, it depends), so be careful with this scenario. But sometimes just making an intermediary DTO keeps the code a little simpler and cleaner.

I think the key is in the translation from one shape of the data to another shape. If there's a lot of translation going on in a service, or a controller, or a view... then perhaps that translation is a large enough component to merit its own object. It's all about separation of concerns, really. A good rule of thumb is that if a piece of code is "re-shaping the data for some purpose and fulfilling that purpose" then that piece of code is doing two things. Might be better to break it apart into two pieces of code. The DTO is how those two communicate.

There are tools (such as AutoMapper) which can help with a lot of "scaffolding" code in translating between like-minded objects.