How to avoid redundant business logic (DB fetching) when creating DTO? - c#

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:
Client creates Request DTO and sends it to Service layer
Service layer maps this DTO to business object and calls BL method
Business layer does something useful, makes requests to DAL, and then returns some business object to service
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.

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.

Related

Three Tier Application

In a 1 tier application i.e Mvc, you get a folder called models and you build and store your classes in there, I'm aware when it comes to a three tier application from what I have read it seems correct to store the models inside the business layer (2nd tier), and from the UI (first tier) I would add a project reference to the 2nd tier which will allow me to use the models and make calls to methods.
From the second tiers perspective it would call the data layer (third tier) and perform crud operations against the database, but the data layer would require the models from the business layer so when I try to add a project reference from data layer to business layer i get the error
A Reference to "Business Layer" could not be added, adding this project as a reference would cause a circular dependency
Which I understand as a reference has already been made via business layer to data layer
How would I get around this? do I create additional models in the data layer and populate them with results from the database and pass that back to the business layer which then passes it back up to the UI? I'm slightly confused on this.
** Update **
From what I have read for the data layer to reference models inside the Business layer I would need to do model mapping, My model mapping will be quite large so I'm thinking of including a 4th tier which will be a shared library and that will consist of all the models that way the data layer and the business layer can access the models as and when is required.
A little off topic but ...
Depending on the size of your application, there may be no reason to introduce unnecessary complexities to try and follow pattern you may not necessarily understand. Doing so, will cause you extra headache.
That being said, if your project is of a large size and requires some good organizing, I would strongly suggest more research and maybe a few sample project in where you try out the architecture you came up with. No way you'll get it right the first time.
I would personally suggest looking into "onion architecture" instead of "n-tier", and of course you'll find many different views on it. You'll have to make your own decisions.
Here's a generic set-up I would start off with.
Core. It knows about no other project. This is where your classes with your "business" go. Such as Customer, Product, Order, etc.
Data. It knows about Core. It is responsible for taking in a Core object and storing it somewhere. That is all.
Service. It knows about Core AND Data. It's job is to expose methods such as "Create Customer", it will be responsible for creating a customer and storing it.
Web / Api / Mvc. This will know about Service. It's job is to expose your service to the user. (UI and such). (It may also know about Core / Data ... but that's a larger discussion.)
You're on the right track but I find it easier to think of the model layer as the data (third tier), the controller (business layer, second tier) manages the flow of the data between the ui (first tier) and the data layer.
If you modify your architecture this way, you should get rid of the circular references.
This also allows you to map your data layer objects to the appropriate less/more complex structures of the middle tier in a way which simplifies the interface shown to the UI and encapsulates the business logic there too.

Transferring data between layers of an application

If I have a C# application with a 5 layer architecture, much like what is presented here http://msdn.microsoft.com/en-us/library/ee658109.aspx, and I take the strict interaction approach of allowing a layer to only interact with the layer below, I am running into trouble when getting data in my Data layer and passing that data back up to my Business layer.
For example, if I have a business object called MyObject that is defined in my Business layer, but information needed to construct an object of type MyObject is retrieved from the database in the Data layer, my Business layer needs a reference to my Data layer in order to interact with the database. But, my Data layer then also needs a reference to the Business layer, since that is where the MyObject definition lives and the Data layer needs to construct an object of that type from the database results and give that data back to the Business layer. Now we have a circular dependency between the Business layer and the Data layer.
I am wondering what the proper approach is to solve this problem.
I have thought about using DTO objects defined in my Data layer to pass information back to the Business layer. This would work since the Business layer is able to interact with the Data layer, but not vice versa. It just seems like this might be an awful lot of duplicate code to basically mimic the business object definitions in the Data layer.
I also thought about creating interfaces for all of my business objects and putting those interfaces into a separate project that both the Business layer and Data layer can interact with. That way, I can pass instances of the interface and the only common reference between the Business layer and Data layer is the project where the interfaces are defined. I don't see many implementations of this either.
I am wondering what others have done to solve this problem.
Sounds like you would benefit from AutoMapper.
https://github.com/AutoMapper/AutoMapper/wiki/Getting-started
Each layer of your application should have it's own "version of the truth." The data layer has POCOs that are shaped based on the storage format of the data. Then your interface between data and business layers should take those data POCOs and map them into business POCOs. Rinse and repeat for the business/ui boundary or any other layers you may have.
The shape of the data that describes an object best in one layer shouldn't dictate how another layer can best describe an object. (i.e. The data layer might need foreign key ids, but the view can do just fine with an in-memory reference.)
If you need to construct the data on the Data side, then define the type in the data access layer. If the object is constructed in the DL, then that's where the type belongs. This allows you to avoid the circular reference. Just reference the Data project in the business layer project, and you have access to the type.
Another solution is to return raw results from the data access layer, and construct the object in the Business layer from the raw results.

Data Trasfer Objects Between Layers in Domain Driven Design

Domain layers are communicating the other layers via Data Transfer Objects(DTOs). I confused about DTOs.
DTO 1 is between Domain and Presentation Layer.
DTO 2 is between Domain and Data Layer.
Should I create two different DTO objects between layers or only one DTO. Which is the proffesional way?
Lets go through all your layers:
Data Access Layer (DAL). It is used in order to get data from database (DB).
Usually it knows about Domain Entities and Domain Layer.
The DAL can return either Domain Entities or DTOs (DB oriented data structures). These DTOs or Domain Entities can be used in order to build DTOs of Presentation Layer (view models) if it is needed.
Domain Entities usually are heavy and require data mappers or any ORM. I prefer working with Domain Entities, map them and avoid other DTOs. Otherwise DTOs should be mapped also.
Domain Layer (Domain model). It is used in order to represent Business entities and their behaviour, business rules, pure business logic.
Domain Layer should know nothing about the way the entities are stored somewhere (e.g. in DB). It can have its own DTOs which can be results of refactoring Introduce Parameter Object.
Presentation Layer (UI). It is used in order to present UI to users.
It should know about Data Access Layer to load data from DB and about Domain Layer to have access to its business logic.
It can have its own DTOs - view models, which are user interface friendly representation of Domain Entities or DB friendly DTOs. It is responsibility of Presentation Layer to know about view models.
If you are going to have only one presentation your Application Infrastructure can be implemented as part of presentation layer also, but usually it is a separate Application Layer.
It really depends on your your specific needs.
In a general sense, you should create 2 sets of DTO's. This allows for better de-coupling of different layers and makes the architecture of your system more flexible. The specific reasons or cases where it is needed are for example:
Sharing DTO's may not be possible, e.g. because there are differences in technologies used, e.g. a web service and data layer are written in C# and the presentation layer is written in Java.
DTO's are not necessarily the same, i.e. your DTO for the interaction with the database layer may be modelled on the database structure but you may expose it differently to the presentation layer.
Having said that, if you can live with the limitations of having one set of DTO's, you can share them if it suits your needs as it produces less code to write and maintain.
Your image shows two DTO object named DTO1 and DTO2.
DTO1 is sharing data between presentation layer and domian layer. You can call them as ViewModel classes.
DTO2 is sharing data between domain and data layer. You can call them as Data Transfer Objects (DTOs).
So You can use two different transfer objects.
If we assume that you use two separated DTOs (DTO1 and DTO2),
answer is simple:
You must create two separate DTO in this case: DTO1 and DTO2.
Even if they are identical, they should be implemented as separated classes.
It is because DTO1 is created in Domain Layer but DTO2 is created in Data Layer (according to yor picture).
Note that in some solutions, two DTOs are not used - sometimes, there is only one DTO.

Layer design in an application

I have been writing applications which are layered as:
DB<->DAL<->BL<->Service<->Presentation
And that's all that get's referenced. That is, The Presentation doesn't have a reference to the DAL.
We have a new app to write for a client, and the client is proposing something that is foreign to me. That is, the WRITE flow goes through the SL, but to READ data from the database, the want us to have a linq query in the presentation, direct to the DAL. That seems strange, but I am being told that my way is old fashioned and that my way, and their proposed way is essentially the same thing.
Also, my business logic usually resides in the BL, which is a separate project. But the client wants the business logic to be in the DTO object's themselves.
Is this normal? Is this basically Domain Driven Development or something? I find it strange that the linq calls to get the data for a form, is in the presentation layer, as opposed to my idea of a service layer method:
public MyPersonObject GetPersonByPersonId(int personId)
And then the same method in the Business, which might apply some rules to what is got, and then the same method in the DAL, which has the Linq.
Client is client, did you ever hear CQRS?
Your client might be affected by CQRS which is a new architecture fashion in domain driven design. In general, it separates command and query in different ways to database.
But in your client's proposed approach, it seems mixed up between traditional DDD and CQRS which does not use event sourcing inside. But it is still okay and normal, IMHO, query which provides data for presentation layer is trivial and it is not essentially complicated. It is like the report system which just queries data from database, you don't need to use ORM for this.
Also, my business logic usually resides in the BL, which is a separate project. But the client wants the business logic to be in the DTO object's themselves.
Business logic should be in domain entity, if not, seem you are violating Anemic Model anti pattern, it is also not in DTO. DTO is the concept of data transfer object between distribution layer with consumer.
What you describe is in no way DDD. While some DDD implementations do use a split architecture for queries and commands (CQRS approach), it doesn't remove the need for good layering of your application.
If writes go through a Service layer, it probably means that your software is at least of reasonable complexity and as such, should decouple presentation from persistence with a layer of abstraction in between. In CQRS, that layer often takes the form of Facades that accept queries and return DTO's containing the required data.
But the client wants the business logic to be in the DTO object's
themselves.
DTO stands for Data Transfer Object. DTO's don't contain any business logic and have no other purpose but to carry data.

n-Tier Architecture Feedback Needed

I started my website, like stackoverflow, with a little technical debt that I'm trying to pay off. Being a contract developer, I've been in many places and see many different methods of achieving this result, but the way I'm going is..
Presentation (web)
Business Layer (old fashioned entity classes and BL layer)
Data Layer (DA classes to SQL Server via Stored Proc)
My question primarily concerns the Business Layer. Right now I have an Entity namespace and a BusinessLogic namespace.
The BL has a reference to the DA and the Entity.
The Entity has a reference to the DA
(The DA is "unaware" of the BL or Entity)
I really want all my churning of turning Data into Entities to occur within the BL -- thus the Business Logic. However, I want the Entity to be able to access the BL if need be -- and thus remove the Entity's reference to the DL.
So...
Is is "wrong" to have the BL and Entity objects within the same namespace so they can work together?
Essentially, I'm trying have an entity object like Employee (classic example, eh?) and have the Employee have a
public Hashtable[] SubordinateEmployees
property that returns a Hashtable of other Employee objects that report to this employee. But I don't want to load it until it's needed. So for most employees the property would never get accessed, but when it does, it self-loads with a call to the BL, which calls the DA.
Does the question make sense?
If so, does my solution?
Thanks so much in advance!
The usual way to deal with the kind of situation your example represents is with facades. Instead of trying to get the subordinate employees from the Employee object, you use a call to the business logic to get it.
hashtable = BL.GetSubordinateEmployees(supervisor);
That way you have a single point of access to the subordinates, and there is only one thing (the BL) accessing the data layer and creating Entities.
Let me see if I can show you a better way to think about this
you have your data access (sql server, mysql, flat xml files, etc.) all of this should be abstracted away nothing else in your application should care or know how you are getting your data, only that it dose, if anything else knows how you are getting your data you have a layer violation. if the DAL dose anything other then get data you have a layer violation. Next you implement a data access interface something like IDAL that your business layer uses, this is very important for making your code testable by forcing you to separate your layers.
Your data entities can be placed in the DAL name space or give them there own, Giving them there own forces separation. Data entities are dumb objects and should contain very little to no logic and are only aware of themselves and the data they have, THEY DO NOT CONTAIN BUSINESS LOGIC!, DATA ACCESS LOCIC, OR UI LOGIC. if they do you have a layer violation. The only function of a data entity is to hold data and be passed from one layer to the next.
Biz layer implements a data access interface like the IDAL we talked about before you can instantiate this with a factory, an IOC container, or all else failing a concrete type, but add a setter property so this can be changed for testing. The Biz Layer Only handles Business logic, it doesn't know or care where the data came from or where it's going, it only cares about manipulating the data to comply with business rules, this would include date validation, filtering (part of this is telling the DAL what data it needs, let the DAL figure out how to get it). Basically the BIZ handles all logic that isn't UI related or Data retrieval related. Just like the DAL the Biz should implement an Interface for the same reason.
The UI layer Accesses the Biz layer the same way the Biz layer accesses the DAL for the same reason. All the UI layer cares about is displaying data and getting data from the user. The IU Layer should not know anything about the business rules, with the possible exception of data validation required to populate the Data Entities.
The advantage of this architecture is it forces separation of concern making it easier to test, more flexible, and easier to maintain. Today you are building a web site but tomorrow you want to allow others to integrate vi a web service, all you have to do is create a web service that implements the IBIZ interface and your done, when you have to fix a bug in the BIZ layer, it's already fixed in both your website and web service.
Taking this to the next level, lets say you are doing a lot of heavy number crunching and you need more powerful servers to handle this so all you have to do is implement an IDal and IBIZ interface that are really wrappers to WCF that handles the communication between your servers, now your application is distributed between multiple server and you didn't have to change your code to do it.

Categories

Resources