While working on a project recently, I ran into the following code:
There’s some obvious problems with this code, the one that stood out the most to me is the boilerplate code. The solution I used to solve the problem, which is common, is to use closures:
Assuming cache is an instance of net.sf.Ehcache and the dao is your run of the mill Dao.
public SomethingFromDatabase getSomethingFromDatabase(){
Element element = getDataFromCache();
return (SomethingFromDatabase)element.getValue();
}
private Element getDataFromCache(){
Element element = cache.get(KEY);
if(element == null){
element = new Element(KEY, dao.getSomethingFromDatabase());
cache.put(element);
}
return element;
}
There’s some obvious problems with this code, the one that stood out the most to me is the boilerplate code. The solution I used to solve the problem, which is common, is to use closures:
A similar approach is used by Spring in it’s *Template classes. Refactoring the original code to use the Facade, would look something like:
publicT get(String cacheKey, CacheDataClosure closure){
Element element = cache.get(cacheKey);
@SuppressWarnings("unchecked")
T cachedObject = element == null ? null : (T) element.getValue();
if(cachedObject == null){
cachedObject = closure.getData();
cache.put(new Element(cacheKey, cachedObject));
}
return cachedObject;
}
public interface CacheDataClosure{
T getData();
}
I’m sure to some people reading this blog, the solution seems obvious, and almost not worth mentioning. However, over the years I have seen many interesting solutions to the same problem, especially in the database world, but elsewhere as well. You would be surprised how many people solve this problem with inheritance by instinct. Even those who have used frameworks that require a closure in certain scenarios, don’t necessarily think about what it is they’re using, and don’t think to use it when a problem arises later. Despite the fact that closures are ugly in Java, they are still the best solution for allowing for separation of concerns in a lot of scenarios, and reducing boilerplate code.
private Foo getDataFromCache(){
return cacheFacade.get(KEY, new CacheDataClosure(){
Foo getData(){ return dao.getFooFromDatabase(); }
});
}
I do think from looking at it that I may need to go back and think about concurrency. I haven't looked at the ehcache implementation, but I assumed it blocked. I was simply refactoring the earlier boiletplate code.