Categories
computer

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 replies on “Singletons Cause Cancer”

>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.

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.

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.

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.

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.

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.

[…] – Dạo trên blog , thấy có má»™t bài chỉ trích OWASP PHP Top 5 :-B , trên đó cÅ©ng chỉ toàn các lá»—i cổ Ä‘iển , nếu má»™t lập trình viên tiếp cập theo lối hiện đại thì mình nghÄ© mấy cái đó ko có vấn đề. – Thêm má»™t bài về testing , programmer có nên test app trÆ°á»›c khi Ä‘Æ°a cho tester hay ko , thix nhất câu này “like those people who hire house cleaners, and then clean their own houses before the professionals arrive” . – Tá»›i giờ má»›i phát hiện ra cái Mysql Workbench – My language vs your language , chuyện muôn đời của lập trình viên – Mysql Fulltext Searching – Notepad có vụ này sao ta – Đọc lại cái xHtml strict thấy nhiều cái còn thiếu sót quá , vd nó đòi input lồng vào trong 1 thẻ khác , hÆ¡i bị phí thời gian vì thẻ hidden thì sao – TextIterator in PHP6 – Singleton dạo này bị phê bình nhiều nhỉ – Microsoft mạnh miệng nhỉ – Æ  , Programming Like Sex , đọc dzui nhỉ ^__^ – Data Model Collections – LogoPond , Top 20 Designs Blog […]

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…

[…] These days I’m not in to the generic, programming for programming’s sake way. I’m mostly interested in learning through doing though. I don’t want to see any tutorials or sample code that shows off how smart the author is. I don’t believe in Singletons and I think Functors are the work of the devil. Design patterns are a good idea but are often abused. I need thorough reference material and simple examples that suit normal usage. […]

[…] As an advocate of test-driven development, my application unit tests attempt to cover the interactions between multiple peers on the JXTA network. Doing so requires instantiating multiple cores within the same Java unit test process, and being able to reset them to initial states between test cases. Unfortunately, JXTA is designed as a singleton, which as we already know is not a friendly pattern to test-driven development. Couple this unfortunate design with the general difficulties of multi-threaded unit testing, and you’ll either be spending vast amount of time with your unit tests, or forgoing the complicated ones completely. Probably the latter. So what’s the solution? I’m not exactly sure, but I’ve started working on one. […]