[SOLVED] Singleton Patterns - Controversy

Whether you're a newbie or an experienced programmer, any questions, help, or just talk of any language will be welcomed here.

Moderator: Coders of Rage

User avatar
EccentricDuck
Chaos Rift Junior
Chaos Rift Junior
Posts: 305
Joined: Sun Feb 21, 2010 11:18 pm
Current Project: Isometric "2.5D" Airship Game
Favorite Gaming Platforms: PS2, SNES, GBA, PC
Programming Language of Choice: C#, Python, JScript
Location: Edmonton, Alberta

[SOLVED] Singleton Patterns - Controversy

Post by EccentricDuck »

Since finishing exams, I've gone back to my XNA game and hit my "Programming Game AI by Example" book so that I can put some AI entity's into my game (since it currently relies solely on pvp gameplay which would be prohibitive if no one else was online to play). The book seems to start pretty strongly with Singletons - something I've used quite a bit in my XNA project as well as somewhat in my Java framework. To me, so far, it's seemed like a relatively intuitive way of designing complex systems without passing crap all over the place. It gets those hard dependencies out in the open and makes them easier to track (in my limited experience) by defining a system that handles them (as opposed to stringing references through your code by passing them through one object to another object to another object... which I find stupidly hard to keep track of).

There seems to be a lot of controversy over their use, particularly in C++ (I've read less commentary pertaining to Java/C#). This thread is a good example:
http://www.gamedev.net/community/forums ... hichPage=2

One member in that thread seemed to feel that most advocates of singletons were less experienced developers who found a convenient fit to a difficult design decision, while the more experienced developers banned them completely after they became a headache. I think I can understand some of the reasons why they're not preferred. I've sat here mulling it over and reading more, and I can see some of the points that are being made. In my mind, I think the reason that it seems so intuitive is that I'm designing the system and it seems like a logical and easy to keep track of structure, but I imagine that as my focus shifts to other structures it may become less clear what I was thinking at the time I designed it. The thing is, this happens with anything but the simplest of systems anyway - and a system that revolves around a common reference point seems better, in my mind, to keep that structure tight and easy to follow when compared to dropping references here and there through out my code.

This is all off track of the task I had in mind (programming a simple AI agent so that single player is an option) when starting this book , but since I've been leaning toward such heavy use of the singleton pattern, I thought it would be a good idea to analyze that decision. It won't change my XNA project's design since aside from integrating AI, the last big task, all I need to finish is text/textures in the menu interface and HUD and potentially add leaderboards - but I may approach the framework I've been developing in Java from a different angle.

What advice/thoughts/opinions do some of the more experienced programmers here have? The thread I linked above was a good read, but there's a lot of devs there who openly admit that they are strongly against global variables in every sense, so I wonder how much bias may be clouding their judgement. Additionally, I didn't see many suggestions as to how to build a better system, other than a brief mention of creating an eventhandler.
Last edited by EccentricDuck on Thu Dec 16, 2010 3:37 am, edited 2 times in total.
User avatar
dandymcgee
ES Beta Backer
ES Beta Backer
Posts: 4709
Joined: Tue Apr 29, 2008 3:24 pm
Current Project: https://github.com/dbechrd/RicoTech
Favorite Gaming Platforms: NES, Sega Genesis, PS2, PC
Programming Language of Choice: C
Location: San Francisco
Contact:

Re: Singleton Patterns - Controversy

Post by dandymcgee »

The best argument I've see regarding singletons is that they are never really necessary. Think about it, there are certain classes that only ever need to exist as a single object but is there really a legitimate reason to FORCE this? There are thousands of other ways to screw up a program so do you really need to protect the user of your class that much (especially if the only user is YOU)?

Another reason the singleton pattern is commonly chosen is the global access it provides to an object. Yet no respectable programmer would be caught dead still asking "why are global variables bad design?" However, there are times when it's the quickest way to make an objects accessible from anywhere. Falco has stated a few times that he is still using it to represent his debug class in ES, but has eliminated it from all other aspects of the engine. This doesn't upset the actual engine architecture because the debug class is kept fairly isolated from everything.
Falco Girgis wrote:It is imperative that I can broadcast my narcissistic commit strings to the Twitter! Tweet Tweet, bitches! :twisted:
User avatar
EccentricDuck
Chaos Rift Junior
Chaos Rift Junior
Posts: 305
Joined: Sun Feb 21, 2010 11:18 pm
Current Project: Isometric "2.5D" Airship Game
Favorite Gaming Platforms: PS2, SNES, GBA, PC
Programming Language of Choice: C#, Python, JScript
Location: Edmonton, Alberta

Re: Singleton Patterns - Controversy

Post by EccentricDuck »

dandymcgee wrote:Another reason the singleton pattern is commonly chosen is the global access it provides to an object. Yet no respectable programmer would be caught dead still asking "why are global variables bad design?"
That's the thing though, I see it again and again in code examples. This book which I started on, which seems to be a fairly well respected and recommended book on game AI, uses a singleton for every single state that an AI agent might be in with a Finite State Machine. I see singletons used in several (Microsoft created) XNA examples to represent various system/subsystem managers. The main reason for their use seems to be that they are a single go-to handler of some type that can be referenced by all the components that need them without passing lots of references around and creating obscurity in that way (both cases create coupling).

[I've certainly had some initial frustration with the examples I've seen for XNA developers. They work, but for someone who's uninitiated to the details of the system it can be a major pain to navigate. What seems implicit and intuitive when you start out with a concept of the structure winds up being incredibly complex until you get a good sense of that structure. As the guy developing a framework using singletons I can understand why I might have a bias toward them since I have a pre-built model in my head where they fit in incredibly nicely (I don't really have to deal with what it's like to navigate through and build that mental model from scratch). Perhaps this is part of the double edged sword of singletons - they are intuitive when you have a strong mental model from the get-go, but they're not as intuitive when it's not fresh in your mind.]

I understand why global state is a bad thing, in general, but the issue is that I see several code examples that make use of the singleton pattern which seem to work well, and I see a lack of strong examples which give an alternative approach. Especially in languages with managed memory (like Java and C#), you can have a class create a single object of itself with a static reference and then not have to worry about how to go about garbage collection (since it's a stand-alone object not implemented in a hierarchy which is a pain when it comes time to clean up without managed memory). If the issue is global access and modification, then fine, but what would be a better way to structure it. You need to have some sort of cohesive structure to implement your logic, and if you're dealing with objects then inevitably some will need to be coupled to others. Why not use a singleton, and more importantly, what exactly is a better solution? I'm sure that there are several answers to both questions, depending upon the situation, but there must be some good solid examples that can be contrasted with the singleton pattern so that: a) it can be pointed out why a singleton might be problematic in a particular case, and b) a solid solution can be shown that can replace the old design.
User avatar
Falco Girgis
Elysian Shadows Team
Elysian Shadows Team
Posts: 10294
Joined: Thu May 20, 2004 2:04 pm
Current Project: Elysian Shadows
Favorite Gaming Platforms: Dreamcast, SNES, NES
Programming Language of Choice: C/++
Location: Studio Vorbis, AL
Contact:

Re: Singleton Patterns - Controversy

Post by Falco Girgis »

Singletons are a horrendous, fuck-ugly, bastardizing, brainless, degenerative, counterproductive design pattern that completely destroys not only the entire point of object oriented design, but also the programmer's ability to think in terms of an object-oriented paradigm. They should be avoided like the plague or a ravenous rectal STD.

My rant
I fucking hate singletons. I have spent dozens upon dozens of hours rewriting shit code that utilized them. They plagued our original engine and eventually caused a rewrite. I have seen good programmers produce code and projects that were absolute shit because of them. Our latest toolkit endeavor actually just required a 2 day (and I mean 10 hours per day) rewrite because a SINGLE CLASS was a singleton.

The ONLY, and I mean only, time that I EVER use them these days is for a static debug class that I quite literally wish to be able to pull out of my asshole at any given moment from any given function. I would never implement any important class or piece of functionality as a singleton.

I was once a huge believer and supporter of the design. I too thought that abuse came from using them in an abundance and could not think of more elegant ways to implement the same kind of functionality. Then I fell into the gigantic trap that literally hindered my ability to think as an object-oriented programer. I have since completely changed my mind about the design pattern and have changed my ways...

My Philosophy
What is a singleton at the core? Is it two things 1) a way to ensure that only one instance of a class may be created during a program's execution and 2) a method of pulling an instance out of your asshole from anywhere at any given point in time. Number 2 is the reason that singletons are reasting pieces of shit all the way to their core. Number 1 may be implemented in a plethora of different ways NOT utilizing a singleton and not breaking object oriented design.

The fact that you can literally pull a singleton out of your ass from thin air (thanks to a static get function) is the reason that newbies are so drawn to it: it takes the hard part away from object-oriented programming. Suddenly you don't have to map out complex interactions and communications between objects. Your software is no longer an elegantly architectured symphony of independent or semi-independent "objects" communicating in a manner that allows your program to be modular--it is a reasting piece of shit that now has spiderweb dependencies upon everything with a program flow that is literally untraceable.

You have now completely destroyed the biggest and most important task in the field of software engineering: software design. You might as well not be using C++ anymore. At least in C, the behavior of any function calling any other function (and static "states") is acceptable.

No, I'm not exaggerating
Yes, you say. This is all true if you use too many singletons. I assure you, a SINGLE misused singleton can literally cause a mighty software endeavor to fail.

Marcel had found a seemingly legitimate reason to employ a singleton in our latest QT Toolkit endeavor. In QT, your main window encapsulates every single widget within the user interface. Within any GUI piece of software, you probably have dozens and dozens of classes that manipulate the UI in some manner. If many things such as this are changing the UI, would it not make sense to allow anything to access this main toolkit class to gain access to the UI? Would this not be a justifiable singleton?

What we wound up with was a Toolkit in which every single class depended upon (or was able to pull out of its asshole) the ESToolkit main class. Suddenly anything from anywhere in the program was able to manipulate the state of the main UI. We had widgets that were supposed to be completely independent of one another pulling the ESToolkit reference out of their asses to manipulate other widgets. So not only did every widget depend upon the class containing them, but they were also dependent upon the other widgets whose actions they were effecting.

In QT, the signals and slots mechanism is meant to facilitate communication between independent objects such as these (just like delegates in C#, and function pointers (as a much uglier and more primitive example) in C). With this, you are able to register multiple "slots" to be invoked when an object emits a "signal." This allowed each UI element to remain independent of other UI elements (and classes manipulating them). This signal/slot relationship is initialized by the main ESToolkit class which CONTAINS these individual, modular objects/widgets. Thus OO is preserved.

Alternatives
So lets return back to the ONLY justifiable reason to implement a singleton: to create a single static instance of an object/piece of data that may be accessed by CLASSES WITH A GOOD REASON to access that data.

Let me give two examples.

1) Our engine is area-centric. This means that every subsystem within our engine is operating upon a single object that encapsulates all data for the level (tiles, objects, components, entities) within a pretty little structure. These subsystems operate upon this structure every frame (WarpSystem manages WarpComponents, ItemSystem manages ItemComponents, etc.) Keeping this data all encapsulated in one location allows us to simply provide a pointer to each subsystem to enable it to do its job. This allows us to easily have multiple areas in RAM and simply swap a single pointer to change areas (with no unloading and reloading of entities/components if each subsystem had ownership of what it was operating on).

2) The toolkit works in the same manner. There is a giant AssetManager class that encapsulates "Projects" which each have their own "Levels" which each have their own "Areas." Whether you simply be clicking map locations to lay tiles, rename some sort of asset, manipulate an individual component or entity, each widget/window is generally operating upon this chunk of data.

The solution? A static pointer that each class (having business to do so) may inherit from.

Code: Select all

class AssetManager {
    friend class WHATEVER;
    private:
        static Area *_currentArea;
        static Level *_currentLevel;
        static Project *_currentProject;
    protected:
       Area *getCurrentArea() const;
       Level *getCurrentLevel() const;
       Project *getCurrentProject() const;
};
Now any class that requires access to the current project, level, or area to do its job may simply inherit this static data to get its shit done:

Code: Select all

class WarpSystem: public AssetManager {
    void Update() {
        for(unsigned int i = 0; i < getCurrentArea()->warps.size(); ++i) {
            //Do my job.
        }
    }
}
Now whatever class is responsible for allocating this Level/Project/Area/Static piece of data is the ONLY thing that can set this static pointer (the WHATEVER friend class in the example).

Code: Select all

class LevelManager {
    bool SwapLevels() {
        _currentLevel = some other pointer;
    }
}
With this method you have 1) ensured that any deserving class has access to some shared piece of data 2) Ensured that only one instance of this shared data is instantiated (by whatever is setting the initial static pointer) 3) Have NOT violated an object oriented paradigm.
User avatar
Arce
Jealous Self-Righteous Prick
Jealous Self-Righteous Prick
Posts: 2153
Joined: Mon Jul 10, 2006 9:29 pm

Re: Singleton Patterns - Controversy

Post by Arce »

But PHOENIX SINGLETONS are so fucking cool! ;p
<qpHalcy0n> decided to paint the office, now i'm high and my hands hurt
User avatar
Arce
Jealous Self-Righteous Prick
Jealous Self-Righteous Prick
Posts: 2153
Joined: Mon Jul 10, 2006 9:29 pm

Re: Singleton Patterns - Controversy

Post by Arce »

Though I must say, that solution is quite elegant. By far one of the coolest I've seen!
<qpHalcy0n> decided to paint the office, now i'm high and my hands hurt
qpHalcy0n
Respected Programmer
Respected Programmer
Posts: 387
Joined: Fri Dec 19, 2008 3:33 pm
Location: Dallas
Contact:

Re: Singleton Patterns - Controversy

Post by qpHalcy0n »

I can only think of one acceptable usage for a singleton and that is a logger of some sort.

The problem with them is that on the surface they seem very benign. I can't help but note the amount of times you've said "seems to work fine" in your post there. On cursory glance, this may be true. When the code begins to get extremely intricate and lengthy, this will quickly turn into your worst nightmare. Having said that it becomes a testing nightmare and I speak from experience. In one of my projects, me and a team of 5 managed about 3/4 of a million lines of code. The problem occurs when you incur some form of runtime exception and the culprit turns out to be rooted in some improper usage of a singleton that is too "tentacular" (my word for having many tentacles). In other words its object tree is just TOO deep. So then it means that any object that the singleton can see the invoker of the singleton can see and its REALLY not fun hunting through 750k worth of code or traversing an exceptionally deep call stack trying to root out who did what to the state because there's simply no other way to do it.

Another problem that nobody ever seems to bring up is actually one of the bigger problems and led me to detest them altogether. There's hardly no code that I write anymore that is not threaded out the ass. The singleton is the worst nightmare for concurrency imaginable. Simply because when you introduce something like a singleton to the global state, anyone and from anywhere can tap it. Nuff said.

Now, the alternative depends on the pattern! It's impossible to say "Well what would you have us do instead?". Well, what are you TRYING to do? Normally when this question comes up it means that the design has not been fleshed out entirely or has been fleshed out only myopically or at a surface level. Never underestimate the amount of time and "hands-off programming" really takes. That said, I've found a better alternative for virtually every singleton "solution" that I've ever seen proposed.
User avatar
Falco Girgis
Elysian Shadows Team
Elysian Shadows Team
Posts: 10294
Joined: Thu May 20, 2004 2:04 pm
Current Project: Elysian Shadows
Favorite Gaming Platforms: Dreamcast, SNES, NES
Programming Language of Choice: C/++
Location: Studio Vorbis, AL
Contact:

Re: Singleton Patterns - Controversy

Post by Falco Girgis »

qp wrote:Another problem that nobody ever seems to bring up is actually one of the bigger problems and led me to detest them altogether. There's hardly no code that I write anymore that is not threaded out the ass. The singleton is the worst nightmare for concurrency imaginable. Simply because when you introduce something like a singleton to the global state, anyone and from anywhere can tap it. Nuff said.
Damn, that's a really good point that I completely forgot...
User avatar
EccentricDuck
Chaos Rift Junior
Chaos Rift Junior
Posts: 305
Joined: Sun Feb 21, 2010 11:18 pm
Current Project: Isometric "2.5D" Airship Game
Favorite Gaming Platforms: PS2, SNES, GBA, PC
Programming Language of Choice: C#, Python, JScript
Location: Edmonton, Alberta

Re: Singleton Patterns - Controversy

Post by EccentricDuck »

Thank you thank you thank you! That design looks brilliant - thanks for sharing. I can see how there's a major difference between that and rampant use of singletons. With the design you mentioned, (thinking how I might approach things) you could define interfaces for your areas that contain pertinent things like warps, entities, etc. and have that be totally separate from your engine (the latter part being something you've said you're doing several times) without giving up control of them to the manager itself. On top of that, you could better define whatever sort of system you use for interactions between objects in your game and allow you to handle events/messages/whatever in a more controlled manner (which would probably lend itself far better to threading and concurrency than singletons, as qpHalcy0n was suggesting).

I shall look into absolving myself of singletons. A similar structure to what you mentioned would allow me to avoid using some of the systems I was thinking of implementing (singleton managers similar to my XNA project). I'd still need to avoid implementing the finite state machine's state pattern the same way as this book suggests (though it may have other solutions further in that I haven't read yet), and I'll need to re-work the command pattern I'm using (I currently pass a pointer of a list of entities to each entity and they access a Command Singleton which has a Map of all inherited Commands). My intent is to define Command objects and reference those to manipulate entities, menus, etc instead of writing the instructions independently in each place that I use them. It worked decently for implementing basic spot, follow, and attack behavior in a simple game I created for my Comp Sci final project. I'd like to do less passing around of pointers if I can help it since I was passing around a pointer of all entities and one of all dead entities.

I suppose my Java framework could be worse - my XNA project passes around pointers for all kinds of key objects just to instantiate certain things - and it sort of uses XNA's built-in component system (with system components, not entity components) except the components hardly register themselves and act independently, they still need to be updated from where they have access to the information that they need. It's one massive clusterfuck of spaghetti code that should have been re-written 6 months ago when I was sure that I could hammer it out before the semester started. The problem is that it borrows several different solutions from available code samples (which seem to cut corners themselves) and it all inter-meshes into this confusing and inconsistent fabric that is only really held together by the singletons/massive world class that manage it. Without singletons, I don't think it would be possible to keep it alive (and running relatively well). The only possible way I could have my arcade style game implement different "levels" is to rescale the 3D cube that constitutes it.

It's been a great learning experience - and I look forward to releasing it. There's very little code wise that I can salvage from my current XNA game (just experience, though maybe that's the most important part). I'd like to create a better design for future projects however. Thanks for your examples.
User avatar
k1net1k
Chaos Rift Maniac
Chaos Rift Maniac
Posts: 563
Joined: Sun Nov 07, 2010 2:58 pm
Contact:

Re: [SOLVED] Singleton Patterns - Controversy

Post by k1net1k »

so if i understand correctly, gyrovorbis strongly advises making everything a singleton.
singleton tastes good
User avatar
dandymcgee
ES Beta Backer
ES Beta Backer
Posts: 4709
Joined: Tue Apr 29, 2008 3:24 pm
Current Project: https://github.com/dbechrd/RicoTech
Favorite Gaming Platforms: NES, Sega Genesis, PS2, PC
Programming Language of Choice: C
Location: San Francisco
Contact:

Re: Singleton Patterns - Controversy

Post by dandymcgee »

Arce wrote:But PHOENIX SINGLETONS are so fucking cool! ;p
Definitely! How could any design be more sound than explicitly calling destructors?
Falco Girgis wrote:It is imperative that I can broadcast my narcissistic commit strings to the Twitter! Tweet Tweet, bitches! :twisted:
N64vSNES
Chaos Rift Devotee
Chaos Rift Devotee
Posts: 632
Joined: Thu Aug 12, 2010 11:25 am

Re: Singleton Patterns - Controversy

Post by N64vSNES »

GyroVorbis wrote: Singletons are a horrendous, fuck-ugly, bastardizing, brainless, degenerative, counterproductive design pattern that completely destroys not only the entire point of object oriented design, but also the programmer's ability to think in terms of an object-oriented paradigm. They should be avoided like the plague or a ravenous rectal STD.
How are they a horrendous, fuck-ugly, bastardizing, brainless, degenerative, counterproductive design pattern? Yes I admit they are not the object oriented way but if you only every need one single instance of that object what the hell is the problem?

Think about it if you only ever need a single instance of that object wouldn't it be safer to have it a singelton?

True you could have a GameManager class containing those objects and then you could create a refrence to that object but essentially your doing the same thing you would with a singelton only instead your risking the fact its possible to create more instances of a object which was only ever meant to have a single instance.

Suppose the is a level class which was only ever intended to have a single instance.

Here would be a object oriented method

Code: Select all

LevelClass &Lvl = GameManager.Level;
Or if it was a singelton

Code: Select all

LevelClass &Lvl = LevelClass::GetInstance()
I really fail to see the problem here.

*awaits bitching*
User avatar
xXStillAVirgin69Xx
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 1
Joined: Fri May 23, 2008 10:38 am

Re: Singleton Patterns - Controversy

Post by xXStillAVirgin69Xx »

N64vSNES wrote: I really fail to see the problem here.

*awaits bitching*
And people thought I was a fucking dumbass. :nono:
User avatar
Falco Girgis
Elysian Shadows Team
Elysian Shadows Team
Posts: 10294
Joined: Thu May 20, 2004 2:04 pm
Current Project: Elysian Shadows
Favorite Gaming Platforms: Dreamcast, SNES, NES
Programming Language of Choice: C/++
Location: Studio Vorbis, AL
Contact:

Re: [SOLVED] Singleton Patterns - Controversy

Post by Falco Girgis »

n64vsnes wrote:Yes I admit they are not the object oriented way
n64vsnes wrote:blah blah blah
n64vsnes wrote:I really fail to see the problem here.
Wheeeeeeeeeell!
xXStillAVirgin69Xx wrote:And people thought I was a fucking dumbass. :nono:
Goddamn, did I ever mention how ridiculously good looking you are?
User avatar
eatcomics
ES Beta Backer
ES Beta Backer
Posts: 2528
Joined: Sat Mar 08, 2008 7:52 pm
Location: Illinois

Re: [SOLVED] Singleton Patterns - Controversy

Post by eatcomics »

GyroVorbis wrote:
xXStillAVirgin69Xx wrote:And people thought I was a fucking dumbass. :nono:
Goddamn, did I ever mention how ridiculously good looking you are?
I lol'd

as per singletons... I never bothered to use them... I always felt that it was better to keep things more seperate and independent of each other and unable to touch each other like cheap whores....
Image
Post Reply