Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best way of using DTOs in a SOA application?

We are implementing a SOA web application using EF, WCF and jQuery.

Here is our architecture in a brief view:

-------------   ---
|    UI     |  |   |
-------------  |   |
| Services  |  | D |
-------------  | T |
| Businsess |  | O |
-------------  |   |
|    Dal    |  |   |
-------------   ---

We know that we should have DTO classes to pass data between the layers specially between the Services and the UI but We have some conceptual issues about the way of using DTOs (to send to the UI or receive from UI).

For Data-Driven project we can use POCO to generate the DTO objects automaticly. But in big applications it's not that simple.

We know two solutions to solve our issue:

First solution (using POCO besides the new manually created DTOs)

For example suppose that we have an entity with many fields. And there is a lookup combobox that shows the entity records. We need just an entity key as the combobox value field and another field (for example Title) as the combobox text field. So we create a method named "GetAllItemsTitle" to retrieve all entities. Now we should just return the structure which we want (A key and a value in this example). So we have to create a new class to store that structure (A key and a value) in it.

This will be the new DTO class:

[DataContract]
public class SampleManuallyDto
{
    [DataMember]
    public long Id { get; set; }

    [DataMember]
    public string Title { get; set; }
}

And the method signature is like this:

public List<SampleManuallyDto> GetAllItemsTitle()

Second solution (using Nullable or Emptyable DTOs)

We can bypass the POCO and create DTOs manually. Then we may define all properties of the DTO as nullable or something like that which could be recognized as Empty (I called it Emptyable). It allows us to use a DTO for several purposes. Ofcourse we need to follow the Adapter pattern. For example create two method for those Emptyable DTOs named "FromEntity" and "ToEntity" that converts our manually created DTOs to EntityObjects (of entity framework).

Now we can bypass the creation of a new DTO classes in the example of the "first solution" (GetAllItemsTitle).

The method signature will be like this:

public List<SampleDTO> GetAllItemsTitle()

But in the method body we just fill the "Id" and "Title" properties of the SampleDTO. As I said all properties of the SampleDTO can be empty so we just fill those we want and leave the others empty.

Conclusion

Generally, the first solution (using POCO besides the new manually created DTOs) is Strongy-Typed. It's simply possible to find out each method return data type by just looking at the method signature (there is no extra properties). But we are worry about managing manually created DTOs. They will grow up soon.

But the second solution is a more dynamic way and the only way to recognize what will be returned from the "GetAllItemsTitle" is looking at the method body or its documentation. So we are worry about "Runtime Errors". Developers may suppose that a property should not be empty while it is empty.

More over, the expressed example we faced to such issue when "Puting" data from UI to Services. For example for Update and Insert and other such action. Even about the "Search Criterias" we have the same choises.

Sorry for the long question. Please help us with your kindly advices.

like image 832
Amir Karimi Avatar asked May 05 '11 13:05

Amir Karimi


2 Answers

Forget all about the data layer. Create DTO:s that works for each specific web service call.

It's not important how the DTO is built or how it's used. The only thing that matters is how they are designed to minimize the amount of webservice calls for each operation.

For instance: Let's say that you have a use case where you need to traverse all users to to modify their addresses. A bad design would be if you first need to fetch all users and then make a webservice call for each user to fetch it's address. A proper design would be to return a list of UserWithAddress DTO:s in a single call.

like image 79
jgauffin Avatar answered Nov 28 '22 17:11

jgauffin


then how we manage the huge amount of DTOs of a large project? you mean we should have a DTO for every single combination of UserInfo, such as UserWithAddress, UserWithAddressAndAge, UserWithAge,UserWithPhoneNumber,UserWithBlahBlahBlah? This would be a mess in large domains and hard to manage and maintain. I really prefer the Nullable DTOs. You should have a single Dto for each object mapped from the real world. this is the business duty to specify how it should be used. once you create a Dto, then use it according to you business. Calling GetUserAddress service, and don't expect UserAge or any other thing. there is a single DTO for Users as we map the user to our Object Oriented User in our design.

and one more thing! if we create a Dto for our each single purpose and combination of data services receives, as a developer who is joined to support team recently, how can i find a desired Dto for my new method? i should search all Dtos and be careful of my right choices (what happens if i be a lazy and careless developer?) maybe i should read a doc book like "THE DTOS OF THE PROJECT!" to become familiar with available DTOs.

like image 37
Reza Owliaei Avatar answered Nov 28 '22 17:11

Reza Owliaei