Monthly Archives: November 2013

Policy-based ValueCache

In one of my last posts I analyzed how policy based class design could look like in C#. It turned out that policy based class design can help decomposing functionality which would usually be implemented in one class into smaller parts (policies). Those can then be put together (configure) in different combinations in order to compose one class which fits exactly the user’s current needs. In this post I want to work on a policy based class which provides caching functionality for one single datum.

 First I want to differentiate between 2 approaches declaring a cache of data as outdated:
  • The cache does not know when its data “runs out of date” and therefore uses some heuristics or strategies to determine that. For example a common strategy to declare the cache as invalid is when its content is older than a certain timespan. A web browser could follow such a strategy when it determines whether it displays a page from its cache or reloads it from the web.
  • The source of data which is being cached has access to every cache and can actively invalidate them. Consider an in-process cache of an artifact doing database inserts and queries.

The cache I want to implement is going to support the first approach for now. Its only direct operation supported from a user’s perspective is getting the cached value. Internally it has to distinguish two different cases:

  1. The cache is valid: return the cached value
  2. The cache is invalid: cached value must be renewed and returned

The description of those two cases leaves open what the definiton of “when is the cache valid or invalid?” and “how can the cache be renewed?” is. Those definitions will depend on the actual usage scenario of the cache. Some developers might need a cache which becomes invalid after a certain time, others might need a cache which expires after it has been requested for a certain amount of times. Clearly the definition of when the cache is valid or invalid must be made flexible and exchangeable when implementing the cache class. In other words: It should be implemented as a policy. The same applies when obtaining fresh data in case the cache became invalid. Is calling a delegate provided by the user enough? Should that be done in a multi threading safe way? and so on. Eventually we identify two policies: An “invalidation policy” being responsible for the validity of the cache and a “retrieval policy” taking care of getting fresh data.

With that in mind we construct a basic workflow of the cache class:

  1. Inform invalidation policy that the cache is requested
  2. If invalidation policy claims that the cache is valid return the cached value
  3. Otherwise run retrieval policy to get update for the cached value
  4. Inform invalidation policy that the cache has been updated
  5. Return cached value

or in code:

this.cacheInvalidationPolicy.CacheRequested();
if (this.cacheInvalidationPolicy.IsCacheValid())
{
    return this.value;
}
this.value = this.cacheValueRetrievingPolicy.GetValue();
this.cacheInvalidationPolicy.CacheRenewed();
return this.value;

Looking at this workflow the retrieval policy turns out to be quite simple. It supports exactly one operation called “GetValue”:

public interface ICacheValueRetrievingPolicy<T>
{
    T GetValue();
}

Regarding the invalidation policy it needs to support the following operations:

  • Cache class informs the policy that the user requests the content of cache
  • Cache class wants to know whether the cache is valid
  • Cache class informs the policy that the cache has been renewed
public interface ICacheInvalidationPolicy

{
    void CacheRequested();
    bool IsCacheValid();
    void CacheRenewed();
}

Adding all things together – the cache class and the 2 policies – we are done with the first version of the value cache. I have created a small project on CodePlex called “Byleist” which contains the complete source code. You can find it here. Please note that Byleist is a portable library project. Thus you need to install the Portable Library Tools before opening the Byleist project.

Flattr this!

for each cast

Recently I stumbled over code like this:

class Bar
{
    void DoBar()
    {
    }
}

interface IFoo
{
    void DoFoo();
}

class Program
{
    static void Main(String[] args)
    {
        List<Bar> bars = new List<Bar>();
        foreach (IFoo foo in bars)
        {
            foo.DoFoo();
        }
    }
}

One would think the foreach statement above will not compile. The list can contain items of type ‘Bar’ but the foreach statement wants to iterate through IFoos – an interface Bar clearly does not implement. However that code will compile. Let’s have a look at a code line similar to the code the foreach statement might execute internally on the first element:

IFoo foo = bars.First();

This code will not compile. Phew luckily our world view is somehow still intact. The error the compiler is giving is: “Cannot implicitly convert type ‘Bar’ to ‘IFoo’. An explicit conversion exists (are you missing a cast?)” which already gives us a hint in which direction the journey goes. The compiler basically tells us: I would compile that for you if you add a cast to the statement. And indeed:

IFoo foo = (IFoo)bars.First();

compiles. Why does the compiler allow us to cast an object of type “Bar” to “IFoo”? Well the answer is easy: Because a derived type of Bar could implement IFoo.

class Bar2 : Bar, IFoo
{
    void DoBar()
    {
    }

    public void DoFoo()
    {
    }
}

...

    Bar bar = new Bar2();
    IFoo foo = (IFoo)bar;

Whether you can really cast “Bar” to “IFoo” or not, cannot be determined by the compiler at compile time. In fact it will be determined by the CLR at runtime. If the variable “bar” holds a reference to a “Bar” object the cast to IFoo will throw an InvalidCastException when excuting that code.
Now looking at the foreach statement it becomes clear that casting to “IFoo” is exactly what foreach implicitly does for the user and leads to perfectly valid code as we have seen. Nevertheless although it might be valid code it might not be want we want. To navigate around this behavior we have two options:

  1. Declare “Bar” as sealed – Declaring “Bar” as sealed will make it possible for the compiler to detect a problem with the cast to “IFoo” at compile time. The first example will not compile.
  2. Use the OfType<> extension method on IEnumerable – Using the OfType<> operation returns only those elements which are matching a certain type.

Flattr this!