Is cache an optional dependency?

Recently, one of my colleagues stated that the cache should always be required dependency. We should require it in non-null constructor parameter. And we can’t use null-object pattern with it.

How to bring over this point of view? What do you suggest? How do you inject cache in your technologies?

update1: By cache I mean interface, that can query value by key, store it, determine is hit/miss and etc. So it’s some kind of backend storage for https://en.wikipedia.org/wiki/Memoization

4

PSR-6 recommendation regarding Caching Interface expresses a view I personally prefer:

While caching is often an important part of application performance,
it should never be a critical part of application functionality.

So, I’m in favor of considering it as an optional dependency.

No, one either uses a cache or doesn’t.

In your application, one would determine whether caching was necessary. I would inject caching as a decorator pattern.

Consider this interface.

public interface ICommand<in TIn, out TOut>
    {
        TOut Execute(TIn command);
    }

We pass something in and get something back out. Maybe to get something takes a long time. So, we decide to add caching.

public class CacheDecorator<TIn, TOut> : ICommand<TIn, TOut>
    {
        private readonly ICache _cache;
        private readonly ICommand<TIn, TOut> _command;
        private readonly string _key;

        public CacheDecorator(string key, ICache cache, ICommand<TIn, TOut> command)
        {
            _command = command;
            _key = key;
            _cache = cache;
        }

        public TOut Execute(TIn input)
        {
            TOut obj;
            if (_cache.Get(_key, out obj))
            {
                Debug.WriteLine(string.Format("Cache hit for key {0}", _key));
                return obj;
            }

            Debug.WriteLine(string.Format("Cache miss for key {0}", _key));
            obj = _command.Execute(input);
            _cache.Set(_key, obj);

            return obj;
        }
    }

Now any command that get’s something back can be cached. If we don’t need caching then the command is not decorated.

Let’s pretend we are getting a widget and getting a widget is expensive:

 public Widget GetWidget(string id)
        {
            var widgetCommand = new WidgetServiceCommand();
            var command = new CacheDecorator<string, Widget>(id, _cache, widgetCommand);
            return command.Execute(id);
        }

If getting widgets was not expensive, then just remove the decorator and the widget is not cached.

1

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *