Should services always return DTOs, or can they al

2020-01-24 18:44发布

I'm (re)designing large-scale application, we use multi-layer architecture based on DDD.

We have MVC with data layer (implementation of repositories), domain layer (definition of domain model and interfaces - repositories, services, unit of work), service layer (implementation of services). So far, we use domain models (mostly entities) accross all layers, and we use DTOs only as view models (in controller, service returns domain model(s) and controller creates view model, which is passed to the view).

I'v read countless articles about using, not using, mapping and passing DTOs. I understand that there's no any definitive answer, but I'm not sure if it's ok or not returning domain models from services to controllers. If I return domain model, it's still never passed to the view, since controller always creates view-specific view model - in this case, it seem legit. On the other hand, it doesn't feel right when domain model leaves business layer (service layer). Sometimes service needs to return data object that wasn't defined in the domain and then we either have to add new object to the domain that isn't mapped, or create POCO object (this is ugly, since some services return domain models, some effectively return DTOs).

The question is - if we strictly use view models, is it ok to return domain models all the way to controllers, or should we always use DTOs for communication with service layer? If so, is it ok to adjust domain models based on what services need? (Frankly I don't think so, since services should consume what domain has.) If we should strictly stick to DTOs, should they be defined in service layer? (I think so.) Sometimes it's clear that we should use DTOs (e.g., when service performs lot of business logic and creates new objects), sometimes it's clear that we should use just domain models (e.g., when Membership service returns anemic User(s) - it seems it wouldn't make much sense to create DTO that is the same as domain model) - but I prefer consistency and good practices.

Article Domain vs DTO vs ViewModel - How and When to use them? (and also some other articles) is very similar to my problem, but it doesn't answer this question(s). Article Should I implement DTOs in repository pattern with EF? is also similar, but it doesn't deal with DDD.

Disclaimer: I don't intend to use any design pattern only because it exists and is fancy, on the other hand, I'd like to use good design patterns and practices also because it helps designing the application as a whole, helps with separation of concerns, even tohugh using particular pattern isn't "necessary", at least at the moment.

As always, thank you.

9条回答
霸刀☆藐视天下
2楼-- · 2020-01-24 18:52

If you return part of your domain model, it becomes part of a contract. A contract is hard to change, as things outside of your context depend on it. As such, you would be making part of your domain model hard to change.

A very important aspect of a domain model is that it is easy to change. This makes us flexible to the domain's changing requirements.

查看更多
Luminary・发光体
3楼-- · 2020-01-24 18:53

So far, we use domain models (mostly entities) across all layers, and we use DTOs only as view models (in controller, service returns domain model(s) and controller creates view model, which is passed to the view).

Since Domain Model provides terminology (Ubiquitous Language) for whole your application it is better to use Domain Model widely.

The only reason to use ViewModels/DTOs is an implementation of MVC pattern in your application to separate View (any kind of presentation layer) and Model (Domain Model). In this case your presentation and domain model are loosely coupled.

Sometimes service needs to return data object that wasn't defined in the domain and then we either have to add new object to the domain that isn't mapped, or create POCO object (this is ugly, since some services return domain models, some effectively return DTOs).

I assume that you talk about Application/Business/Domain Logic services.

I suggest you return domain entities when you can. If it is needed to return additional information it is acceptable to return DTO that holds several domain entities.

Sometimes, people who use 3rd part frameworks, that generates proxies over domain entities, face difficulties exposing domain entities from their services but it is only a matter of wrong usage.

The question is - if we strictly use view models, is it ok to return domain models all the way to controllers, or should we always use DTOs for communication with service layer?

I would say it is enough to return domain entities in 99,9% cases.

In order to simplify creation of DTOs and mapping your domain entities into them you can use AutoMapper.

查看更多
老娘就宠你
4楼-- · 2020-01-24 19:04

It seems that your application is big and complex enough as you have decided to go through DDD approach. Don't return your poco entities or so called domain entities and value objects in you service layer. If you want to do this then delete your service layer because you don't need it anymore! View Model or Data transfer objects should live in Service layer because they should map to domain model members and vice versa. So why do you need to have DTO? In complex application with lots of scenarios you should separate the concerns of domain and you presentation views, a domain model could be divided into several DTO and also several Domain models could be collapsed into a DTO. So it's better to create your DTO in layered architecture even it would be the same as your model.

Should we always use DTOs for communication with service layer? Yes, you have to return DTO by your service layer as you have talk to your repository in service layer with domain model members and map them to DTO and return to the MVC controller and vice versa.

Is it ok to adjust domain models based on what services need? A service just talks to repository and domain methods and domain services, you should solve the business in your domain based on your needs and it's not the service task to tell the domain what is needed.

If we should strictly stick to DTOs, should they be defined in service layer? Yes try to have DTO or ViewModel just in service later because they should be mapped to domain members in service layer and it's not a good idea to places DTO in controllers of your application(try to use Request Response pattern in your Service layer), cheers!

查看更多
Animai°情兽
5楼-- · 2020-01-24 19:08

In my experience, unless you are using an OO UI pattern (like naked objects), exposing the domain objects to the UI is a bad idea. This because as the application grows, the needs from the UI change and force your objects to accommodate those changes. You end up serving 2 masters: UI and DOMAIN which is a very painful experience. Believe me, you don't want to be there. The UI model has the function of communicating with the user, the DOMAIN model to hold the business rules and the persistence models deals with storing data effectively. They all address different needs of the application. I'm in the middle of writing a blog post about this, will add it when it's done.

查看更多
地球回转人心会变
6楼-- · 2020-01-24 19:10

I'd suggest analyzing these two questions:

  1. Are your upper layers (i.e. view & view models / controllers) consuming the data in a different way of what the domain layer exposes? If there is a lot of mapping being done or even logic involved I'll suggest revisiting your design: it should probably be closer to how the data is actually used.

  2. How likely is it that you deeply change your upper layers? (e.g. swapping ASP.NET for WPF). If this is highly unlike and your architecture is not very complex, you may be better off exposing as many domain entities as you can.

I'm afraid it is quite a broad topic and it really gets down to how complex your system is and its requirements.

查看更多
劳资没心,怎么记你
7楼-- · 2020-01-24 19:12

In my experience you should do what's practical. "The best design is the simplest design that works" - Einstein. With that is mind...

if we strictly use view models, is it ok to return domain models all the way to controllers, or should we always use DTOs for communication with service layer?

Absolutely it's ok! If you have Domain Entities, DTO's and View Models then including database tables you have all the fields in the application repeated in 4 places. I've worked on large projects where Domain Entities and View Models worked just fine. The only expception to this is if the application is distributed and the service layer resides on another server in which case DTOs are required to send across the wire for serialization reasons.

If so, is it ok to adjust domain models based on what services need? (Frankly I don't think so, since services should consume what domain has.)

Generally I'd agree and say no because the Domain model is typically a reflection of the business logic and doesn't usually get shaped by the consumer of that logic.

If we should strictly stick to DTOs, should they be defined in service layer? (I think so.)

If you decide to use them I'd agree and say yes the Service layer is the perfect place as it's returning the DTOs at the end of the day.

Good luck!

查看更多
登录 后发表回答