2
votes

I'm developing N-Tier application in C#. Server side consists of this layers:

  • Data access layer (EF Code First Entities and DbContext)
  • Business layer (contains all business logic and objects)
  • WCF Service layer (per-call instanstiated services that expose some operations from business layer)

Now client requests are processed in this way:

  1. Client creates Request DTO and sends it to Service layer
  2. Service layer maps this DTO to business object and calls BL method
  3. Business layer does something useful, makes requests to DAL, and then returns some business object to service
  4. Service layer maps business object to DTO Response and returns to client

It works nice despite code duplication which is mitigated by Automapper. The actual problem is this:

Client shows same objects in different views: grid, form, etc. For example, grid(list) view requires only Id and Name from User object, while Form(details) view needs every User's property. But Business layer knows nothing about views. It can only provide full UserBL object to Service calls and then it's the Service responsibility to map this UserBL to UserListDto or UserDetailsDto. And for some heavy objects, fetching extra fields from DB become a performance issue.

So, should Business layer provide different methods for different client operations? I don't like this solution because it looks like domain logic polluting, but I don't know what else could be done.

1
Have you considered using some caching on the client? Especially if you are getting the same information from the service layer all over again. How volatile is this data?Darin Dimitrov

1 Answers

3
votes

Client shows same objects in different views: grid, form, etc. For example, grid(list) view requires only Id and Name from User object, while Form(details) view needs every User's property. But Business layer knows nothing about views. It can only provide full UserBL object to Service calls and then it's the Service responsibility to map this UserBL to UserListDto or UserDetailsDto. And for some heavy objects, fetching extra fields from DB become a performance issue.

I usually return different representations of a business entity depending of the type of action that is made in the BL. For instance when searching a return a search representation of user which just contains the minimal set of properties required to identity a user. When fetching a specific user I return a complete business object.

Regarding your issue with code duplication. It is not duplication. Those different representations of a user have different responsibilities.

  • DTO: Responsible of transferring a user and creating a loose coupling between the business layer and the consumer
  • BO: Responsible of encapsulating and performing business operations
  • DB entity: Responsible of making the BO object persistent ignorant

Thus if you would use only one representation of a user you would merge all those responsibilities and therefore have to do sacrifices in good design to be able to use it everyone. The only really gain is that you have to write a few lines less code. Keep that in mind when you start to maintain the released application. You saved a few lines, but got a lot harder application to maintain.