Reputation: 6095
I am trying to figure out which layer should be responsible for the caching (insert/remove) work in a Domain Driven Design project. The goal is to improve performance of the Web Application by caching any entities that is retrieved from the repository.
My solution is separated as follows:
MyApp.Infrastracture
MyApp.Repositories
MyApp.Domain
MyApp.WebApplication
I feel that since it's only the Web Application that utilises the cache then it should be this layer that the caching logic should go? However this does not feel correct as i want to keep the web app lightweight and focused on serving web pages.
Also caching is not a first class domain concept so does not have a natural fit in the Domain layer.
What to do?
Upvotes: 12
Views: 3668
Reputation: 6360
You noted
The goal is to improve performance of the Web Application by caching any entities that is retrieved from the repository.
So I think you should implement it transparently in your repository. The repository is meant to hide the details of persistence from the domain, and if you want to cache large objects for performance, then the domain should be none the wiser. Your repository will have to get quite a bit smarter, potentially tracking multiple copies of the same object as parallel threads request objects and simultaneously mutate them. Or -- if possible -- serialize access to individual aggregate roots as they represent transaction boundaries.
As @Oded pointed out, caching can really happen anywhere, and you'll likely find yourself implementing it in lots of places if performance is a problem, and each spot might do it differently. For instance, you might cache the result of certain queries in your domain, or you might cache entire HTML responses.
The cross-layer coordination comes in because caches can be quite a leaky abstraction. If your domain objects are cached, when should they be uncached? What if one thread is using a cached object and the other is not? What if you are caching query results, but the underlying objects have since changed? When to invalidate and how to invalidate are difficult questions, both from the infrastructure perspective and the business perspective. Stale queries aren't always bad.
Upvotes: 5
Reputation: 6054
The caching could be distributed among layers, sometimes caching can be automatically achieved in the domain layer if you are using a ORM like Nhibernate which supports caches of multiple levels. In upper layers it could be based on requirement, for example when loading the user the system loads what are the functions user is allowed to do, then it can be cached in the Application level. So it all depends on the application.
Upvotes: 0
Reputation: 7846
I totally agree with Oded that it's a cross cutting concern, but it should also be transparent to the client of the cached items.
For example, users of your repository shouldn't care whether an item is cached or not.
I would argue that if caching is an important aspect of your solution then it should made clear in the Domain, however, you'll probably find that it actually ends up as part of the infrastructure and is delivered (silently) via whichever IoC container you use.
Upvotes: 4
Reputation: 499112
It is a concern of all of the above.
Caching is one of those cross cutting concerns that each layer needs to handle individually and the application needs to orchestrate.
Upvotes: 12