2

I want to architect my asp.net web form application like this :

1-DB
2-Data Access Layer(Using ORM[EF])
3-Repository/Unit Of Work (Pattern)
4-Business Layer
5-Service Layer
6-UI

Right now my primitive solution looks like this :

Just two class libraries :

  • DAL (Data Access Layer) where my EF resides in.
  • Domain Classes (auto generated) with their equivalent partial classes.

enter image description here


My questions concerning this design :

  1. 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 ?
  2. Could some one clarify what's the difference among those terminologies in the design perspective (POCO,Domain Class,BusinessClass)?
Anyname Donotcare
  • 11,113
  • 66
  • 219
  • 392

1 Answers1

3

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.

Community
  • 1
  • 1
Stephen Byrne
  • 7,400
  • 1
  • 31
  • 51
  • Great Answer , Really thanks a lot,still i have some confusion ,i will be grateful if you would help me .If I have some method like `GetEmployeeName()` and the implementation of this method in my code behind of some page right now .I want to refactor this code . My question is: Where this method belongs to ?(`Employee Domain Class` or `Employee Repository`) and if i put it in my domain class , i have to `add a reference of my repository to my Domain Classes` !! this will make `Circular dependency` – Anyname Donotcare Mar 01 '16 at 21:20
  • Well a method like `GetEmployeeName` sounds like it belongs on `Employee`; The EmployeeRepository shouldn't be a concern at this point at all because you should already have called this to get the Employee out of the database, and then you later on call this method to get the name (for whatever reason). Does that make sense? – Stephen Byrne Mar 01 '16 at 21:32
  • Make sense , but what about the circular dependency? I will have to add a reference of the `repository dll ` to` the the domain classes`!!.. – Anyname Donotcare Mar 01 '16 at 21:55
  • No, you don't need that - your service layer would have a reference to both, and it would drive the process of getting the `Employee` from the Repository, and then asking that `Employee` to execute `GetEmployeeName()`... – Stephen Byrne Mar 01 '16 at 21:57
  • Excuse me could u write code as an example to clarify this idea please ? – Anyname Donotcare Mar 01 '16 at 22:01
  • @AnynameDonotcare - I've updated with a code sample, I'm not sure if this clarifies or not. – Stephen Byrne Mar 01 '16 at 22:14
  • Really thanks a lot . One last question, should i create service class for each domain class to map the required behavior between these layers – Anyname Donotcare Mar 01 '16 at 22:22
  • 1
    Not necessarily; the service classes should be created based on the processes that you need to implement. So you should find yourself with Service classes that typically co-ordinate between 2 or more Domain Objects in order to achieve some "grander" result, if you see what I mean. But this might not always be the case; just as a rule of thumb, a 1:1 relationship between Service and Domain classes across the solution can indicate that your Domain classes have too many responsibilities, or that you don't really *need* Domain classes at all (see my second update) – Stephen Byrne Mar 02 '16 at 01:08
  • Thanks a lot .. And according to your answer i can use my service layer to coordinate between repositories and domain classes . – Anyname Donotcare Mar 02 '16 at 06:35
  • That's exactly what I meant, yes :) – Stephen Byrne Mar 02 '16 at 11:02