Why Singletons Suck

People often ask why singletons are considered such a bad idea. After all, the implementation is quite simple and you get a warm feeling of solving a design problem in such a simple and clean way. For me, getting rid of singletons was the single most influential thing I did to improve my design skills. I would like to share this advantage with whoever is interested, which is why I am writing this post.

Definition

One thing that complicates reasoning about singletons is there are two kinds of singletons that get mixed up very easily. One is the “enforced” singleton class that has special code which makes it impossible to create more than one instance. The other is a “logical” singleton class that has only one instance in your application, but contains no explicit code to limit the number of instances. The first kind of singletons is the bad one, the second one is quite harmless. The following critique therefore applies to the enforced singletons only.

The enforced singleton pattern is usually implemented with a class method (called getInstance or whatever else). This method returns the only existing instance of the singleton class, creating it first if neccessary. When other classes want to collaborate with the singleton class, they obtain an instance using the getInstance method.

Problems

The problem is that this pattern creates tight coupling between modules, it violates the principle of single responsibility, makes testing harder, complicates lifecycle management, hides dependencies and makes you write the same code over and over.

Tight coupling causes many problems at once. If you have an application that’s wired together using getInstance calls and want to change the wiring — like exchange one interface implementation for another — you have to change class implementations. If you can’t change the class implementation, you’re out of luck. Wouldn’t it be nice to have the building bricks independent of each other and have the application structure described separately on one single place? Also, how do you want to create reusable software components when each of the components is tightly bound to the rest of the design, dragging all its collaborators with it?

Tight coupling is the reason why singleton-bound architecture is harder to test, too. It’s harder to create an isolated instance of the class being tested when it’s pulling its collaborators alive through the getInstance calls.

The principle of single responsibility is violated because a singleton class takes care of its instantiation and its usual purpose at once. Mixing several responsibilities makes it harder to read the code and grows the number of possible inner states of an object, raising the possibility of something going wrong.

Singleton code hides dependencies because you don’t always see the collaborators in the class interface. Does the class use some other collaborators through getInstance calls in the implementation file? Who knows, you’d have to go through the code.

And as for the DRY principle, who would want to write the singleton boilerplate again and again? Singleton boilerplate is also a perfect place for bugs. Are you sure your getInstance call is thread-safe? There can be no bugs where there’s no boilerplate code.

Summary

If you feel unconvinced, I urge you to go and code as many singletons as you like. If you later encounter any problems with your design, come back here, re-read the text and see if some of your trouble could not be solved by getting rid of the singletons.

I first learned about the problems with singletons from Miško Hevery in his Singletons Are Pathological Liars blog post. If you are interested, read that and all the linked articles on his blog, it’s a very worthwile time investment.

A logical follow-up question is how to wire the building blocks together if you can’t use the convenient getInstance call. I hope to answer that in some of the future posts.

PS. You can now see an example of assembling an application without the use of singletons in a sample Xcode project on GitHub.

Notes

  1. zmotula posted this