I’ve been maintaining a lot of code that liberally uses the Singleton Pattern lately, so I want to turn a bit of a critical eye to it. It’s usually used when you need exactly one instance of something and it’s a cross-cutting sort of need, meaning that it’s needed by multiple other objects.

Here’s how it looks in Java:

public class Singleton {
  private static final Singleton INSTANCE = new Singleton();

  // Private constructor prevents instantiation from other classes
  private Singleton() {}

  public static Singleton getInstance() {
    return INSTANCE;
  }
}

This mechanism is definitely simple and effective at creating only one instance of itself, but it’s quite deceptive in its simplicity. Many other languages don’t have the ability to create private constructors, and that inability can reveal some general problems with the pattern. Here it is in Actionscript 3.0 (though I could’ve easily shown it in another language like PHP, Python, or Javascript):

public class Singleton {
  private static var instance:Singleton;
  private static var creatingSingleton:Boolean = false;

  public function Singleton(){
    if (!canConstruct) throw new Error( "Cannot instantiate" );
  }

  public static function getInstance():Singleton{
    if( !instance ){
      canConstruct = true;
      instance = new Singleton();
      canConstruct = false;
    }
    return instance;
  }
}

So if you have a DatabaseConnectionSingleton Here’s how you’d use it:

var conn : DatabaseConnectionSingleton = DatabaseConnectionSingleton.getInstance();

With this algorithm, it becomes more obvious that we’re trying to restrict construction. This code now needs to throw an exception if someone tries to instantiate it.

What’s that smell?

It’s an interesting exception to throw, because it’s not really an “exceptional” or rare circumstance when this would get thrown — it’s a “never-ever-ever” or “something-is-wrong-in-the-universe” situation. There’s no good reason to catch it and recover, because there’s no reasonable way to reliably continue after this exception is thrown. And make no mistake, the java version’s private constructor is highly unusual as well. I actually prefer this Actionscript version, because at least the weirdness is more obvious. Any highly unusual code like this should be considered a smell . It should force you to ask yourself why you don’t you have to do things like this more often.  Indeed:

  • Ordinarily you don’t dictate how many times a class can be constructed.
  • Ordinarily you don’t restrict how a class is used when you write it.
  • Ordinarily you don’t actually add code to make a class less useful.

These are all things that should be considered very carefully. I would find it difficult to argue that you should make exceptions to your ordinary practices in this case. The poor guy who uses your singleton has to know how to instantiate it properly — you left him with that responsibility so that he can avoid the Exception you throw that should never have occurred. Why not just leave him the responsibility of just instantiating the class once? In general: If you just want one instance of something, why not just create one instance of something? That seems so simple!

The Insidious Truth

The singleton pattern isn’t really about ensuring that you only create one instance at all. If it was why didn’t we just do this instead?

public class Singleton {
  private static var instantiated:Boolean = false;

  public function Singleton(){
    if (instantiated) throw new Error( "instance already exists" );
  }
}

// usage:    var conn : DatabaseConnectionSingleton = new DatabaseConnectionSingleton();

It’s a simpler implementation, with a simpler usage, and it accomplishes the same instantiate-only-once criteria as the previous algorithm.

This is where the true nature of the singleton is revealed. This second implementation is missing a key part of the functionality that Singleton users are really after: the instance is statically bound to the class so that the instance is globally available.

Do I smell something else?

Having an object globally available is very strange indeed. Java doesn’t have globals at all. PHP intentionally uses the globals keyword so that if you want to bring something into a method’s scope that is not an explicit parameter or an instance variable, you can’t do it without first declaring it. Global state is generally as shunned as much as goto itself, and for good reasons:

Non-locality. Global state is by definition not local. The reason you care is because having data far from where it is acted upon adds complexity. You have to keep track of what else might be modifying that data, and what those modifications might mean for your code. In a large system, global state increases complexity quite significantly as the maintainers have to track more and more places where global state can be modified and more and more places where those changes might have ramifications. The pursuit of locality is the primary reason for object-oriented programming in general.

Dependencies. If an object requires a singleton to perform it’s duties, then it depends on that singleton. Anywhere you use your object, you must make sure you also use the singleton. That’s increased coupling which decreases the ease with which you re-use your object. Your object always needs that singleton around any time you want to use it. That’s painful when re-using your object in other applications, and it’s painful when you want to write unit-tests. That singleton needs to travel everywhere your object goes.

In short, the singleton pattern makes code more complex, less useful, and a real pain to re-use or test. Eliminating singletons can be tricky, but it’s a worthwhile endeavour.

6 thoughts on “Singletons: anti-pattern, or worst anti-pattern ever?

  1. Very reasonable. One more reason people use Singleton pattern is performance.

    I’ve made a test in PHP : creating new objects is actually 6x faster then executing get_instance() function, as long as you have empty constructor, which is often the case, since it has no arguments anyway. So this reason is probably not valid as well.

  2. I agree sooo much with your post. So much so that I tend to forbid static methods when working with Java or C# (and I have the power to make the decision).
    Static dependencies are such a pain. Especially when you are new to a piece of code and there are no unit tests. Static dependencies basically must be tracked by reading the code from start to end.
    Typical code that uses static methods looks like this:

    MyObject o = new MyObject();
    o.doSomething();
    —> deep somewhere into the code of doSomething, there is a static call to Service.provideIt();
    And of course, most of the time, Service.provideIt does not work unless you have correctly done some kind of initialization by calling a Service.init();
    So that the code works only because it is written like this:
    Service.init();
    // some code in between
    MyObject o = new MyObject();
    o.doSomething(); // which uses Service.provideIt();

    I’d 100 times rather re-write this mess into the following way:
    Service s = new Service();
    // some code in between
    MyObject o = new MyObject(s);
    o.doSomething(); // which uses s.provideIt(); but now the dependency is explicit

    Unfortunately, it seems to me that many OO programmers write code with static methods and singletons. Thus it is very hard to convince most people (management, other programmers) static methods should simply be forbidden.

  3. Pingback: On Managing Complexity · Contact and Coil

  4. There is nothing wrong with using the singleton design pattern if you are competent. Your ‘Non Locality’ and ‘Dependencies’ sections are contrived and appear to be influenced by some bad experience you had with (probably) badly designed code structure that had nothing to do with singleton. There is a reason the EJB 3.1 spec added a Singleton annotation. There are many good reasons to use Singleton including cache implementations, configuration/property readers or simple util classes such as Calendar or DateUtil to name a few. I don’t know what particular issues you had with your project, but I am guessing that it went far beyond the simple misuse of Singletons.

Leave a reply

required

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>