Repository Pattern - Caching
Asked Answered
P

2

49

I'm not sure where I should implement the caching in my repository pattern.

Should I implement it in the service-logic or in the repository?

GUI -> BusinessLogic (Services) -> DataAccess (Repositories)

Pm answered 9/8, 2010 at 16:30 Comment(0)
S
38

I would handle it in the repository/data access layer. The reasoning is because it isn't up to the business layer on where to get the data from, that is the job of the repository. The repository will then decide where to get the data from, the cache (if it's not too old) or from the live data source based on the circumstances of the data access logic.

It's a data access concern more than a business logic issue.

Sackett answered 9/8, 2010 at 16:48 Comment(2)
Thanks for the answer! I think it's also better for implementation lazy loading.Pm
IMHO it's a performance issue in the first place, that's why we do caching usually, no? and caching the business layer is more efficient as you avoid re-executing the business logic every timeVariometer
K
76

It's a good idea not to put the caching logic directly into your repository, as that violates the Single Responsibility Principle (SRP) and Separation of Concerns. SRP essentially states that your classes should only have one reason to change. If you conflate the concerns of data access and caching policy in the same class, then if either of these needs to change you'll need to touch the class. You'll also probably find that you're violating the DRY principle, since it's easy to have caching logic spread out among many different repository methods, and if any of it needs to change, you end up having to change many methods.

The better approach is to use the Proxy or Strategy pattern to apply the caching logic in a separate type, for instance a CachedRepository, which then uses the actual db-centric repository as needed when the cache is empty. I've written two articles which demonstrate how to implement this using .NET/C#, which you will find on my blog, here:

If you prefer video, I also describe the pattern in the Proxy Design Pattern on Pluralsight, here:

Keele answered 18/10, 2011 at 10:39 Comment(9)
I'm agree with you approach. Legacy business logic classes keep using non-cached repository and new business logic services could use the new one. You've less impact on existing logicRusell
The SRP applies to a class. You can implement a cache in a Repository pattern without doing everything in 1 single classTask
@Task Yes, if you follow the approach described here. That's the whole point. :) If you add responsibility for caching to a repository class that is already responsible for persistence, that's more than one responsibility.Keele
Your articles are fine and thanks for sharing. How about Iqueryable returns? If I have some repository methods that gets parameter as Expression and returns IQueryable; how can we use a cache repository?Airliner
Probably better as a separate question. You can build a cache key from an expresssion, but it’s not trivial code. Alternately you can use the specification pattern and add a key property to the spec. Don’t return IQueryable, though. That will make your life harder.Keele
@Keele I think you need to clarify the meaning of "put the caching logic directly into your repository". Do you mean by exposing the caching mechanism through the Repository objects or their internal implementations? SRP only matters when your object exposes methods and properties that serve purposes other than its original responsibility. But, it's totally fine for the internal implementations to implement caching as long as those logics are not exposed. As far as the consumers of his Repositories concern, they don't care/don't know if his repositories perform any caching or not.Infant
@Infant I clarified why with "If you conflate the concerns of data access and caching policy in the same class, then if either of these needs to change you'll need to touch the class." You can also think of this as applying the Open/Closed Principle. By using the CachedRepository pattern I describe, you can add caching (or other behavior) without having the edit the code you're using for your data access implementation.Keele
@Keele I think your understanding of Open/Closed Principle and SRP is quite narrow. Editing existing class is not evil, in fact it should be done for purpose of refactoring, improve performance, updating internal dependencies to new API, etc. A class should be Closed for modification that alters its exposed API and be Opened for API extensions that cover on-demand needs but still within the scope of the original API. This is the same idea with SRP, as long as your exposed API does not change, you can and should edit your codes for the above reasons, as in this case, to improve performance.Infant
@Keele With regards to CachedRepository. You typically have 2 options: 1) Use a Cache object that expose API to retrieve-from/save-to a local store. 2) Write the caching logic inside CachedRepository. Now, if you opt for option 2 and expose a caching API, then it's bad because such API doesn't align with the logic domain of Repository. If you opt for option 2 without exposing a caching API or option 1, it's pointless to create another class, just edit the original class to use Strategy pattern. Proxy pattern is also bad here because user should not consider any side effects while using a it.Infant
S
38

I would handle it in the repository/data access layer. The reasoning is because it isn't up to the business layer on where to get the data from, that is the job of the repository. The repository will then decide where to get the data from, the cache (if it's not too old) or from the live data source based on the circumstances of the data access logic.

It's a data access concern more than a business logic issue.

Sackett answered 9/8, 2010 at 16:48 Comment(2)
Thanks for the answer! I think it's also better for implementation lazy loading.Pm
IMHO it's a performance issue in the first place, that's why we do caching usually, no? and caching the business layer is more efficient as you avoid re-executing the business logic every timeVariometer

© 2022 - 2024 — McMap. All rights reserved.