views:

324

answers:

6

I currently represent my Business Layer and Data Layer in a single project in my application. I have very good separation of concerns between the two sets of classes. However, My Data Layer classes take as parameters and return my business objects. So I will have code that loosely resembles (please don't be too critical of this code, my production code doesn't look much like this):

//business class fragment
public bool Save()
{
    if(this.IsValid)
    {
       //DataProvider is one of many data access classes that implement an IDataProvider interface.  Switched elsewhere in the class.  This allows switching of Database providers, xml, etc.
       DataProvider.Save(this);
       return true;
    }
    return false;
}

public List<MyBusinessObject> GetObjectsByCriteria(string criteria)
{
    return DataProvider.GetMyBusinessObjectsByCriteria(criteria);
}

I don't want my business classes to have to deal with DataSets any more than I like having my Data Layer classes deal with Business Classes.

I have read up a lot on Data Access Objects, or Data Transfer Objects to possibly solve this problem, but the this seems like an anti-pattern case for those patterns.

What can I do? How to I elegantly achieve complete separation of these two layers of my application?

+1  A: 

Pull the persistence logic out of your business objects and put them into a Data Adapter. It will work kind of like how the existing adapters in .NET work (OleDbDataAdapter). This way you will also separate your business objects and the persistence logic.

Your client's code will be a little more verbose, but I think that is really the best way to truly separate the layers.

Bob
This is what we do, but we also combine it with DTOs.
JP Alioto
+1  A: 

A popular pattern to do this is the Repository pattern. In this case the Repository acts as a facade using collection semantics, completely hiding where persisted data resides, whether that be a file system or database. You can implement it to access data, then map the data to whatever types you want to work with.

You might look into Domain Driven Design as an alternative to the Active Record pattern that it appears you are using.

jlembke
A: 

You should have a look at the DAO pattern (Data Access Object). http://en.wikipedia.org/wiki/Data_Access_Object

The best is, to use a ready DAO construct (spring loaded). Have a look at http://trac.synyx.org/hades

DAOs are not an antipattern! Use them with Spring and generics and you haven't to care ;)

There is everytime an connection between the layers! To seperate them completely means, that they have no availability to communicate (so they are useless).

Use the basic CRUD operations or dynamic finders whereever it makes semantic sense.

Martin K.
+1  A: 

This is a more general problem than just how to separate Domain Model from Data Access. The same problem occurs when you attempt to separate your Application Logic from your Domain model, your Presentation Model from Application Logic and so forth.

The common solution is a technique called Dependency Injection (DI). Some people also refer to it as Inversion of Control (IoC).

The seminal text on the subject was Martin Fowler's article Inversion of Control Containers and the Dependency Injection pattern, but we have come a long way since then, so be sure to examine some more recent texts as well.

You can implement DI manually, like described in this blog post, or you can let a DI Container (i.e. a framework) do the work for you.

Common DI Container are:

Mark Seemann
+1  A: 

I don't think you can have the two completely separated, but you can ensure that the dependency isn't bi-directional.

I think it's important to define a couple of things:

  1. model objects (e.g., Person, Address, Order, etc.)
  2. persistence layer (e.g., DAOs, repositories, etc.)
  3. service layer (interfaces whose methods map to use cases, know about units of work, etc.)
  4. web or view layer (controllers/pages for web apps, widgets for desktop).

The persistence, service, and view layers know about the model objects; the model objects are oblivious to the layer they're in.

The dependencies for the layers are unidirectional and flow back to front:

  • persistence->model
  • service->model, persistence
  • view->model, service

You unit test from back to front, because the dependencies make it easy to mock.

It's impossible to have NO dependencies, but you should design them so there are no cycles.

The only class with no dependencies is one that is called by no one and never calls another class. It's neither useful nor a worthwhile design goal.

duffymo
I do not see "good separation of concerns" on Nosredna's question. I think this post migth clarify some concepts and help. Nice post, duffymo!
Eduardo Xavier
A: 

n-tier desing: in the business logic layer you can make a data access class and a data manipulation class. always program to an interface.

see_sharp_guy