Patterns I Hate #1: Singleton
This entry inaugurates a new series on patterns that I hate. Hate is a strong word, perhaps a better name would be “patterns that I’ve frequently seen lead to ruin”. But that seemed too long.
Anyhow, the singleton pattern is the hands-down #1 pattern that can lead me to froth at the mouth. When a programmer first stumbles on GoF, Singleton seems to be the pattern that they first latch on to because it’s so easy to understand (just one class). Novice programmers doing their first design will often break out subsystems and access them via singletons.
Why is Singleton evil?
- Hides dependencies – A component that uses one or more singletons is hiding crucial information about your dependencies. It doesn’t take long for calls to a singleton to creep through your code base like kudzu, slowly attaching itself to every class in the system. Exposing that dependency forces you to think about it as you use a component. It also makes it more reusable as the caller can understand its requirements and how they might be satisfied.
- Hard to test – The hidden coupling of users on a singleton makes testing a nightmare as there is no way to mock out or inject a test instance of the singleton. Also, the state of the singleton affects the execution of a suite of tests such that they are not properly isolated from each other.
- Hard to subclass – Since initialization occurs in a singleton in static code, it is not amenable to subclassing because subclasses inherit the initialization code without the chance to override it.
- It’s a lie! (in most Java systems) – Singletons in Java are based on static variables, which are held per-classloader, not per-VM. In most systems of any complexity these days (any based on an app server, OSGi, Eclipse, plugins, etc) many classloaders will be involved. In that case, it is quite easy for two plugins to create their own instance of a singleton. Sometimes this is done by design and is desirable. But it’s also easy to screw up. It’s also usually critical that the singleton get created in the right classloader, which can make lazily constructing the singleton tricky.
- A singleton today is a multiple tomorrow – It’s not at all unusual to discover that you now need 2 or more of something you previously only needed one of. Hard-coding the singleton pattern into your code makes it impossible to satisfy that demand later. This probably seems really weird if it hasn’t happened to you, but it has happened more than once to me.
What is the alternative?
First, it is important to separate the “need for one of something in my system” from the “singleton pattern”. It’s perfectly reasonable to want one of something but to avoid using the singleton pattern. In other words, the problem is in the pattern, not in the goal.
When a singleton seems like the answer, I find it is often wiser to:
- Create an interface and a default implementation of your singleton
- Construct a single instance of your default implementation at the “top” of your system. This might be in a Spring config, or in code, or defined in a variety of ways depending on your system.
- Pass the single instance into each component that needs it (dependency injection)
This alternative will give you the effects of a singleton, but makes the dependencies clear in the components that need it, allows a singleton to be mocked (via the interface), subclassed, proxied, and tested.
But I already have a bunch of singletons in my code!
Sometimes, you’ll have a system (built by you or someone else) that is heavily dependent on some singletons. Often, you will find this annoying as you try to test and/or add functionality to the system. To refactor the singletons out of your system, you need to start from each point of use and allow the singleton to be set as a dependency on the component using it, rather than calling to the singleton’s getInstance() method. Doing so moves the singleton access (but not use) up one level. Repeat until the singleton’s getInstance() method is called in as few places as possible (ideally one).
At this point, all components in the system declare their dependence on the concrete singleton class and that singleton class is instantiated at a very few points at the “top” or your architecture (then passed down through the systems). Next, it’s time to apply some classic refactoring. Most importantly, we want to change the concrete singleton class into an interface and move the existing concrete implementation into a new default implementation class implementing the interface. Finally, you’ll probably want to cleanup the calls to getInstance() with either a call to new the concrete default implementation or a factory method that can do that for you.
This transformation should make all of your components dependent on an injectable, interface-defined component, which is easy to mock or swap in during unit testing of the component itself. It also typically makes testing of the concrete singleton implementation itself a breeze compared to the prior implementation.
Note that the first phase of bubbling the singleton instantiation up through the architecture can be done as slowly as needed and does not need to be done all at once. You’ll find the second phase is fairly easy with any modern IDE once you get to that point.
But I really, really, really want to use a singleton
There are still some cases where singletons are a valid choice.
One is logging. Logging is so pervasive that unless you use some fairly heavy-handed dependency injection or AOP, it is not feasible to inject every class in the system with a logger. Instead, this is a case where using static methods or singletons are probably worth the compromise.
Another common use is to obtain a handle to a service locator (think JNDI) that knows how to access everything else. This is actually one way to change your entire system from using many singletons to using one singleton that knows how to find the others. This is a valid technique that addresses some of the inherent problems (mockability, testing) with singletons and may be a less invasive change to a legacy code base.
Swing or other client-side UIs are another case where singletons may be a valid choice. In the case of a Java desktop app, it is likely that you have more complete control over your deployment environment than you do in a server-side application. In this case, it can be acceptable to have a manager class managing some state as a singleton in the VM. However, my preference would be to go the extra step to expose that dependency.
If you do really need to use a singleton, please make sure you initialize it safely!
This concludes the first pattern I hate. I’ll be back soon to talk about another.