Question

I have clear understanding of what repository pattern is and its importance from TDD's standpoint. I also understand that how easy it can be to switch underlying data store for the application because Repository acts as a window to data access logic.

What I am NOT getting is how to support multiple data stores at a same time. Here's an example, assume that I have defined a repository IPersonRepository which has two implementations and the requirement is to read XML file and store into SQL database or vice-versa.

DataAccessLayer

public interface IPersonRepository  
{  
    Person GetPersonById(int id);  
}  

public class PersonRepositorySQL : IPersonRepository  
{  
    public Person GetPersonById(int id)  
    {  
        // get person from sql db (using ado.net)  
    }  
}  

public class PersonRepositoryXML : IPersonRepository  
{  
    public Person GetPersonById(int id)  
    {  
        // get person from xml file  
    }  
}  

BusinessLogicLayer

public PersonService   
{  
    private IPersonRepository personRepository;  

    public PersonService(IPersonRepository personRepository)  
    {  
        this.personRepository = personRepository;  
    }  

    public Person GetPersonById(int id)  
    {  
        personRepository.GetPersonById(id);  
    }  
}  

Questions (ordered by importance):

  1. Does this mean I have to instantiate two PersonService objects everytime for reading data from db and xml by passing PersonRepositorySQL and PersonRepositoryXML respectively?
  2. For doing above, I have to add reference to repositories in upper level (mostly presentation)? How can this be avoided?
  3. Is DAL good place to keep repositories?
  4. Is it OK to name a BLL class as Service ex: PersonService?

I realize that post has become very long but I wanted to put everything that's causing confusions in mind.

-- NV

Was it helpful?

Solution

Does this mean I have to instantiate two PersonService objects everytime for reading data from db and xml by passing PersonRepositorySQL and PersonRepositoryXML respectively?

No, but you're heading in the right direction. I would inject both repositories into the service (two constructor args) and write two service methods, one that moves data one way and another the other way.

It should be the responsibility of the service to connect the two repositories, rather than the client.

Then use an IoC container to setup and provide the service instance to clients, having New Services() all over the place is definitely not recommended. You'll need to look up the IoC tools/approach that works best for whatever presentation technology you're using.

For doing above, I have to add reference to repositories in upper level (mostly presentation)? How can this be avoided?

That's okay for presentation as it needs to know what to inject into the service instance, presentation is the only place you need to reference concrete DAL classes directly and for only that reason.

I found Googling for VS layered architecture project structure (or similar) helped me heaps back when I wasn't too sure.

Is DAL good place to keep repositories?

That's where they should be. Your DAL is generally for everything that touches hardware i.e. files, dbs, webapis.

Is it OK to name a BLL class as Service ex: PersonService?

Absolutely. It's short, sweet, and tells people (and other devs) what it is (a service) and what it's responsibilities are (people)

OTHER TIPS

Just to address question #1: instead of instantiating two services, you could instantiate one service and pass a Composite into it. For that you'd need a CompositeRepositoryFactory type that would create the appropriate Composite. Please note that a

A bit more about the Composite and your particular case:

  • It allows you to chain multiple implementations while the client maintains a reference to the original interface.
  • Allows you to chain multiple implementations of the same interface. This way, implementations cascade the method calls, allowing for a richer logic. On the other hand, the client maintains the desired dependency: only on the interface itself.
  • Composite pattern facilitates SRP principle: if your class is too extensive and has a large interface, you won’t be able to decorate it because: It will be difficult to precisely implement the decoration (since the class does too much).
  • On the figure below: client has a reference to CompositeComponent (via a IComponent reference variable). The CompositeComponent has a reference to another IComponent implementation (e.g. ConcreteComponent), some logic of its own within Something() and then as part of that logic – it calls the ConcreteComponent.Something(). This way the initial call to CompositeComponent.Something() cascades to ConcreteComponent.

Composite Repository diagram

  • I've also created a quick diagram of how the above figure might apply to your case: your client code will keep using PersonService, however instead of passing in some IPersonRepository implementation directly, you'd first go to the PersonCompositeRepositoryFactory. The only change necessary at the resolution root side would be the use of PersonCompositeRepositoryFactory

enter image description here

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top