(^146) 97 Things Every Programmer Should Know
Resist the Temptation of the Singleton Pattern ............
Sam Saariste
THE SiNGLETON PATTERN SOLVES MANY OF YOUR PROBLEMS. You know
that you only need a single instance. You have a guarantee that this instance
is initialized before it’s used. It keeps your design simple by having a global
access point. It’s all good. What’s not to like about this classic design pattern?
Quite a lot, it turns out. Tempting they may be, but experience shows that most
singletons really do more harm than good. They hinder testability and harm
maintainability. Unfortunately, this additional wisdom is not as widespread as
it should be, and singletons continue to be irresistible to many programmers.
But they are worth resisting:
- The single-instance requirement is often imagined. In many cases, it’s pure
speculation that no additional instances will be needed in the future.
Broadcasting such speculative properties across an application’s design
is bound to cause pain at some point. Requirements will change. Good
design embraces this. Singletons don’t. - Singletons cause implicit dependencies between conceptually independent
units of code. This is problematic both because they are hidden and because
they introduce unnecessary coupling between units. This code smell
becomes pungent when you try to write unit tests, which depend on loose
coupling and the ability to selectively substitute a mock implementation for
a real one. Singletons prevent such straightforward mocking. - Singletons also carry implicit persistent state, which again hinders unit
testing. Unit testing depends on tests being independent of one another,
so the tests can be run in any order and the program can be set to a known
state before the execution of every unit test. Once you have introduced
singletons with mutable state, this may be hard to achieve. In addition,
such globally accessible persistent state makes it harder to reason about
the code, especially in a multithreaded environment.