Written materials

Bits and pieces about programming and design…

A baseclass for every interface

Posted by Marc Vangrieken on January 16, 2008

I have a lot of software designing habits; one of them is creating an abstract base class for every interface I introduce into a system. A while ago I found a very interesting quote from JEFFREY RICHTER:

My recommendation to people is this: Define an interface first and then define an abstract base class that implements the interface. Use the interface to communicate to the object and let end-user developers decide for themselves whether they can just define their own type based on your abstract base class (for convenience) or define their own type based on whatever base class they desire and implement the interface (for flexibility). A good example of this is the IComponent interface and the Component base class that implements IComponent.

He’s very right to talk about convenience and flexibility. In this post I will show you how to create the greatest amount of flexibility using this 3-step structure in combination with the Template Method Pattern.

Consider the implementation of a family of merge algorithms. We don’t know anything expect that we’ll have a lot of different ones and that they are pretty much alike although some might be peculiar. Let’s start by defining the Interface we would like our client code to work with:

interface IMergeStrategy
{
    void Merge();
}

At this point, developers can start creating the family of specific algorithms by creating their own classes that implement the interface. This is nice; there’s flexibility, but we didn’t do anything about convenience.

public class MyMoreComplicatedMergeStrategy : IMergeStrategy
{
    void Merge()
    {
        //…
        //Provide your own implementation
    }
}

Introducing just-a-base class wouldn’t give us any extra convenience; we need to figure out how we can make some default implementations. Our case allows us to identify the basic step of most merge algorithms, the order in which they have to be execute, the pre-conditions for executing them, etc… That’s why I’m going to introduce the base class and the Template Method Pattern.

   public abstract class MergeStrategyBase : IMergeStrategy
   {
       //Steps
       public abstract void DoPartiton();
       public abstract void DoAggregation();
       public abstract void DoGroupBy();
       public abstract void DoOrderBy();       
 
       //Driver
       public virtual void Merge()
       {
           //…
           DoOrderBy();
           //…
           DoGroupBy();
           DoAggregation();
           //…
           DoPartiton();
       }
   }

Now we have our 3-step structure; it will serve our need for both flexibility and convenience. End-user developers can now decide whether to start from scratch or to fit their code into a subclass of the MergeStrategyBase. And when they do the latter they will not have to bother with the driver, the preconditions and they will be hinted about the steps that actually make up the algorithm (convenience). Note that for methods (or steps) that only provide data I use the prefix “Provide”. For actions I always use “Do”.

public class MyMergeStrategy : MergeStrategyBase
{     
    public override void DoPartiton()
    {
        //..
    }

    public override void DoAggregation()
    {
        //..
    }

    public override void DoGroupBy()
    {
        //..
    }

    public override void DoOrderBy()
    {
        //..
    }
}

The IMergeStrategy interface allows the client code to know nothing about this choice (flexibility).

IMergeStrategy simple = new MyMergeStrategy();
simple.Merge();  
IMergeStrategy complicated = new MyMoreComplicatedMergeStrategy();
complicated.Merge();

Note that it’ also possible now to have multiple MergeStrategyBase implementations (e.g. one optimized for speed and one for memory usage). I demonstrated the Template Method Pattern, but there are a lot of other scenario’s that make having a baseclass for every interface worthwhile.

Happy designing!

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>