A Curious Mind
#tastic

The skeletons in Singleton's closet.

Monday, August 21, 2006 3:36 PM

Ok, so I have a personal distaste for code based singletons. Code based Singletons are hard to test (think NUnit), they make changing from a singleton to "Not Singleton" painful, [add other rants here]

Instead of using code based singletons I prefer to use a MicroKernel like Castle's MicroKernel or Spring.Net. The big change is that this lets me do Dependency Injection(DI) on the singleton class.

With DI I can easily test the internals of the class.

Before

public sealed class Printer
{
    private static Printer _instance;

    public static Printer Instance
    {
        get
        {
            if(_instance == null)
                _instance = new Printer(new Spooler()); //1
            return _instance;
        }
    }
}

After

public class Printer
{
    private Spooler _spooler;

    public Printer(Spooler spooler)
    {
        _spooler = spooler;
    }
}

Which one of these classes is going to be easier to test? The gotcha in the Before set of code is where I have the comment //1. How in the heck are you going to test that? Versus the after where you can easily pass in a subclass (Spooler is actually an interface, I am not a big fan of I notation for interfaces).

The next reason I really like MicroKernel style singletons are their lifestyle configurablilty. You will typically have a nice selection such as Singleton, Transient, PerThread, Pooled, and Custom which is great in case a different app needs to use the code in a different way (Web code vs Windows code). To get this kind of flexiblity in a code based singleton would take a lot of code.

However after all of this ranting another developer Ayende has been turning me back on to Code based singletons that are not much more than a simple wrapper around some code, that tries to provide more of a Global Access concept than a Single instance concept. And this I like.

Well thats all for now.

Dru


Feedback

No comments posted yet.


Post a comment





 

Please add 8 and 8 and type the answer here: