In an application that has followed a Domain Driven Design where you have the following sorts of concepts
- A repository that deals with the DataBase access
- A application service that co-ordinates interactions between enties and value objects etc.
where in general would you put caching code to elimenate an expensive call to the database?
I have seen code bases that just cache all over the place and it is difficult to monitor memory usage and difficult to provide guidelines to other developers.
Please understand that I know you should only cache data when you need to, I am just asking a general question.
The wonderful thing about abstract Repositories is that you can use the Decorator pattern to implement such cross-cutting concerns as caching.
As an example, given an IMyRepository interface, you can create a MyCachingRepository like this pseudo code:
public class MyCachingRepository : IMyRepository
{
private readonly IMyRepository repository;
public MyCachingRepository(IMyRepository repository)
{
if(repository == null)
{
throw new ArgumentNullException("repository");
}
this.repository = repository;
}
public Foo SelectFoo(int id)
{
Foo foo = ... // attempt to get foo from cache
if // foo is not it cache
{
foo = this.repository.SelectFoo(id);
// save foo in cache
}
return foo;
}
}
In this example, GetFoo is defined by IMyRepository. Notice how the decorated Repository is only invoked if the item isn't found by the cache.
This follows the Single Resposibility Principle because the real caching implementation can concentrate on retrieving and saving data, whereas the caching Decorator can concentrate on caching. This lets you vary the two independently of each other.
In our current project we used this approach, and what is extra nice is that we could do it as an afterthought without even touching the original Repositories. This is in spirit of the Open/Closed Principle.
I'd put it into the repositories. The repositories should be defined by a contract, and the usage of a cache should be hidden behind that contract, so it's transparent for the consumer of the repository.