“Erm… Just create one”
Excuse my ignorance …
I never use singletons myself (I tend to use classes full of static stuff instead), but what’s so bad about them anyway?
The static stuff :
Serious: Singletons lead to code with implicit dependencies not exposed in the classes interface. This creates unexpected sideeffects. This way large software systems using singletons are difficult to maintain. Especially if there are frequent changes in the development team. Also Singletons and code using Singletons are difficult to unit test.
Can’t say that I’ve ever had a problem with them. They Just Work.
Cas
Fair enough. I’ve been using static stuff like this for years and I can’t say I’ve noticed any problems. Then again, I mostly work on smaller projects with relatively stable teams and no unit testing - oh, the luxury!
believe me, they only work if you look at them
Sure Singletons do work, but they are just one pitfall more you stumble upon when you last expect it. Using a service/component orientated approach with all required dependencies declared in the constructor makes things so much easier.
But then again, it all depends on the projects’ context. (And is really OffTopic :))
Back on topic: singletons work really great in games programming. Actually static instance variables work really great in games programming. You can tell you’ve got a well written game when there’s singletons about because you know someone’s just gone and made something work easily and quickly without wanking around.
Cas
LOL
Statics are enemies of threading. Static singletons are enemies of subclassing.
I prefer having all my singletons accessible trough an ApplicationContext, like in servlets or similar to DarkStar. If i need to switch a singleton with a different implementation, i just change the reference in the ApplicationContext. There is no need for all the high-level classes to hold a reference to each other, they all access each other trough the ApplicationContext. I use a number of non-singleton (UpdateContext, CullContext, RenderContext, ThreadContext) context classes too. ThreadLocal is almost as fast as static, and is faster when using multiple threads (even on a hyper-threading but single-core CPU).
But it doesn’t hurt. IMHO Singletons are a solution to a nonexisting problem and only a quick hack to avoid refactoring of your class instantiations.
Except now every subsystem has a dependancy on the ApplicationContext, and ApplicationContext depends on UpdateContext, RenderContext, etc… Your dependancies are badly messed up and the whole thing devolves into a big mess of spaghetti.
You can make it slightly more sane by having ApplicationContext hold a bunch of interfaces, but you’re still encoraging heavy module cross-talk instead of having a better engineered modules with proper dependancies.
It does hurt. If i have the InputSystem reference stored in 20 places, i cannot switch it to a different implementation at runtime. And cross-references among classes leads to clutter. Its much more cleaner to have a single class which holds the reference to all the subsystems in one place. And its a better API too. One look on the ApplicationContext class, and its easy to find the accessor for the subsystem needed. With static singletons, there is InputSystem.getInstance(), SoundSystem.getInstance(), etc and you just wonder what else there may be. With cross references, all the classes are cluttered with setInputSystem(), setSoundSystem() and the like methods. When using contexts, the classes can take from the context what they need themselves.
@Orangy
I think you imagine differently those contexts. UpdateContext and RenderContext are not subsystems those are like the HttpRequest class in servlets, those are passed to handler methods, to do some job on them.
…and effectively hide their dependencies, so you never know what a class may need without either running it or analysing it’s source.
No, you would require them in a constructor (except you use setter based DI). Also I talk about subsystem/component wireing here, not deeply buried implementation classes. Those should get their subsystem reference in a suitable update callback like “updateSound(SoundSystem ss)” or something. You rarely need to access a subsystem out of thin air, so don’t design an api/spi in a way that encourages it.
See, you’ve spent all this time wanking around arguing over singletons instead of writing games!
Cas
^^^ I LOL’ed
May be, but I think this is the place to wank over design principles Other than that, I only post here when waiting for a build to finish
Nothing stops anyone from storing a singleton reference or a reference retrieved from a AppContext, so you gained nothing regarding runtime switching of subsystem implementations. If you want to do that, you need to define a subsystem interface and only hand out proxies delegating to the real implementation. This can be done with any discussed approach.
The programmer can do whatever he wants anyway, especially if its an open-source library.
If you have time to read over it, you can see the context system used in my code:
http://code.google.com/p/vlengine/source/browse/#svn/trunk/vle_cleanup/src/com/vlengine
There are things in need of fixing and redesign, but i consider the AppContext a good thing. There are lots of C game engines around, and most of them do have a central object, most of them just call it “Engine” instead of “AppContext”.
If it works, it’s good. Theres a saying I know from my wife: “Everything that works is good. And good is better than perfect.”
I guess it’s her way to explain the “New Jersey style”, even if she has nothing to do with software engineering.
I have no problem with someone using static environments or singletons, if it works for them. It’s just, that there are problems with this approach, which can be overcome by using other design principles, but chances are, that you never encounter this problems in your projects’ scope and context.
If I would design an engine from scratch, which I am not doing (currently ;)), I would use an approach based on constructor declared dependencies using Pico as IoC container and DI engine. But hey, I am a J2EE developer, so I might tainted
Damn straight - if you’re the one writing your code and only you or a small team have to interoperate, there’s no point in worrying too much about the philosophical (or even practical) problems with globals, statics, singletons, etc. If you eff up, you can always change stuff after the fact without breaking other people’s code.
This is a freedom that most “good code” advice assumes you don’t have, because a) these books tend to be written by people dealing with far more substantial and publicly-used codebases (Bloch (for instance) is a master, but let’s be honest, nobody here is writing code for the audience that he’s writing for), and b) the books are generally aimed at people doing enterprise work where the ability to add or alter functionality without changing existing code is crucial.
For game designers these things shouldn’t matter very much at all (unless you’re writing a general library), because codebases should almost always be independent per-game and don’t need to be publicly exposed. You probably don’t need a singleton because you can just decide for yourself that you’re just going to create one of the offending object, but on the other hand you don’t need to avoid the pattern if it feels like the best way to go, because you can deal with the ways that it sucks by holding yourself to a similar mental contract.
You’d probably be shocked to see the internal state of many games that you know and love. What’s important is not how it’s written, it’s how it plays and how long it took to write - nobody’s maintaining these things after they’re released, you’ve got to get it right the first time (well, unless you’re dealing with something massive like an MMO, but that’s venturing into EE-level scope, so it’s a different ballgame). If you can cut corners and stay within spec, by all means do it. All the Flash game developers do, and to be frank, I suspect they’re putting out a lot more content per-developer than we are!