Sign in to follow this  
m0nkfish

Singletons

Recommended Posts

OK, so what's the deal here? I understand the concept and the implementation - what I don't understand is why I am constantly being warned against The Evil Singleton. Sometimes the reason is given that it is not a truly OO approach - but if I want to implement a singleton "LawsOfPhysics" then what's not OO about that? Are there multiple instances of the laws of physics in our universe? No! So in a component-based architecture where I want my engine driven by separate component controllers, why the objection to the Singleton design pattern? It seems to fit perfectly.

Share this post


Link to post
Share on other sites
For generalized arguments, read this. And this.

Quote:

So in a component-based architecture where I want my engine driven by separate component controllers, why the objection to the Singleton design pattern? It seems to fit perfectly.

It's actually quite the opposite: it's a horrible fit. One of the purposes of component-oriented design is to increase modularity by encapsulation of behavior and, to a degree, state. Enforcing singularity for no other reason than it 'sounds good' is the antithesis of that. Not to mention all the additional problems is causes, like difficult is isolation of components for unit testing (which components otherwise lend themselves to).

You don't need it, so don't expend the effort to do it.

Share this post


Link to post
Share on other sites
This might go a few pages :)

One thing about the singleton pattern is that it says that not only is there only one LawsOfPhysics object, but that there can ONLY be one LawsOfPhysics. And if you later want to create maps that have rooms with alternate LawsOfPhysics, you have a lot of work ahead of you.

You have a lot less work if you just created a normal LawsOfPhysics class, and just passed it as a dependency to objects that need it in the first place.

Speaking of dependencies, the singleton pattern makes unit testing a huge pain. You can't inject a test version of your LawsOfPhysics class into a class you are trying to test to see how it's using LawsOfPhysics, without doing a lot of work.

Also that LawsOfPhysics is suddenly available to classes that have nothing to do with physics (like UserLogin, or Sprite). Do you really want your architecture to be that messy?

And, lets not forget static initialization and thread safety issues, language depending.

In general, the evil of using singleton comes about when the real case is not "There can only ever ever be one of these" but "I only have one of these right now, and it's easy to use a singleton whereever."

Share this post


Link to post
Share on other sites
The problem with Singletons is that you never knew you needed one until you discover this "wonderful pattern". So you spend a while putting them into your project. Later on, you will realise that you have gained little or nothing in doing so. Worse - your code can start becoming more rigid and inflexible. It is harder to unit test, harder to reuse, harder to refactor, harder to reason about.

The above happened to me. It has happened to other people on these forums.

With experience I have learned that 99.999% of classes are not restricted to a single instance. I have also learned that global access is also not right for most code. That is of course in theory, I often find that a global can work as a temporary solution when hacking in a new feature. Sometimes we have to work within constraints where we can't afford to spend the time necessary to properly integrate the feature with an existing design.

Oh, and the LawsOfPhysics? What if next week you want to create a different Universe with different laws? Your thinking is warped by the assumption that the Universe itself is a Singleton.

I am afraid I disagree [smile].

Share this post


Link to post
Share on other sites
Quote:
Original post by m0nkfish
OK, so what's the deal here? I understand the concept and the implementation - what I don't understand is why I am constantly being warned against The Evil Singleton. Sometimes the reason is given that it is not a truly OO approach - but if I want to implement a singleton "LawsOfPhysics" then what's not OO about that?


LawsOfPhysics has no local state. As such, it should be expressed using free functions.

FrameOfReferenceComponent however not only has local state, but each observer has one.

For example, while LawsOfPhysics on person orbiting earth in space shuttle and person free falling in an elevator in vacuum shaft would be simiar, to an outside observer they would be completely different. As such, laws of physics depend on individual frame of reference.

Do you realize, that while writing this message, you're moving at about 30km/s.
That this is only along Earth's orbit around Sun. Not considering for velocity of our solar system around center of galaxy. While the universe is expanding at accelerated rate.

And the best thing - the above calculation is different for each one of us, due to relativistic effects, which directly affects our perception of time, and consequently all calculations.

So unless LawsOfPhysics simulates everything with mass in our entire universe, it cannot calculate your current velocity or acceleration, or anything else.

Singletons need to know too much, so we use local instances to simplify things. And we make one universe for use on earth, one for astronauts, one for orbital mechanics, one for solar system's motion of planets, one while we're in a car, one in an elevator, one in ....

Share this post


Link to post
Share on other sites
Quote:
Original post by m0nkfish
Sometimes the reason is given that it is not a truly OO approach - but if I want to implement a singleton "LawsOfPhysics" then what's not OO about that? Are there multiple instances of the laws of physics in our universe? No!
Sure there can be... very large masses or masses that move at high velocity might more appropriately use a relativistic physics system. You might also have a situation where a physics system should put more emphasis on quantum physics. And, of course, in many cases a simpler Newtonian model is more appropriate.

There is no reason to think that you might not want more than one of those running in the same process.


Share this post


Link to post
Share on other sites
The point of writing a class is to define a data type. There's next to no point to giving and explicit name to the type of something that is unique.

If it's important that some collection of data is created only once, wrapping it up in a Singleton simply means that you have to go out of your way to write a class definition - implicitly creating the ability to re-create the data - and then go out of your way again to take that ability away.

Share this post


Link to post
Share on other sites
So much hate for poor, poor singlton.

Like the auto_ptr, it might have a use in some places and like multiple inheritance, if you want to use it, that's your decision and it's your decision whether to let other people form your opinion on your use of it. Couldn't I consider my OS a singleton? (Host OS?)

I personally don't think it's the best thing I ever heard, preferring a plain old global if I'm going to go that rout. The thing I don't like about it is the initialized on first use principle. If it's global, it's already initialized before its first use. That principle just creates annoying overly complicated getInst() crap. (And if your application is threaded, overly complicated "Double Checked Locking Pattern".)

Quote:
Original post by someboddy
What if I have an Highlander class? Can I make it a singleton?

There can be two, but you shouldn't have one male and one female together.

Share this post


Link to post
Share on other sites
From personal experience they are best avoided, but when wrapping a c style library in a series of classes to enhance functionality I found it difficult to dodge a singleton. The special circumstances are that first, SDL_Mixer isn't really multi-instancable because it is based on several c functions which share a single state. And the second is that to implement a play list it seems you require a basic c style function pointer. At the time I knew of no way to cast between a class specific member function and a global c function, but I believe that mem_func would probably do what I need (though when I was having this issue nobody suggested it.)

In any case, it was a decent use of a singleton because the actual concept being wrapped could not safely have several instances without each instance knowing about the other ones so we knew if it was initialized and playing etc.

Nobody suggested a better alternative in this thread:

http://www.gamedev.net/community/forums/topic.asp?topic_id=520472

Share this post


Link to post
Share on other sites
Quote:
Original post by M2tM
From personal experience they are best avoided, but when wrapping a c style library in a series of classes to enhance functionality I found it difficult to dodge a singleton. The special circumstances are that first, SDL_Mixer isn't really multi-instancable because it is based on several c functions which share a single state. And the second is that to implement a play list it seems you require a basic c style function pointer. At the time I knew of no way to cast between a class specific member function and a global c function, but I believe that mem_func would probably do what I need (though when I was having this issue nobody suggested it.)

In any case, it was a decent use of a singleton because the actual concept being wrapped could not safely have several instances without each instance knowing about the other ones so we knew if it was initialized and playing etc.

Nobody suggested a better alternative in this thread:

http://www.gamedev.net/community/forums/topic.asp?topic_id=520472
I dealt with this also while building a framework around SDL_mixer, but didn't use a singleton. The problem here (if you want to call it that), is that the class in question only meets one of the 'singleton' criteria: it would be an error (more or less) for there to be more than one instance.

However, the other criteria - that global access is needed (or even desirable) - doesn't really apply here. Under normal circumstances only a small percentage of game code will need access to the sound system; as such, I'd argue that a singleton isn't really an appropriate solution here.

I ended up deriving the 'sound system' class from a 'single instance' base class that throws an exception if more than one of the derived type is created, and used static functions where C-style callbacks were needed. Not ideal perhaps, but I do think it's a better solution to the given problem than a singleton (at the very least, it shows that there are other solutions to this sort of problem besides using a singleton).

Share this post


Link to post
Share on other sites
Quote:
Original post by Splinter of Chaos
Couldn't I consider my OS a singleton? (Host OS?)

No. A singleton is instantiated per process creation, while an OS is instantiated per bootup.

Share this post


Link to post
Share on other sites
Problem is that singletons are often used to enable global access, rather than control instantiation. They're often basically used as an "OO-compliant" version of globals (which isn't really the purpose).

Instead, they should be used when only ONE instance of the class should ever be instantiated... as in "bad things will happen if there are two of these around." If the singleton still implements an interface, you can still pass it to objects via dependency injection.

So they're not inherently bad, just almost always misused. Sniff test: A singleton that doesn't implement an interface is most likely a misuse of the pattern.

Share this post


Link to post
Share on other sites
Quote:
Original post by jyk
Quote:
Original post by M2tM
From personal experience they are best avoided, but when wrapping a c style library in a series of classes to enhance functionality I found it difficult to dodge a singleton. The special circumstances are that first, SDL_Mixer isn't really multi-instancable because it is based on several c functions which share a single state. And the second is that to implement a play list it seems you require a basic c style function pointer. At the time I knew of no way to cast between a class specific member function and a global c function, but I believe that mem_func would probably do what I need (though when I was having this issue nobody suggested it.)

In any case, it was a decent use of a singleton because the actual concept being wrapped could not safely have several instances without each instance knowing about the other ones so we knew if it was initialized and playing etc.

Nobody suggested a better alternative in this thread:

http://www.gamedev.net/community/forums/topic.asp?topic_id=520472
I dealt with this also while building a framework around SDL_mixer, but didn't use a singleton. The problem here (if you want to call it that), is that the class in question only meets one of the 'singleton' criteria: it would be an error (more or less) for there to be more than one instance.

However, the other criteria - that global access is needed (or even desirable) - doesn't really apply here. Under normal circumstances only a small percentage of game code will need access to the sound system; as such, I'd argue that a singleton isn't really an appropriate solution here.

I ended up deriving the 'sound system' class from a 'single instance' base class that throws an exception if more than one of the derived type is created, and used static functions where C-style callbacks were needed. Not ideal perhaps, but I do think it's a better solution to the given problem than a singleton (at the very least, it shows that there are other solutions to this sort of problem besides using a singleton).


I agree with you, the primary reason for the decision to actually make it a singleton was because I thought I needed a global access point in order to get an instance of my class from within the c global function callback it registered to. This then meant that it fulfilled both requirements (as far as I knew at the time).

That said, I believe it could be avoided with mem_func but I haven't implemented it yet. Provided that works as intended it would no longer need to be a singleton and I could enforce the single instance in a similar manner to what you describe.

Anyway, a round-about way of admitting I used a singleton because it seemed to be a good idea and it certainly isn't a terrible application for the pattern (indeed, it's a better candidate than most) but in reflection it may have been unnecessary and thus a better solution could be present.

Share this post


Link to post
Share on other sites
Quote:
Original post by kyoryu
Problem is that singletons are often used to enable global access, rather than control instantiation. They're often basically used as an "OO-compliant" version of globals (which isn't really the purpose).

Instead, they should be used when only ONE instance of the class should ever be instantiated... as in "bad things will happen if there are two of these around." If the singleton still implements an interface, you can still pass it to objects via dependency injection.

So they're not inherently bad, just almost always misused. Sniff test: A singleton that doesn't implement an interface is most likely a misuse of the pattern.


What he said. The problem with the Singleton is misuse. They are fine for making sure one instance exists, they can also help in cases where you need control over the order of instantiation of an object. Both of these are valid reasons to use a mechanism that helps with that.

However, it's a much rarer case where you need a global point of access to something. This is part of the singleton definition, but it is the controversial one too. Even if you do have that global point of access, as kyoryu says there is nothing to stop you passing the object around via dependency injection. This is valid because the code using the singleton often has no use for the knowledge of whether something is globally accessible and taking that into account does get you around the decoupling problems.

The problem with the singleton pattern is the lack of defence against misuse. It's very common to be misled by it, taking a path that initially looks like an easier one. Almost every C++ programmer has fallen for that one.

Also, don't fall into that laws of physics example. I know plenty of games that have been tweaked to be playable simply by fiddling with the physics on a level by level, object by object basis.

Share this post


Link to post
Share on other sites
A global point of access is required for a singleton so that you can actually *find* the thing. If there's only one of the thing lying around, it must have a globally known access point, or you wouldn't be able to get to it.

It is not, however, a *feature* of a singleton, and the use of the singleton pattern shouldn't be based on the global accessibility. Control of instantiation (both number and timing) is the *feature* of the singleton.

Share this post


Link to post
Share on other sites
Quote:
A global point of access is required for a singleton so that you can actually *find* the thing. If there's only one of the thing lying around, it must have a globally known access point, or you wouldn't be able to get to it.
How so? I have a number of objects in my framework that are the only one of their type (a constraint that is enforced), but they aren't globally accessable; rather, they're created locally and then passed forward as necessary.

Or are we talking about different things?

Share this post


Link to post
Share on other sites
Well, you could do that by making the class private, and inheriting from some base class, I guess, but at that point that class isn't particularly usable by anybody except that particular implementation.

I'd probably argue that what you're doing is closer to the "intent" of the singleton pattern than the common usage of it.

I'm basically asserting that the common usage of the singleton pattern (MySingleton::GetInstance()->... in all kinds of places) is really just a global with a pretty wrapper. People use it like that, IMHO, because globals are really convenient, and wrapping it in a design pattern (even if it's being misused) somehow blesses the global.

Share this post


Link to post
Share on other sites
I don't buy the anti-singleton statements on this forum. Yes, they can be misused, yes, there are alternate solutions to "solving" the problem, but find me something in programming that can't be misused or done differently. I don't see why singletons get any special attention.

If you want to use a singleton, I say go for it, just make an educated decision and know the pros/cons of your choice.

Share this post


Link to post
Share on other sites
Quote:
Original post by gekko
I don't buy the anti-singleton statements on this forum. Yes, they can be misused, yes, there are alternate solutions to "solving" the problem, but find me something in programming that can't be misused or done differently. I don't see why singletons get any special attention.

If you want to use a singleton, I say go for it, just make an educated decision and know the pros/cons of your choice.


The problem with them imho is primarily that they hide dependencies and you can get very obscure results with unrestricted global access and they are not multi-instancable which makes test suites with projects with many singletons difficult to run...

Most cases where people use a singleton there is no real reason why there can't exist more than one instance of the object, I had an example where it would be an error to have more than one instance, but even asserting that you have a true example of a single instance requirement the global access point is prone to enabling messy code and still hides dependencies.

Here is a decent video presentation of the case against Singletons.
http://ca.youtube.com/watch?v=-FRm3VPhseI

I don't believe that they are evil, but before you use one make -sure- other possibilities have been exhausted and that the cleanest and best option is a Singleton.

See my comment for the highlight of the presentation:

Share this post


Link to post
Share on other sites
Quote:
Original post by kyoryu
Problem is that singletons are often used to enable global access, rather than control instantiation. They're often basically used as an "OO-compliant" version of globals (which isn't really the purpose).

Instead, they should be used when only ONE instance of the class should ever be instantiated... as in "bad things will happen if there are two of these around." If the singleton still implements an interface, you can still pass it to objects via dependency injection.

So they're not inherently bad, just almost always misused. Sniff test: A singleton that doesn't implement an interface is most likely a misuse of the pattern.


Word.

It's funny to watch these threads pop up regularly..

I think Singletons are a hapless victim of people's love affair with OOP. I guess we all have to hate something.

Share this post


Link to post
Share on other sites
Quote:
Original post by scratt
Quote:
Original post by kyoryu
Problem is that singletons are often used to enable global access, rather than control instantiation. They're often basically used as an "OO-compliant" version of globals (which isn't really the purpose).

Instead, they should be used when only ONE instance of the class should ever be instantiated... as in "bad things will happen if there are two of these around." If the singleton still implements an interface, you can still pass it to objects via dependency injection.

So they're not inherently bad, just almost always misused. Sniff test: A singleton that doesn't implement an interface is most likely a misuse of the pattern.


Word.

It's funny to watch these threads pop up regularly..

I think Singletons are a hapless victim of people's love affair with OOP. I guess we all have to hate something.


Did you even read the real and tangible reasons for avoiding them?

Share this post


Link to post
Share on other sites
Quote:
Original post by M2tM
Quote:
Original post by scratt
Quote:
Original post by kyoryu
Problem is that singletons are often used to enable global access, rather than control instantiation. They're often basically used as an "OO-compliant" version of globals (which isn't really the purpose).

Instead, they should be used when only ONE instance of the class should ever be instantiated... as in "bad things will happen if there are two of these around." If the singleton still implements an interface, you can still pass it to objects via dependency injection.

So they're not inherently bad, just almost always misused. Sniff test: A singleton that doesn't implement an interface is most likely a misuse of the pattern.


Word.

It's funny to watch these threads pop up regularly..

I think Singletons are a hapless victim of people's love affair with OOP. I guess we all have to hate something.


Did you even read the real and tangible reasons for avoiding them?


Yes. I also use them daily, and am aware of all the pitfalls. But I still attest they have their uses, and their are often times they are a good solution to a problem.

Elitism is not something I aspire to.

Share this post


Link to post
Share on other sites
Nobody said anything about elitism. What are you talking about? Discussing technical merits and pitfalls and suggesting it is a good idea to avoid global data when possible does not equal elitism at all.

It's pretty a basic object oriented principle that you should avoid doing things that subvert encapsulation and introduces ambiguous dependencies. Because the Singleton pattern deals with objects and is easily misused it is not unreasonable to stress the importance of very, very careful consideration before implementation. Typically they are more indicative of design failure than a genuine need to actually use them.

Give some examples of where you think the Singleton design pattern is a good idea if you're set on proving a point. Otherwise you are spouting conjecture without any real specific reasons to back up an argument for Singletons. I myself have provided an example of a good candidate for Singleton use, but there aren't many. If you can paint a picture of exactly what situations you think call for a global single instance with real examples I'll take you more seriously.

The unsubtle and completely unrelated jabs at the community combined with the vague condescending tone don't do it for me.

[Edited by - M2tM on January 22, 2009 5:08:48 AM]

Share this post


Link to post
Share on other sites
Quote:
Yes. I also use them daily, and am aware of all the pitfalls. But I still attest they have their uses, and their are often times they are a good solution to a problem.

Elitism is not something I aspire to.
The issues people tend to bring up with respect to singletons are pretty cut and dried, so I don't think it's really an issue of elitism. It may very well be that your own use of singletons is fully justified. However, on these forums at least, when someone says that 'singletons have their uses', it seems that 9 times out of 10 it turns out they're talking about a texture cache or some other object that doesn't meet either of the design criteria associated with the singleton pattern. Because of this, I think we tend to be a little skeptical when someone says that they find the singleton to be a useful pattern (especially when no supporting examples are given).

As for elitism, let me just say right now that there's a lot to be said for 'getting the job done' and using whatever techniques, patterns, or tools you feel most comfortable with. However, keep in mind that a lot of these 'singleton' threads are targeted towards (and read by) folks who are early in the development process and have yet to commit to a particular approach. In this case, I think it's perfectly justified (and not elitist) to put forth the arguments for and against singletons in no uncertain terms, so that beginning developers are better equipped to make good design decisions early on.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this