|
WhySingletonsAreControversial
A brief explanation of the problems with singletons.
Featured Why Singletons Are ControversialThe 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) |
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.
singletons are definitely not a global var, singleton should be thread-safe, multi-thread-safe and synchronized, you may dream to accomplish this Job with global vars, especially if you have singletons in a shared Object(s)/Librarie(s).
this is by the way the definition of singleton design pattern, in Java and Objective-C it's really easy to accomplish and there is a big use of this pattern especially in Desktop Application. I n C++ it can be painful except with Boost :), there are several folks who wrote interesting stuff about singletons in C++, one of essential aspect of singleton pattern is the multi-thread support with a mutex/lock mechanism, the next version of STL/C++ should include this natively in the same way than Objective-C/ Class Struct where every Object has a mutex property.
And finally, to answer to the author, there is no controversial/trivial point, as Developer you are supposed to know what you are doing and understand basic OO design pattern if you do not, chose another Job! Code is really not for you.
-Tchuss
you may use OCaml and stop doing Java, it could help :), there are several developers who are using Singletons in a proper way, detect them if you want this is for me what you wrote, is useless, try to replace a brain by a poor parsing tool, LOL, it's like machine learning, it's totally void, we should spend this energy in other fields, like change the way we are building machine, change our electronic view, you will never accomplish such things on our actual tech, yes sure it's working a bit but comparison of the billions of $ put in this field...
When one class references another class, it is coupled to that class, period. It does not matter if either class is a singleton. Coupling is unavoidable in software. You can not reduce it by avoiding the singleton pattern.
Further, the 'getInstance()' method of a singleton gives you a reference to an object. At that point, you don't care if the object is singleton or not, so long as it exposes it instance methods instead of statics.
There is a time and a place for singleton. The real problems with singletons are the problems with all statics - holding memory, synchronizing initialization and access, etc.
Of course when one class references another, there's coupling. I think the issue with singletons is that their use can hide the particulars of those dependencies in multiple places within source code, making changes and testing much more difficult to deal with. That's what led to the rise of dependency injection's popularity in the Java world. Those dependencies are explicitly stated in the class definition, avoiding the use of any singletons behind the scenes. That means, for example, that it's easy to test a class that's dependent on a db and mail connection because you can set the connection references directly in a test class using either a test db or mail account, or a mocked connection. If you're using a singleton in your implementation without that kind of explicit dependency declaration, you don't know how or where the connection is coming from and it's difficult to swap out for testing purposes, let alone when implementation details change.
I think that singletons in and of themselves aren't bad, though. It's just that using them behind the scenes makes testing and debugging more difficult than it could be otherwise.
IMHO singletons are not worth a discussion. Originally introduced as the small "1" annotation in UML diagrams and the like (where you need it) they were always present and known as "global variables". Since that was not possible anymore with Java, some strange implementation efforts have been started to compensate for that deficit - and they're still spreading to other languages. To me it seems like a competition of who's creating the most complex implementation available - unfortunately I did that myself 5-10 years ago. And excuses like "thread safety" - come on... do you really want a single synchronization point across all your threads?
When I hear someone say Singletons are they way to go , they drop down a few points in my book.
The main problem is that they are EXTREMELY easy to misuse. The purpose of a Singleton is for a SINGLE point of class instantiation , but that begs the question , "how often do you 'accidently' create another instance of a class".
I was on one project where they were used for everything. Remote services , controlling views , controlling mediators , controlling mediator-view communication and more. Debugging and testing became impossible because the singletons where referenced amongst so many classes. Because of this , a test result using the singleton could not be taken seriously because during runtime , you could never be sure of the singleton's state and who/what was changing it.
TL;DR Singleton/Global variables are bad , it becomes hard to figure out their state during global execution.
@drewmca "Of course when one class references another, there's coupling" which is why you shouldn't dependt on concrete implementations but interfaces/pure abstracts. The you can say well I could pass a singlton for a parameter then. Yes you could but then you have no need for the static getinstance method. You simply allocate the resposibility of creating the object to a specific entity. Adherring to SRP as a free gift
@0xcafefeed: "singleton should be thread-safe, multi-thread-safe and synchronized" so because they are all that they can't also be global -ly available var -iable state? Those are not mutually exclusive concepts. The singleton pattern is a simpler way of slowing down the system by use of one sync point implementing syncronization for a collection of global var's
If people really need global variables then create something to read/write a stream for them!
Seriously - need to store the "health" of a player?... ... writer it to disk using a "non-global" writing object and read it later on.
If you have lots of global variables as such and considering writing them , re-factor.
I've seen couple of times singletons (as in usage, someSystem::getInstance()->method()) that later would need to become proper objects, such as:
etc.The proper use of singletons and the most common design pattern is for managing the state and attributes of a scarce or limited resource that does not support concurrency. A Singleton is the only design pattern that can be used for such a requirement. As such, it is expected that the developer manage concurrency via thread safe management and control of the resource.
It's a sad state of affairs, when so many software "engineers" actively advocate widespread use of global variables and even call it a "design pattern".
First, there is no "global" method of singletons in Java, it is on a classloader basis. Second, thread-safe singletons can be created without synchronization. There are several ways of doing this. Third, most use cases for singletons can probably be implemented by passing instances created by a factory
its depends on the demand of your design. Somtime you may need to use Singleton accross different process. For details refere to http://dgmjava.blogspot.com/