Good Luck to me (to stick with a blog) How to Design a Good API and Why it matters, Google Tech Talk by Joshua Bloch
Jul 04

I came across a very good blog article today at http://tech.puredanger.com/2007/07/03/pattern-hate-singleton/. It’s about Singleton Pattern.

I was not surprised at the title “Why I hate: Patterns” since like any man made creation, they have their own share of weaknesses. The author has made five points in support of his argument, he says:

  1. Singleton hides dependencies.
  2. Singletons are hard to test
  3. Singleton can’t be sub-classed (easily)
  4. Singleton is a lie (from Java Perspective)
  5. The system might evolve to need more instances of an object, whose only one instance is needed in current perspective.

Alright, first three points are fair. But are they really problems? I don’t think so, Singletons are meant to encapsulate the objects that are needed through out the system (e.g. a database connection). So it should be understood that (almost) all of the classes in the system would be using this resource.

About hard to test, well I am confused about it. The author says that singletons hide coupling and therefore make it hard to run tests. Well, may be, but I have not run into such a situation yet (and I immediately admit that I consider myself a beginner with patterns).

Well, yeah Singletons are hard to subclass. This is a genuine problem.

The last two points are not fair. If a platform sucks at supporting patterns, it’s not the pattern’s fault. (No offense to Java, but that seems as if MS were to blame JavaScript for having buggy implementation in their browser, would that have been fair.?)

Lastly, if I don’t foresee how the system would evolve and have used a Singleton where it should not have been, it’s a fault that I am responsible for. I should not have used singleton in first place. It’s the architects job to use the patterns right.

Conclusion:

Singleton pattern, as I said earlier, is meant to encapsulate global resources. It has become a convention to use Singletons for (at least) logging and DB Connections, which is, what Singletons are meant for. Having a couple of Singletons (for global resources) in the system won’t do any harm. But if you have stuffed your system with them, then there’s trouble and I guess that’s what Miller’s (author’s) article is addressing, but may be it’s not appropriately named.

————

[EDIT] The post was originally titled “Singletons are Evil? But why?”, however, it has been changed based on the discussion below…

written by ishaq \\ tags:


4 Responses to “Singletons are Evil? Yes they (almost) are…”

  1. 1. Alex Miller Says:

    To expand a bit on the testing issue, singletons maintain static state. Let’s say for a minute that you have a singleton that manages database connections (which I’d say is a really, really bad idea). You might run a suite of tests and each test would be checking out a database connection from the singleton to run its test. So, what happens when a test fails and hangs a database connection or perhaps ALL of the connections? At that point, downstream database tests will all fail, not because of the test, but because of the invalid static state; this breaks the basic expectations of test isolation. This is a really obvious problem - there are many far more subtle problems that can occur with such a setup.

    In a perfect world, every test would run in a fresh clean environment and would be totally unaffected by any tests that ran before it. Singletons maintain global static state and thus are NOT isolated between tests.

    For that matter, what if you want to swap in a test database or pass in a connection manager that can do fault injection or even mock the persistence layer entirely for your tests (to avoid hitting the database at all)? If you were passing a connection manager interface to the code, you could do all of these things, but all of these are difficult or more complicated in the face of a singleton.

    Most experienced designers that I know have built systems that rely at some level on singletons and have eventually been bitten by the need to swap out or change the implementation of that singleton at a later point and been unable to do so. I know I certainly have.

    With respect to evolution of the design, things change over time. You never know what requirement will come up a year down the line. Using a singleton locks you into an architectural choice with no way out. Eventually, you’ll regret it.

  2. 2. ishaq Says:

    Great Reasoning for Hard To Test argument Miller, I agree with you on that.

    However, for the evolution of the design, No I don’t because, although we never know how the design is going to evolve, we can still predict it to some extent (in fact that’s what an architect is trying to achieve in the design most of the time.) And if the system has evolved so much that it can’t live with singletons any more, it means two things:

    1. The architect made a bad design and has stuffed everything with Singletons. (which I already said that singletons should only be used for obvious reasons). I blame the architect here.

    2. The system has evolved to a point where original design has become obsolete. If this is the case, then it’s not only singletons but a large part of the design that has worn out, and therefore calls for a huge upgrade. In which case, Singleton may be blamed.

    Singletons should be used cautiously, and if they are, There won’t be as many design evolution problems

  3. 3. Alex Miller Says:

    The problem is that when you reach the point in #2, you’re often out of options. At that point, the singleton is woven too deeply into the entire system or APIs you would need to pass those singletons through are frozen or politically difficult to change (as they affect many users). I’ve been at this point and it’s a bad place to be. My point is that there are better alternatives and making those decisions early will save you great pain at a later date.

    In my opinion, choosing singleton is virtually ALWAYS a bad design choice. Part of making a good choice as an architect is understanding how to create a design that can evolve with the least pain, even in the face of unknown or unforeseeable requirements. That sounds counter-intuitive, but it’s possible.

  4. 4. ishaq Says:

    Hmm, That sure is scary… But:

    1. Thou shall look at the system and if it’s not very critical and/or big, Thou shalt go for Singletons (they keep the code clean and easy to read).

    2. If the system is critical and/or is going to live for several years, Thou shalt avoid them (and pass things around yourself).

    I agree with you… :)

Leave a Reply