共用方式為


Why Singletons are Evil

While I did not write this, I totally agree with it. Brian Button is probably one of the most talented people I know, and I am sure he would love your feedback.

1) Singletons frequently are used to provide a global access point for some service.
True, they do this, but at what cost? They provide a well-known point of access to some service in your application so that you don't have to pass around a reference to that service. How is that different from a global variable? (remember, globals are bad, right???) What ends up happening is that the dependencies in your design are hidden inside the code, and not visible by examining the interfaces of your classes and methods. You have to inspect the code to understand exactly what other objects your class uses. This is less clear than it could be. The urge to create something as a global to avoid passing it around is a smell in your design; it is not a feature of globals/singletons. If you examine your design more closely, you can almost always come up with a design that it is better and does not have to pass around tramp data to every object and method.

2) Singletons allow you to limit creation of your objects.
This is true, but now you are mixing two different responsibilities into the same class, which is a violation of the Single Responsibility Principle. A class should not care whether or not it is a singleton. It should be concerned with its business responsibilities only. If you want to limit the ability to instantiate some class, create a factory or builder object that encapsulates creation, and in there, limit creation as you wish. Now the responsibilities of creation are partitioned away from the responsibilities of the business entity.

3) Singletons promote tight coupling between classes
One of the underlying properties that makes code testable is that it is loosely coupled to its surroundings. This property allows you to substitute alternate implementations for collaborators during testing to achieve specific testing goals (think mock objects). Singletons tightly couple you to the exact type of the singleton object, removing the opportunity to use polymorphism to substitute an alternative. A better alternative, as discussed in the first point above, is to alter your design to allow you to pass references to objects to your classes and methods, which will reduce the coupling issues described above.

4) Singletons carry state with them that last as long as the program lasts
Persistent state is the enemy of unit testing. One of the things that makes unit testing effective is that each test has to be independent of all the others. If this is not true, then the order in which the tests run affects the outcome of the tests. This can lead to cases where tests fail when they shouldn't, and even worse, it can lead to tests that pass just because of the order in which they were run. This can hide bugs and is evil. Avoiding static variables is a good way to prevent state from being carried from test to test. Singletons, by their very nature, depend on an instance that is held in a static variable. This is an invitation for test-dependence. Avoid this by passing references to objects to your classes and methods.

I hope this explains a little more fully my opinion of the singleton pattern. I have a small collection of links I found through Google of others, including Jim Hyslop and Herb Sutter, who share this opinion. Let me know if you'd like them.

[Now Playing: Metallica - Disposable Heroes (08:17)]

Comments

  • Anonymous
    May 24, 2004
    The comment has been removed

  • Anonymous
    May 24, 2004
    #2 is saying Singlton is managing a resource and a factory or builder is a better "true" option for how to create a object. #3 means that everytime you use a singlton in some other class you are not tied to that singleton and everyone who uses it... and that is same problem with globals. In todays new SO environment and given that one of testings principles is isolation, tying everone to that one singleton smells bad. Singletons have there place I am sure, just not sure I have ever come across a need for one.

    And what links do you want me to post?

  • Anonymous
    May 24, 2004
    Singletons are a great temptation, as are static classes with public methods and private state.

    I havent put this into practice yet, but I have a feeling that the IServiceProvider constellation of interfaces is a good approach to handling singletons, at least, it seems that it might be the solution in the MVC code ive been working on.

  • Anonymous
    May 24, 2004
    The comment has been removed

  • Anonymous
    May 24, 2004
    The comment has been removed

  • Anonymous
    May 25, 2004
    #1 is inevitable when your system consists of tons of services (as in tens and even hundreds). Passing them around is plain impossible, you end up with too many parameters, most of them unused (methods will be passing most of its parameters to other methods without using them).

    Alternatively, you may add a bunch of Get methods to other object intefaces in an attempt to let objects get to the service so when A needs B but only has C, it will call C::get_D, then D::get_E and then E::get_B.

    Difference from global variable is very simple and described in patterns books: you cannot modify the object. Nothing is wrong with const global variable (read: #define).

    BTW, it is much easier to refactor code with QueryService calls vs one that passes everythign around. If you don't want code to be talking to service provider, don't give service provider to it.

  • Anonymous
    May 25, 2004
    I would not replace singleton with global variable. The reason is more personal. All my singletons are (almost completely) stateless. The only state they contain are generally configuration settings.

    If I had to use global variables ;) I don't think this same restriction would apply. If the global variable had state, I would never use it. If it is stateless then I can see how global variable and singleton could be seen as the same. The problem with global variables is not that they are global, but rather the fact that anyone can change their state.

    If classes use singletons, I think it is much easier changing/replacing the singleton than replacing all method signatures in a call stack etc.

    PS. How about this as food for thought. What would the general comment be if I said in essence SOA's are singletons

  • Anonymous
    May 25, 2004
    Mikhail,

    #define and const global variables are very different things. #defines do not introduce dependencies on classes, whereas variables do. I don't understand how the cases are parallel.

    As far as your other points about having a system with many services, I fear that our coding styles may be different. I definitely tend towards lots of small, special purpose classes, which usually means that one class needs a very small number of services. I don't run into the situation where one class needs to know about the entire rest of the world. And when I do, I take that as a hint from the code that the design is not as good as it could be, and I make it better.

    Whether you pass the objects in or use a global method of accessing them, that module is still very tightly coupled to the entire rest of your system, and is entirely untestable at the unit level.

  • Anonymous
    May 25, 2004
    Roaan,

    That's an interseting point you raised about SOAs. In essence, I agree with you on that. Once again, I prefer to find a way to make their presence known, and to limit their reach into the rest of my code, as with singletons.

    The issue I try to mitigate when faced with a static dependency like this is the tight coupling that this puts onto any code that calls this. Since singletons, statics, and SOAs are all direct dependencies, without the benefit of an interface on top of them, I always try to interpose a shim class over them. I create an interface for that class, and then I can use a special testing version of that class during unit testing, so I don't have to access the network, set up a server, etc. The downside of this is that I then do have to pass that service around to where it is needed. In my mind, though, that just makes public a dependency that was already there.

    Most of the complexity I end up adding to systems I do to make the final system more unit-testable. I find that the act of doing this also takes me down other good roads, like forcing my code to be more modular, eliminating spiderwebs of dependencies, and things like that. All Good Things (TM).

  • Anonymous
    May 25, 2004
    Mikhail,
    I aggree with you on that. I am assuming you are talking about Visual Studio with QueryService. I think this is a good way to use singltons, and the cool thing about this is I really don't know that I am using one as far as the service is concerned. I guess this might also be concidered as a facade into my service (whatever that might be), and I agree with this approach. Of course I love Visual Studio so I guess the QueryService part does not bother me. :). Thanks for the feedback.

  • Anonymous
    May 26, 2004
    Scott Densmore has an interesting post regarding singletons and why he thinks they are evil. I'd like to go through his points one by one and add my thoughts: Singletons frequently are used to provide a global access point for...

  • Anonymous
    August 17, 2004
    Button's Law of Design Maturity

  • Anonymous
    December 14, 2006
    PingBack from http://blog.rainer.eschen.name/2006/12/15/how-to-decontaminate-a-singleton/

  • Anonymous
    January 31, 2007
    PingBack from http://www.taylor.se/blog/2006/02/01/finding-coupled-code/

  • Anonymous
    February 27, 2007
    PingBack from http://www.elilopian.com/2007/02/19/evil-singleton-mocking-with-natural-mocks/

  • Anonymous
    May 24, 2007
    PingBack from http://complejidad.wordpress.com/2007/05/25/antipatrones-de-diseno/

  • Anonymous
    July 25, 2007
    PingBack from http://www.softwareas.com/the-only-thing-wrong-with-gof-design-patterns-is

  • Anonymous
    September 13, 2007
    learn spanish free online course

  • Anonymous
    September 17, 2007
    hide comments friends myspace code

  • Anonymous
    April 12, 2008
    The comment has been removed

  • Anonymous
    April 27, 2008
    I know the title of this post is weird, but just bear with me a moment... Often time I found myself writing

  • Anonymous
    May 29, 2008
    PingBack from http://softestpawn.wordpress.com/2008/05/29/singletons-are-good/

  • Anonymous
    July 07, 2008
    Design Patterns - A deep dive 3

  • Anonymous
    August 27, 2008
    PingBack from http://flexdesigner.wordpress.com/2008/08/28/an-actionscript-singleton/

  • Anonymous
    September 08, 2008
    The comment has been removed

  • Anonymous
    September 15, 2008
    PingBack from http://piotrga.wordpress.com/2008/09/15/ant-script-good-practices-few-thoughts/

  • Anonymous
    October 08, 2008
    PingBack from http://www.codingwithoutcomments.com/2008/10/08/singleton-i-love-you-but-youre-bringing-me-down/

  • Anonymous
    November 19, 2008
    PingBack from http://underground.infovark.com/2008/11/19/the-curse-of-the-singleton/

  • Anonymous
    December 18, 2008
    PingBack from http://blog.sharendipity.com/simple-actionscript-pseudo-threads

  • Anonymous
    December 28, 2008
    PingBack from http://www.fikribol.com/donkisot/?p=113

  • Anonymous
    January 17, 2009
    PingBack from http://www.hilpers.com/1174751-frage-zu-unittests-in-vs

  • Anonymous
    March 03, 2009
    PingBack from http://blog.adrweb.net/2009/01/27/c-pattern-singleton/

  • Anonymous
    March 10, 2009
    PingBack from http://codex.grimoire.ca/2009/03/10/singled-out/

  • Anonymous
    March 27, 2009
    PingBack from http://blog.uncommons.org/2009/01/11/random-number-generators-there-should-be-only-one/

  • Anonymous
    April 19, 2009
    PingBack from http://hoachau.wordpress.com/2009/04/20/whats-wrong-with-singleton/

  • Anonymous
    April 22, 2009
    PingBack from http://lukehalliwell.wordpress.com/2009/04/23/stupid-evil-cancerous-liars-i-hate-you/

  • Anonymous
    June 03, 2009
    PingBack from http://castironbakeware.info/story.php?title=being-scott-densmore-why-singletons-are-evil

  • Anonymous
    June 11, 2009
    Seems I touched off a bit of a “swirl” with a comment I made on my last blog post: I think, in general

  • Anonymous
    June 12, 2009
    PingBack from http://buildesignwebsite.com/you%e2%80%99re-not-your-data-access/

  • Anonymous
    June 12, 2009
    PingBack from http://buildesignwebsite.com/you%e2%80%99re-not-your-data-access-2/