Google today open-sourced the Google Singleton Detector, a tool that helps detect singletons in Java code. According to the tool's designers, singletons introduce subtle design problems, and make code hard to test. What do you think is wrong with singletons?
Google today announced that it open-sourced a tool, the Google Singleton Detector, that helps detect singletons in Java code, with the ostensible goal to aid in removing singletons. More generally, the tool helps discover code patterns that rely on various forms of global state:
[The tool] detects four different types of global state, including singletons, hingletons, mingletons and fingletons... Second, it outputs a graph with all these different types of static state highlighted, and shows all the classes that are directly dependent on them. The point of this tool is to allow you to see all of the uses of global state inside a project, as well as how they are all interrelated.
According to the tool's creators,
The problem with singletons is that they introduce global state into a program, allowing anyone to access them at anytime (ignoring scope). Even worse, singletons are one of the most overused design patterns today, meaning that many people introduce this possibly detrimental global state in instances where it isn't even necessary.
A key problem of relying on global state is that it makes code harder to test:
It is no longer possible to test the user without also testing the singleton. In many cases, this is a deal breaker that can prevent a developer from testing a class at all, especially if the singleton represents a resource that should not be updated by tests (i.e. an important database).
They also note that objects that depend on global state tend to hide their dependencies on that state:
Allowing programmers to use [global state, or singletons] inside of a method without having to pass it in expressly through parameters [is another problem]. While this may seem easier to the programmer, relying on this static instance means that the signatures of methods no longer show their dependencies, because the method could pull a singleton out of thin air."
Yet another problem is that order becomes significant when executing tests involving singletons:
One of the important things about these tests is that they must be able to be run in any order (not dependent on each other), which can become a problem with singleton usage. Because the dependencies of some given methods aren't clear when they rely on singletons (getting them from static getters), a tester may unknowing write two tests that actually depend on each other by modifying a shared resource (the singleton). This can produce flaky tests, ones that pass when run in one order but fail when run in another, which aren't very useful.
What do you think is wrong with singletons, if anything?
It depends on what you want. If there is really only one of something in the system then the singleton is a good choice, it ensures that you don't make the mistake of having two.
For example if there is one ADC (as in one bit of hardware) in an embedded system having the ability to make two ADC (as in ADC class that talks to the hardware) instances would be an error. So you have a trade off, do you want to ease testing of your code were you can easily mock the ADC or do you want compile time checks that you only have one ADC?
I haven't had too much trouble allowing a different singleton for testing but others seem to have. Frameworks like Guice provide a good way to do this, but they still mean you have to change your code to enable testing just like any other means of substituting a singleton for testing.
The Singleton pattern was published before distributed computing environments were common. In distributed environments, trying to create and use a Singleton is probably more trouble than it's worth. In a more limited environment, Singletons are a useful tool.
So they "introduce global state" to a program? Would someone mind explaining to me why this is necessarily a Bad Thing? One thing programs have plenty of is 'state'; it's part of what they are, and what they do.
Thus, people started using it everywhere, especially where it wasn't supposed to be use (when the only pattern you understand is hammering stuff in other stuff, all the stuff looks either like nails or like planks), and it all went downhill.
A primary objective behind the development of languages such as Modula-2 in 70's was to introduce encapsulation (then modularity) in order to avoid the maintenance nightmare and subtle bugs that creep into a code-base when global variables are used. The key question you *never* want to ask is "who uses this?".
The Singleton sneaks global variables back into a code-base. That makes them evil ;)
Test Driven Design, for instance, combines badly with the Singleton because of this sneakiness. If you don't know there is a Singleton hiding in there, you won't know that you have to reset its state before each test. If you add a new test in the wrong order that changes the state of the Singleton, other tests may unexpectedly fail.
If you accept loose coupling as a quality measure (and you should) note that Singletons typically show up like star networks in a coupling diagram.
The popularity of Singletons can be attributed to the fact that, as one of the simplest design patterns, pattern books often introduce them first without warning that they are very seldom required and most often abused.
> And it's the only GOF pattern that's trivial to grok for > "imperative" programmers,
Actually, one of my biggest problems with the use of Singleton is that it's generally over simplified. It's not really what the GoF pattern was meant to accomplish. The book could make this more clear, but if you look closely (especially the examples) the point of the Singleton is to be able to configure the type of the Singleton instance. This makes it useful for implementing other patterns such as the Abstract Factory pattern.
Personally, If you want to create a static method for retrieving instances, it shouldn't matter to the clients of this method what instance they receive. If it's a Singleton at first and then later you need to change that design, that shouldn't matter and it definitely shouldn't require renaming anything.
Given all of that, most 'Singletons' I see are merely global objects. This global object pattern is overused because a lot of developers think in globals. This is the only way they know of to communicate between different parts of a program.
> Test Driven Design, for instance, combines badly with the > Singleton because of this sneakiness. If you don't know > there is a Singleton hiding in there, you won't know that > you have to reset its state before each test. If you add a > new test in the wrong order that changes the state of the > Singleton, other tests may unexpectedly fail.
That's been my experience too; global state in general and singeltons in particular become a nightmare once you have a large test suite. You generally need some way to keep state from bleeding between tests, and random singletons make that essentially impossible. They also encourage people to write code in such a way that the inputs aren't explicit, since the code can just grab singletons out of the air whenever it needs them; that's often difficult to get around, but singletons tend to encourage people to not even try.
Well, it's not only global state that hurts (though global state alone is enough). Another problem is that the object shouldn't be responsible for its cardinality. This is an integration problem, and it is best handled by dependency injection containers. Also, the domain of singleton uniqueness is rather obscure — it's AppDomain under .NET, process under C++ and so on. That couples the Singleton pattern with its implementation, making it more a technical hack than an architectural concept.