Should I put my business logic in a new layer or just in the domain classes layer where each business belong to the related domain class Or put my business logic in the code behind of my web pages ?
- Your business logic should be only in your domain/business classes, and nowhere else; otherwise you run the risk of having an Anemic Domain Model and this is generally a bad idea in the long run. (interesting viewing here)
- Your service layer should serve only as a point of orchestration between business objects i.e. it implements process flows, whereas your business objects implement the individual steps of a process.
Example
So you might have an OrderService
class, that lives in the Service Layer, which has method PlaceOrder
and which drives a process to check the status of the Customer
class (a business object), save the Order
(a business class) to the data store (possibly via your Repository layer), and queue an email confirmation for the customer. (possibly via another Service)
(Note that's a very simple example which doesn't necessarily claim to be the best process flow for your specific scenario)
Could some one clarify what's the difference among those terminologies in the design perspective (POCO,Domain Class,BusinessClass)?
- For most intents and purposes, there is practically no difference between "Domain" and "Business" Objects.
- Both exist to model a solution to a business domain - the only difference tends to be that if you have followed a strong Domain-Driven design approach, you'll tend to refer to these classes as "Domain Objects".
- But otherwise, you can consider them the same thing - they encapsulate the behaviour and data required to solve your business problems.
POCO is not DTO
POCO means "Plain Old CLR Object" and it basically means an instance of a class that has no dependency on any external framework in the forms of attributes or inheritance from said frameworks.
So for example if you're not using EF Code First, then your EF model classes will typically be decorated with attributes that EF itself uses at runtime to know what property is a Primary Key, and so on.
By using EF Code First, you can avoid this and have pure POCOs in your code.
POCO and DTO are often conflated; they are not the same at all!
A DTO is a class whose sole purpose is to transfer data between boundaries (layers, processes, etc.) and as such is typically just a bunch of read/write public fields or properties with no business behaviour. It's barely deserving of the "Object" classification.
A POCO on the other hand can have both data and behaviour, just like and proper Object, and is the ideal archetype for Domain (or Business, if you will) classes.
Some thoughts
I also wanted to point out a couple of other things related to your proposed design.
- First, if you are using EF, you do not really need a separate Unit of Work, since
DbContext
already encapsulates a Unit of work pattern for you.
- Consider if you really need "layers" at all; for example unless your application is a very simple CRUD application, you might benefit more from using Command/Query patterns whereby instead of designing your architecture as a shallow series of wide layers which can lead to inflexible structure, you instead use thin vertical slices of code that are feature-oriented, which means they can be as shallow or deep as they need to be, leading to a more cohesive design that's easier to adapt. Interesting viewing on this here
- My honest advice if you are using Entity Framework is to use Code First; it's much more flexible than the classic
.edmx
model way.
- Also, it's OK to embrace EF and let it percolate all the way up to your service layer...and then DTOs come into play to transform these objects into transport buckets which your web controllers can emit. (for example using Automapper). Some interesting perspective on EF and Business Objects here **
- I know this probably flies in the face of a lot of the typical "Persistance Ignorance" advice but in my experience, it's rarely a problem (unless you find yourself switching database providers every other week!).
The benefits you will gain by using EF Code First and embracing DbContext include
-True POCO Domain/Business Objects (you can declare your BOs in a separate assembly so that they enjoy persistance ignorance, yet can also be mapped against EF separately in another assembly such as your Data Access Layer)
-Simplified codebase that doesn't do pointless mappings between layers
**I just realised that all of my references are for works by the same person. He's not paying me to do this, I swear :)
Update
Based on the OP's comments in terms of the perceived problem of circular dependency, here's an example code for one specific scenario (the use case is a bit unfunctional, just illustrative)
public class EmployeeNameService
{
readonly IEmployeeRepository _repo;
public EmployeeNameService(IEmployeeRepsitory repo)
{
_repo=repo;
}
public string GetEmployeeName(int empID)
{
var emp = _repo.GetByID(empID);
var name = emp.GetEmployeeName();//does some crazy logic based on the Employee state or whatever.
return name;
}
}
Now the point of the above is that the EmployeeNameService
resides in the Service "layer" which has a dependency (reference) to both the Repository Layer and the Domain Object "layer" (which is not really a layer, just a separate project containing the Domain / Business classes). So there is no worry about circular dependencies.
Of course the Repository will have a reference to the Domain Objects, which is fine since it's a one-way dependency.
Update 2
One thing I didn't mention previously was when NOT to follow the advice above; if you have a very simple CRUD model whereby you are taking user input and just passing it down to a data store without any "business logic" in between, then just stick with simple layers as originally planned. However as soon as there is any business logic at all, then consider using the above concepts.