Why you REALLY need to think about your interfaces

kick it on DotNetKicks.com

I was working on performance tuning an application the other day.  The code in this post is a rough approximation of the problem I had to solve.  The application defines a plug-in interface that the plug-in developers can implement.  The plug-in gets initialized with a dictionary and and the application talks through the rest of the interface.

public interface IPlugin
{
    void Initialize(Dictionary<string, Information> dataLibrary);
    string TalkToMe(string message);
}

The initialization from the application is simple:

public void SetUpPlugin(IPlugin plugin)
{
    Dictionary<string, Information> data = PopulateDictionary();
    plugin.Initialize(data);
}

When this interface was originally written, the dictionary was populated using XML files.  The dictionary only included about two hundred items, but over time, this dictionary became more complex.  It grew out of the XML files, and into a database.  It grew into tens of thousands of items.  It is not hard to tell that there is a performance bottleneck here as the application populates this many items from the database.  It turns out that the plug-ins don’t tend to need a lot of the data in the dictionary, though I cannot predict what it will need to lookup.  To populate the entire dictionary takes a TON of time, and it is completely unnecessary.

Unfortunately, I am bound to this interface, which is already published to our plug-in developers.  My first inclination was to write a custom Dictionary<> class.  It would be really nice if .NET would let me do something like this:

public class DataLibrary : Dictionary<string, Information>
{
    private IApplicationLogic _logic;
    public DataLibrary(IApplicationLogic logic)
    {
        _logic = logic;
    }     

    public override Information this[string key]
    {
        get
        {
            return _logic.LookupInformation(key);
        }
    }    

    public override int Count
    {
        get
        {
            return _logic.InformationCount;
        }
    }
    // etc
}

This would solve my needs completely if only methods were not sealed by default in C#.  Unfortunately, they are, and .NET didn’t make the Dictionary members virtual.  In fact, it turns out, I am completely coded into a corner since I can’t change the interface.  If only the IPlugin interface were thought through a bit further, I wouldn’t be in this predicament. 

All that really needed to happen was for IPlugin.Initialize to take an IDictionary<string, Information> instead of a Dictionary<string, Information> (notice the ‘I’ in front of the Dictionary, indicating that it is an interface as opposed to a concrete class.)  If this were only the case, I would be able to implement the interface using a database lookup and move on with my life.

Now, I really don’t have any solution other than asking for an interface change to all of the plug-in writers for my application.  This not only looks bad, but it IS bad.  I suppose might be able to come up with something crazy using Dynamic Proxies, but that would get rather ugly rather quickly.

The more you think about it, the choice of Dictionary<string, Information> was bad for other reasons as well.  The Dictionary class is a read/write class.  We do not want our plug-in authors to modify the dictionary — we only want them to look up data.  We don’t need them to iterate over the data, and we don’t need to give them a vectored view of the keys or the values.

The message I am trying to get through here is simple:  When you are creating an interface for public use, you need to think hard about what that interface looks like.  Avoid concrete data passing when interfaces are available (IDictionary instead of Dictionary).  These interfaces don’t get to change much.  They aren’t as flexible as the internal code.  Please, think about your interfaces.

Leave a Reply