Singletons Cause Cancer

It’s been said before. I’ll say it again. The singleton pattern sucks. From a pragmatic point of view, it has two primary drawbacks: reuse and testability.

Reuse

A public static getInstance() method is, by definition, statically bound at compile time. Since you can’t override static methods, reusing singleton code via inheritance means you’ll need to create a new getInstance2() method. No matter how creative you get with this method name, you have to accept that users of your code will periodically call the parent types public getInstance() method instead of your spiffy new getInstance2(). Working off an interface largely becomes a moot point since the developer must know the exact type of singleton they want to use at compile time in order to invoke the correct getInstance() method.

How do you configure a singleton without a parameter to getInstance(), which would not be consistent with the intentions of the pattern? Since the instance is constructed internally using a non-publically-accessible constructor, there isn’t a convenient way of introducing configuration information before it’s created.. unless the singleton is aware of a configuration source at compile time with yet more static binding. This makes the code very inflexible, as developers intending to reuse it will be at the mercy of your pre-chosen configuration mechanism, which may not be appropriate for their circumstances, or even unit testing.

Testability

Unit tests generally require control over the lifecycle of the class under test to fully validate proper state transition and contractual validity. Since you, the master of the known universe, are writing the software, you’ll certainly write negative scenarios into your unit tests to assert proper failure handling. If intentionally introducing a negative test results in an irrecoverable state, how do you throw out the singleton and start the next case with a new one? You can’t. What if your test case is creating a tricky concurrency scenario emulating multiple systems within the sandbox of a single JVM? You can’t (trivially). What happens when you discover you need multiple instances of the singleton within your application? You can’t. Time to refactor.

Additionally, unit testing of code using static singleton dependencies has a high potential of awkwardness due to an inability to swap out implementations for mock objects. Under the principle of designing for testability, quality and maintainability, hackishness is not a quality to aspire to.

Conclusion

Singletons can be hazardous to your health, seriously jeopardize your family’s safety, and have been classified as ‘terrorist patterns’ by the U.S. government. The fact that an application only needs one instance of something does not mean the object should be designed that way, and there aren’t very many scenarios where singletons are appropriate. Do as the Jedi do and use them with consideration and responsibly.

12 thoughts on “Singletons Cause Cancer”

  1. >Do as the Jedi do and use them with consideration and responsibly.

    That statement is applicable to all Design Patterns, not just singletons. Just because you CAN use one does not mean that you SHOULD use one.

  2. In praise of the pattern: I used it before i knew the pattern exists. Had to share a number of resources on a Web Server, not only db connection but also content of parameter files and so forth. Other objects would get an instance of this shared component which would provide services. Dramatic improvement in performance becaus all the startup is done only once. Actually the dll runs under COM Plus on an IIS server.

  3. Jason,

    Absolutely. Anyone can read about design patterns; the hard part is putting theory into practice and learning how and when to apply them effectively. Design patterns are not one-size-fits-all solutions.

  4. Giorgio,

    A database connection is a classic example of something which is likely to be instantiated once, but should not be designed as a singleton. If you only need one, only instantiate one and store it someplace else in your app which semantically can only be legitimately instantiated once.

    If you need to establish a connection to a second database within the same app (perhaps for backup purposes) and wish to reuse your code, you’ll probably need to refactor away from the singleton pattern. Or if you decide to deploy multiple apps which share the same database, you’re also likely to need to refactor to be able to unit test concurrency scenarios.

  5. Er, I have to agree with anyone who mentions databases (or any other sort of stream/data access.) That makes them invaluabe. Sure, you can’t subclass them easily…although you could just as easily make a wrapper class, bearing in mind that you won’t get any of the OO benefits (polymorphism, etc.)

    A small price to pay when you need a single, relegated point of access to something.

  6. Justin,

    I think you’re talking about something slightly different than Giorgio. When you create a wrapper class, you’re separating the singleton from the DB object being instantiated. This at least allows the DB class to be reusable and more testable, while providing a single-point-of-access via a different class.

  7. Perhaps it is not a problem with the singleton pattern but, the common implementation in java. getInstance() is a factory method and as you point out if it is a static you run into a number of problems. Put it another way, if the object was not a singleton but could only be constructed through a static getInstance() you would be presented with all the problems you have stated. I don’t think there is anything inherinently wrong with singletons, it is the common java implemetation of them that causes cancer…

Comments are closed.