Why such an aversion to the Singleton Pattern?

Started by
117 comments, last by Dmytry 16 years, 2 months ago
I've read many, many times here that Singletons should be avoided like the plague, but I'm unclear on the reason for this. Obviously abuse of any design pattern isn't good, but why such an aversion to the Singleton? In my project I have designed the application such that I can control most of the overall parameters through a parameters file. I can control placement of characters, maps, etc using this file and the parameters involved impact the whole application. Rather than reload the file multiple times, I created the ParameterMap class as a Singleton such that I load the parameter file once, then anywhere I need to access a parameter, I simply create a ParameterMap object and find the information I need. -Kirk
Advertisement
Quote:Original post by kirkd
I've read many, many times here that Singletons should be avoided like the plague, but I'm unclear on the reason for this. Obviously abuse of any design pattern isn't good, but why such an aversion to the Singleton?

In my project I have designed the application such that I can control most of the overall parameters through a parameters file. I can control placement of characters, maps, etc using this file and the parameters involved impact the whole application. Rather than reload the file multiple times, I created the ParameterMap class as a Singleton such that I load the parameter file once, then anywhere I need to access a parameter, I simply create a ParameterMap object and find the information I need.

-Kirk


Singletons are globals. Any criticism you heard about globals also applies to singletons. The only real advantage to singletons is that you know they will always be constructed whenever they are needed. Past that, they're globals. So, immediately you introduce extra dependencies when a class makes use of a singleton and it does not allow the class using the singleton to make use of different behavior via polymorphism. These dependencies make refactoring very difficult. Oftentimes, instead of using a singleton, you could use an interface reference as a parameter to the constructor of your class, store the reference, and call back upon this. The benefit is that the behavior is what this class actually is will be hidden from your class, thus you can change behavior without rewriting, and actually use different implementations in different parts of the system.

Here's a quick sample:

class ParamInterface{public:    ParamInfo getParam() const = 0;};class LogicComponent // dumb name just to prove the point{public:    LogicComponent(ParamInterface& p_paramInterface) :        paramInterface_(p_paramInterface)    {    }    ...    void doStuff()    {        ...        param = p_paramInterface.getParam(); // implementation could be anything derived from that interface        ...    }private:    ParamInterface& paramInterface_;};


That's a lot cleaner than the singleton pattern in the long run for many cases. Any time people start talking about something that's global to an entire application, it gets scary because it locks you in to a specific framework and only allows a single implementation that is suitable for the entire application.
See "Singleton Considered Stupid".
What's wrong with having a singleton class for manager classes, etc? Typically many classes will depend on the manager. You could pass a pointer to it in the constructor, but this gets annoying and I don't think makes it any easier to maintain than a singleton.

I'm sure singletons can be abused like anything. But they are sometimes convenient.
-----Quat
From that article linked to:

Quote:
Anyway, I liked Singleton for the same reason everyone does: it's almost exactly the way I programmed back when I didn't know jack squat about OOP. The only significant difference is that instead of having a file with a bunch of global functions in it, I have a file with a CLASS that has a bunch of global functions. No need to worry my little head about how many of them to have, since you only need one! It's OOP made easy.


Well, it is pretty obvious he was not using the pattern correctly, if he just used it to dump functions in it.
-----Quat
Required reading - a whole bunch of articles and forum discussion which explains why singletons are basically a really bad idea.
Quote:Original post by Quat
What's wrong with having a singleton class for manager classes, etc? Typically many classes will depend on the manager. You could pass a pointer to it in the constructor, but this gets annoying and I don't think makes it any easier to maintain than a singleton.

I'm sure singletons can be abused like anything. But they are sometimes convenient.


It ultimately has to do with the implicit assumption that there is one implementation for everything in your entire application. This enforces that the implementation has to be there: you can't take an otherwise reusable class out and put it in a different application without bringing over your singletons and their implementations too = dependencies. Furthermore, you can't specify different behavior (implementations) for different parts of your system. Every part of the system gets the same stuff = dependencies.

From experience, I will say, in my experience, that about 50% of the time an assumption is made about global applicability, it is wrong. Why intentionally write code that makes refactoring harder?

This is not to mention that the order of destruction and deallocation is undefined (if you even make an attempt to deallocate at all?). If you have singletons that depend on other singletons... good luck, you'll need it.
Quote:Original post by Quat
Well, it is pretty obvious he was not using the pattern correctly, if he just used it to dump functions in it.


That was sort of his point... there is very little functional difference between using it "correctly" (calling getInstance(), and then a method) and just having a class with a bunch of static functions in them. He was illustrating that the singleton pattern is, in fact, a group of global functions with an OOP facade.
I can certainly see the argument for classes that define significant behaviors. You are tied to a particular implementation of a function. But back to my ParameterMap - if all I'm doing is asking "what is the value for this parameter" why is it wrong to use a singleton to contain the parameters of interest?
Like many programming pitfalls, the dangers of the Singleton tend to be proportionate to the amount of code using it.

When you start using them, they are easy. The more code that depends on them, the harder they get. Removing them from a massive code base can be a nightmare.

I've tried Singletons back when I was naive (well, considerably more naive anyway [smile]). I thought they were great. As my program grew, I learned the truth. Debugging code is hard when execution may at any time jump into a Singleton. Trying to follow code you've written is difficult.

It is hard to put into words. The reason we strongly criticise them is that a beginner cannot guess the evil to come when they decide to make their renderer (or whatever) a Singleton. Typically, there is some kind of giddy phase in C++ when one discovers a Singleton template, all of a sudden you get a bunch of "manager" objects that "need" to be Singletons for no particular reason.

Singletons are usually used a substitute for actual design, in my opinion.

This topic is closed to new replies.

Advertisement