Why I Hate Singletons

One of the most derided, yet most loved and used patterns is the singleton pattern. Its supporters continually praise its ability to limit instantiation of objects and its opponents continually chastise its tendency to be little more than a glorified global.

While programming in many ways boils down to a matter of preference (you can always find someone that agrees with you,) I thought I might as well document my opinion so that those who don’t care can have one more thing to ignore.

Details after the jump

First, what is the singleton? Most of us know what it is and for many of us I would guess it is the first pattern we grew to know and love. The official definition from the GoF’s book is as follows.


Ensure a class only has one instance and provide a global point of access to it.
- Design Patterns: Elements of Reusable Object-Oriented Software.

The basic summary of why I think singletons are evil is summed up in the second half of its definition. It provides a "global point of access". Even people that say singletons are not evil tend to ignore the fact that this is a built in property of the pattern and some even go so far as to not realize that this is even mentioned in the official definition:

Singletons should be used to control creation, not access. A singleton should *not* be used as a global object just because you can. I find it hard to dismiss a pattern simply because some people don’t use it how it was intended to be used. - Matt Berther, Singletons are not evil

A large, defined purpose of the singleton is to provide a global point of access to an object. This cannot be argued.

So why is a single point of access a bad thing?

A single point of access is not in and of itself a bad thing. If you read the entirety of Matt Berther’s article, you would find that he is very clear that he does not believe you should use a singleton as a global just because you can. By "using it as a global" he is referring to the method of peppering your code with calls to MySingleton::getInstance(). It may be hard to see some of the initial similarities between the following snippets of code.

 

and

 

Don’t let the extra class name fool you. While it does indeed force that object to be of a particular class you will never have any clue by looking strictly at your method declaration of what the dependencies of the method are. This is one of the large problems with both globals and singletons: they mask your dependencies. This will without a doubt make your code less flexible and harder to understand. The lack of flexibility also makes your code harder to test and in the long run harder to maintain.

But the singleton pattern is so useful!

Of course singletons are useful. There are many things that are useful, but that doesn’t automatically make it a good idea.

I will admit, I have used singletons quite heavily in my past. The most common reasons that I would implement them are:

  1. You can only legitimately have one logical instance of a class
  2. The object is expensive to create
  3. You need primitive caching (sort of related to #2)

These are all legitimate reasons to use a singleton pattern. I would discourage the thought of using as a permanent solution for caching however. While it is useful for quick and dirty caching there are many more useful patterns and systems for doing this.

So if you take away caching then there are still two uses for the singleton. A responsible person does not tell you to not use something without offering an alternative. So here is my alternative:

Don’t use singletons…

That’s right, sage advice I know. If your software is designed properly you should still be able to centralize the object creation (that needs centralized) to ensure that you only are creating one instance of an object. If you need to control creation of it then use a factory to do so. Then pass the object to the methods that need it. This will allow you to make your dependencies much more explicit which will provide you with more flexibility in the long run. It will also allow you to unit test your code much more effectively.

Unless you have to!

There are some times you just cannot get away from singletons. In most cases the reason why is the amount of refactoring that it would involve. You simply do not have time for it. The singleton pattern is not all bad. I do think it is a viable pattern for object creation. So just don’t "take advantage" of the second half of its definition (global access.) Get rid of all the getInstance() calls. Those are the real problem with singletons anyways. Move them as high in your call chain as you possibly can. Then you get the benefits of NOT using the singleton without having to embark on a massive rewrite of code.

I bid you farewell

Ultimately, programming is a matter of preference. So long as you are achieving easy to understand and therefore easy to maintain code. It doesn’t honestly matter much how you do it. I personally do not see very many viable uses for singletons and I know there are many people that agree with me (google evil singletons). It’s simplicity seems appealing, but they are incredibly easy to use in a damaging way. This is the danger you risk with any concept that is easy to understand and easy to abuse.

Share
This entry was posted in PHP. Bookmark the permalink.

30 Responses to Why I Hate Singletons

  1. Great advice… I’m totally guilty of using the singleton as a glorified global! Thanks for highlighting the downside of doing so, this will definitely have an effect on my coding practices.

  2. Tim says:

    I’m really interested in seeing some bad usage examples. In the project I’m working on we have a lot of singletons. But they also represent physical hardware, which is globally single. I keep reading posts like this, but I’d like to see a legitimate bad code example.

  3. Scenario: You are writing a unit test, and your code calls a singleton to get an instance of the database.

    For the unit test, you only need a really small, in memory database, like sqlite, with a bit of prefilled data that you can set up and tear down.

    So, your code looks like:

    function foo() {
    db = DBConnection::instantiate();

    results = db.query(…);

    return results;
    }

    and your test looks like

    assert array(1,2,3) == foo();

    Unfortunately, there’s no way to change the behavior of your singleton – lets call it DBConnection; unless you start providing methods like ‘setForTest()’, and then your test becomes

    DBConnection::setForTest(…)
    assert array(1,2,3) == foo();

    … and this works fine for a while; until you are writing this for the 15th time and forget to reset the DBConnection back to the original.

    // First test
    DBConnection::setForTest(…)
    assert array(1,2,3) == foo();

    // Some other test
    assert array(1,2,3,4) == bar(); // that’s odd! This test works just *fine* when I run it alone, but fails in the suite! Spooky action at a distance!

    Sure, you can say “Well, don’t forget then!”, but I would argue that is messy, error prone, and likely to bite you on projects with more than one person.

    More:
    http://misko.hevery.com/2008/08/17/singletons-are-pathological-liars/
    http://googletesting.blogspot.com/2008/08/where-have-all-singletons-gone.html

  4. Mike Lively says:

    Well stated. The two links above are also excellent and did in fact provide some inspiration a few months ago for this article. (I’m slow on the draw)

  5. Dell Sala says:

    This is great… More and more people are recognizing singletons for what they are: globals. Here’s a great talk I that finally convinced me to do away with ALL global state. It is actually possible, and totally worth the effort:

    [url]http://www.youtube.com/watch?v=-FRm3VPhseI[/url]

  6. Justin says:

    At the very least – if you have to have a singleton (they’re the right way to handle database connections, file handles, etc), put it in a registry pattern. Singletons are HARD to test, but a registry pattern lets you pick and place ‘instances’ out of the registry. That way, you only have to have 1 ‘true’ singleton (that for the registry).

  7. Daniel says:

    Eww @ all pervasive registry.

    Why not

    // Nasty configuration reading
    $db = new DatabaseConnection($settings_from_somewhere);

    $foo = new Application();
    $foo->setDatabase($db);

    … and pass $db down the application further

  8. Sam Hennessy says:

    I’m working on a project right now that allows no need to access the global name space in frameworks like ZFW. I believe that getting rid of access to the global name space is the only way to get real code isolation.

    Thatnks for the post Mike :)

  9. Mike Lively says:

    Even registries can have the same problem of masking dependencies. The creational aspect of singletons while somewhat rigid is not the worst aspect of them. In my opinion you should be passing your dependencies to your methods and objects, not pulling them out of thin air.

  10. Eric says:

    Designing an application to be able to test it is evil to me :) Test should adapt themselves to the application not the opposite!

    Also Registry seems cool at the first glance but in fact it lead to other problems like variable name collision and to give you my feeling about it : Registry is a politically correct Global-Array (so not so cool at the end).

  11. Designing an application around testing is evil?

    Having a whole lot of small, well understood components which can be wired together to produce the outcomes I want seems like a pretty good way to go about it for me, especially when I have to fix the defective bits!

    If I can replace SlowSuperProductionDatabaseDriver with CannedResultsDriver by simply telling just the component I want to test to swap; that’s going to save me huge amounts of time – both in execution of the test and in programming time.

    Think about it.
    It’s way easier to create an array and tell CannedResultsDriver what to say than it is to
    * connect
    * interact with a network
    * ask the slow production database to insert records for me
    * optionally: make sure there are no left overs or duplicates from the last time I ran this test, and it failed half way, which would cause this test to fail sometimes
    * Execute the code, which repeats the interaction with network and ask database for results steps…
    * Hey, don’t forget to go back in and clean up everything

    If I’ve got a problem somewhere, and I don’t know where; isn’t it much better to be able to say “If I give it a 1, it throws an exception, ooh bad code” rather than “maybe its the network cable / dodgy data / mystery panthers / April 1st”…

  12. Eric says:

    Don’t misunderstand me: Testing is good, component architectures are good and patterns is awfully good also :)

    But if you don’t use a pattern because the pattern make the code hard to test even if it is the rigth pattern for the job it’s evil.

  13. The design of your business logic / code should be to take a very strict and limited input, throw a tantrum if it doesn’t get it, and produce a predictable result.

    If you choose to apply a design pattern that makes it harder for your code to run when giving it the input it was designed for, and that produces random or uncertain results… well, quite frankly I’ve frightened of that design pattern.

    */foaming at the mouth annoying rant mode*

    Sorry about that… full moon… I kind of turn…

  14. “The class is expensive to create” should be “The object is expensive to create”.

  15. Mike Lively says:

    One of the benefits of unit testing is that it exposes areas of your program that have a high level of coupling. The more coupling you have, the less flexible your code is. So in some senses, designing your code so that it is easy to test can lead to more decoupled code which leads to more flexibility and opportunities for easy re-use. So I would disagree that it is evil to throw out a pattern just because it makes testing easier. Testing is an important aspect of development and one that if it is hard, it is generally ignored (not saying it is right, it is just how it is.)

    The opposing argument is that the more decoupled and ‘flexible’ your code is, generally speaking it is harder to understand because there are more levels of abstraction. I would argue however in the case of singletons you are losing flexibility AND making your code any harder to understand. You cannot look at a class and all of its methods and immediately infer what kind of objects you need to set up before hand.

  16. Mike Lively says:

    yah, what he said…

  17. Tim says:

    So we use this pattern in java. Hopefully my PHP works. To make Singletons testable we combine it with the factory pattern:

    class SingletonFactory {
    private $classToCreate;
    private static $instance;

    __construct($classToCreate) {
    $this->classToCreate = $classToCreate;
    }

    public function getInstance(){
    if(!isset(self::$instance)){
    self::$instance=new $classToCreate;
    }
    }
    }

    class Inventory {
    private static $factory;
    public static getInstance() {
    return $self::factory->getInstance();
    }
    public static setFactory($factory) {
    self::$factory = $factory;
    }
    }
    Inventory::setFactory(new SingletonFactory(“Inventory”));

    Then when you want to write a test you just add the following line to your test:

    Inventory::setFactory(new SingletonFactory(“MockInventory”));

    and you’ll be returned your mock object rather than the standard one.

  18. Justin says:

    Yeah, but it kinda sucks programming wise. I don’t know, there is something about agile/iterative programming that makes Singletons very attractive, because you may not know what all database connections, etc, you might need at what level of code – so you end up with some general way to get at them. I’m in a environment that is filled with a glut of singletons, and its pretty deep in the code, so to work around it, in classes that depend on one, we wrap that in a simple function that is easy to mock. Its not super elegant but it works for now.

  19. The problem is not a singleton, but the hard link to that singleton. Once this knot is untied, kaboom, you can substitute a mock, and do what you want. And test the singleton separately.

    To make it clearer. Any class is a singleton. How do you test a constructor or a factory? :)

  20. Jiri Fornous says:

    The problem of singleton in PHP is late static binding isn’t present yet :) Thus you are unable to extend the singleton proper way and that’s why is better to use the singleton factory – which I recommend too.

  21. Eric says:

    I understand your arguments but the problem is not just black or white and Singletons are usefull in some cases and I just can’t ignore a pattern because it is over or misused.

    For exemple let’s take a log file. It is needed in the whole program. But it is not a dependency of any componant because it is not part of the execution flow.

    For me a Singleton is good for that problem and for other of that kind.

    Is this evil ? I don’t think so ;)

  22. Mike Lively says:

    Like I said, the single instance aspect of a singleton can be useful. It is just the global access aspect that annoys me.

    Using a logging singleton as an example. If you are using a pure singleton and littering your code with Log::getInstance() it does make logging from anywhere relatively simple. However what if you decide to change your logging mechanism, or you want to make your logging mechanism more user configurable. Such as allow logging to either file, syslog, database, or even more than one location etc. You cannot simply extend your log class. Those calls to Log::getInstance() will always be bound to Log. Your only recourse at that point is to rewrite Log to contain the functionality you need, or rewrite Log to no longer be a true singleton.

    I am hoping everyone understands that this is my real point. Singletons aren’t pure evil, they are just sort of evil. If you need to ensure you only have a single instance of an object then they work well. Using them to pull in functionality from what is essentially a global scope, will always limit you.

  23. The code snippets are missing!!! :-(

    Is it ‘cos I’m using Firefox 3?

  24. Swizec says:

    Personally I use singletons as glorified globals on purpose when it makes sense that there should be one object of something that does stuff. Like for example having only one very global template engine object for the whole framework. Why would I need two if I’m only outputing one thing at the end and everything needs to tell that one thing what to output? Makes sense to have a singleton.

    Another occurence when I use singletons as glorified globals is when working with javascript and concurrency. Javascript has a nasty tendency to jump into a callback method that suddenly doesn’t have a reference to its parent object anymore. Singletons can solve this issue very effectively and in a very bloody simple way too.

  25. SocialGeek says:

    I see your point here, a singleton is indeed often abused as a glorified global. Nonetheless, there are some good reasons to use singletons now and then.

    Imagine a standard MVC-structured PHP application with a signed in environment. Of course you are going to use the $_SESSION variable in PHP to store the session information, but what if that is not enough? The $_SESSION variable is but a simple array of data, tying together keys and values. With a nice little singleton class, encapsulating (not the OO-principle) the $_SESSION variable, you gain a lot of flexibility and scalability for your application.
    So nothing wrong with using a singleton-class here …
    Just my two cents of course

    As a final warning, I read some comments where people use singleton classes to create database-objects or connections. I strongly discourage this practice. Your next assignment will probably be to connect and work with multiple databases and multiple connections.

  26. Mike Lively says:

    I think what you are saying actually ties in quite nicely to only utilizing singletons (the getInstance() methods, not necessarly a singleton instance returned from these methods) in your higher level code. For instance I don’t see that much of a problem calling something like Session::getInstance() and passing the results into a front controller to be passed to your other controllers. Then individual properties / method results can be passed to models / views that may need it. I see this as a much cleaner, acceptable design as opposed to Session::getInstance() calls littered throughout all of your controllers and ESPECIALLY your models and views.

    Also, I fully support your comments regarding database objects. This happened at my office. To solve the issue we essentially converted the singleton into a registry. Still not my favorite way to do it, but if you are stuck with a singleton to begin with it is a doable way to solve the problem quickly.

  27. Mike Lively says:

    Remember single object does not mean that object can only be accessed via a global call. You can still pass a singleton instance down to your lower level code.

    I will not argue the simplicity of singletons, they are simple. However it quite often applies that simplicity also brings rigidity with it and in my personal opinion adding a method call or a parameter to your classes and methods to accept an instance of our singleton is normally an acceptable ‘complexity’ for the flexibility you gain with less restrictive dependencies.

  28. Mike Lively says:

    I apologize, this is due to a ‘feature’ of my blog. I’ll get it fixed shortly.

  29. Jessica says:

    Designing an application to be able to test it is evil to me :-) Test should adapt themselves to the application not the opposite!

    Also Registry seems cool at the first glance but in fact it lead to other problems like variable name collision and to give you my feeling about it : Registry is a politically correct Global-Array (so not so cool at the end).

  30. syndrael says:

    May be a great article.. but i can’t see both snippet codes.. on FF3.6.17 and Chromium 14.
    Best regards
    S.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>