I have a web client that calls my WCF business service layer, which in turn, calls external WCF services to get the actual data. Initially, I thought I would use DTOs and have separate business entities in the different layers... but I'm finding that the trivial examples advocating for DTOs, to be, well, trivial. I see too much duplicate code and not much benefit.
Consider my Domain:
Example Domain
I have a single UI screen (Asp.net MVC View) that shows a patient's list of medications, the adverse reactions (between medications), and any clinical conditions (like depression or hypertension) the patient may have. My domain model starts at the top level with:
MedicationRecord
List<MedicationProfile> MedicationProfiles
List<AdverseReactions> Reactions
List<ClinicalConditions> ClinicalConditions
MedicationProfile is itself a complex object
string Name
decimal Dosage
Practitioner prescriber
Practioner is itself a complex object
string FirstName
string LastName
PractionerType PractionerType
PractionerId Id
Address Address
etc.
Further, when making the WCF requests, we have a request/response object, e.g.
MedicationRecordResponse
MedicationRecord MedicationRecord
List<ClientMessage> Messages
QueryStatus Status
and again, these other objects are complex objects
(and further, complicates matter is that they exist in a different, common shared namespace)
At this point, my inclination is that the MedicationRecordResponse is my DTO. But in pure DataContracts and DTO and separation of design, am I suppose to do this?
MedicationRecordResponseDto
MedicationRecordDto
List<ClientMessageDto>
QueryStatusDto
and that would mean I then need to do
MedicationProfileDto
PractitionerDto
PractitionerTypeDto
AddressDto
etc.
Because I have show almost all the information on the screen, I am effectively creating 1 DTO for each domain object I have.
My question is -- what would you do? Would you go ahead and create all these DTOs? Or would you just share your domain model in a separate assembly?
Here's some reading from other questions that seemed relevant:
- WCF contract know the domain
- Alternatives for Translation Layer in SOA: WCF
- SOA Question: Exposing Entities
Take a look on excellent articles
- Why You Shouldn’t Expose Your Entities Through Your Services
- DTO’s Should Transfer Data, Not Entities
above links don't work, looks like a domain issue (I hope it'll be fix), here is the source:
- DTO’s Should Transfer Data, Not Entities
- Why You Shouldn’t Expose Your Entities Through Your Services
I've always had an aversion to the duplicate class hierarchy resulting from DTOs. It seems to be a flagrant violation of the DRY principle. However, upon closer examination, the DTO and the corresponding entity or entities serve different roles. If you are indeed applying domain-driven design then your domain entities consist of not only data but behavior. By contrast, DTOs only carry data and serve as an adapter between your domain and WCF. All of this makes even more sense in the context of a hexagonal architecture also called ports and adapters as well as the onion architecture. Your domain is at the core and WCF is a port which exposes your domain externally. A DTO is part of how WCF functions and if you agree that it is a necessary evil your problem shifts from attempting to eliminate them to embracing them and instead focusing on how to facilitate the mapping between DTOs and domain objects. A popular solution is AutoMapper which reduces the amount of boiler plate mapping code you need to write. Aside from the drawbacks, DTOs also bring a lot of benefits. One is that they furnish a buffer between your domain entities and the outside world. This can be of great help in refactoring because you can keep your core domain very well encapsulated. Another benefit is that you can design your DTOs such that they fulfill requirements of the service consumer, requirements which may not always be in full alignment with the shape of your domain objects.
Personally, I don’t like using MessageContract as entities. Unfortunately, I have an existing WCF service that use MessageContract as entities – i.e. data is filled into the MessageContract directly in the data access layer. There is no translation layer involved.
I have an existing C# console application client using this service. Now, I have a new requirement. I need to add a new field in the entity. This is not needed by the client. The new field is only for the internal calculations in the service. I had to add a new property named “LDAPUserID” in the MessageContract which also act as a entity.
This may or may not break the client depending on whether the client support Lax Versioning
. Refer Service Versioning.
It is easy to mistakenly believe that adding a new member will not break existing clients. If you are unsure that all clients can handle lax versioning, the recommendation is to use the strict versioning guidelines and treat data contracts as immutable.
With this experience, I believe it is not good to use MessageContract as entities.
Also, refer MSDN - Service Layer Guidelines
Design transformation objects that translate between business entities and data contracts.
References:
- How do I serialize all properties of an NHibernate-mapped object?
- Expose object from class library using WCF
- Serialize subset of properties only