views:

257

answers:

2

I'm using a basic 3-tier design. For flexibility (and testing) purposes, I wanted the data layer to be abstract and specify the concrete class in my code. But, how should I pass this along to my business objects. Here's an example (pseudo code):

abstract class IDataLayer
{
    PersonData GetPerson(int); //PersonData would be a row of data from a table for example
    JobData[] GetJobs(int);
    void UpdatePerson(PersonData);
}

class ConcreteDataLayerSQL : IDataLayer
{
...
}
class ConcreteDataLayerXML : IDataLayer
{
...
}

class PersonBAL
{
    void PersonBAL(personId)
    {
        //What goes here?
    }

    JobBAL[] GetJobs()
    {
       //What goes here?
    }
}
class Program
{
    static void Main()
    {
        person = new PersonBAL(1);
    }
}

So the problem is, how does PersonBAL know which ConcreteDataLayer to use? I'm thinking between a few options:

1: pass the concrete data layer to person. This becomes a pain when you start adding new classes that need to interact with the data layer (something like new PersonBAL(IDataLayer, int), then new JobBAL(IDataLayer, int), etc etc)

2: Create a static object that holds which data layer to use (Read: global variable)

Any other ideas?

+1  A: 

The problem you're trying to solve is "dependency injection".

Assuming that this is .NET code (your psuedo-code language looks a lot like C#), you might want to look into a framework like Spring.NET that is designed for this kind of thing.

Licky Lindsay
While I appreciate the clarification on the term, I'd like a better solution than to get a framework to handle the problem. How does the framework handle the problem?
Jon
A: 

I think passing the class in each constructor would be challenging for the reason you listed and because changing the code to use a different class would be an error-prone chore.

Dependency Injection is at the core of the Spring framework. Spring uses XML configuration files to describe the relationships between classes. For your use case, you can specify the specific type you want to instantiate in the configuration, so you only have to make one change to switch implementations.

Spring is a well-known and tested framework, but of course you don't need it to resolve the problem. You could very well write you own code for configuration files. Either way, this is essentially a variation on the second option you mentioned.

alexsome