|
|
Why Singletons Are Controversial
The use of singletons is actually a fairly controversial subject in the Java community; what was once an often-used design pattern is now being looked at as a less than desirable coding practice. 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. What's wrong with singletons' use of global state?
First, programs using global state are very difficult to test. One of the hallmarks of testability is a loose coupling of classes, allowing you to isolate a single class and test it completely. When one class uses a singleton (and I'm talking about a classic singleton, one that enforces it own singularity thorough a static getInstance() method), the singleton user and the singleton become inextricably coupled together. 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). The ideal solution here is to pass in the singleton as a parameter in the user's constructor, allowing a tester to easily mock out the singleton for tests. The singleton then doesn't have to enforce its own singularity; this can be handled by the client or a factory class, which could produce the real version or a test version, eliminating the global state altogether. In fact, it should be considered a violation of the Single Responsibility Principle of OO design to have an object responsible for its own singularity as well as its normal tasks.
Second, programs that rely on global state hide their dependencies. One of the unique abilities of a singleton is that it can be accessed anywhere though its globally available static method (i.e. getInstance()), allowing programmers to use it inside of a method without having to pass it in expressly through parameters. 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.” This means that users need knowledge of the inner workings of code to properly use it, making it more difficult to use and test.
Tying these two problems together shows another issue with singletons. In todays world of test-driven and agile development, it is more important than ever to have small tests covering most of your code. 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.
Still not convinced? Well, this certainly wasn't originally my idea, and it's not even that new. If you're looking for some more compelling arguments, check out some of these sources:
All pages with Singleton in their title at the Portland Pattern Repository Wiki
Use Your Singletons Wisely (IBM developerWorks)
Sign in to add a comment

In most cases a singleton is equivalent to a class consisting only of static attributes and methods. Why is this a bad smell to most developers, whereas the singleton isn't? Maybe because the latter is a well known pattern?
No, with the latter you can take advantage of inheritance.
Another problem with a static class implementation is that you may later find the need to change from having a single global instance to multiple context-based instances. With a static class, you will wind up having to rewrite a lot of static references in your code.