   Singleton is bad. What good then?
  Hi there folks.I keep reading from people that Singleton is bad and should be used when nothing else left. Few years ago I would say "I dont care what others thinks", but there were a discussion I was involed at, and apparently I was wrong, and decided to listen to people who knows more than me.Back to the topic:I'm looking to replace Singleton pattern with something else. In my game I need to get access to lets say TextureManager from any point of the software so with singleton it would be something like:[source lang=cpp]...TextureManager::getInstance()-&gt;loadTexture("robot.png");...So simply I saw Singleton as a replacement for global variable (they also considered bad).So any suggestions?Thanks!   
  Here are some options.1. (The OOP response:) Refactor your project so you don't NEED to get access to TextureManager from any point in the software. Will your sound system be loading textures? Will your pathfinding function be loading textures? One problem with singletons is that they lose you the opportunity to carefully delimit interactions, and this addresses that problem.2. (The pragmatic response:) Use a global variable. Singletons are bad in ways that global variables are not: They complicate creational and access patterns, they obscure functionality, and they lock in a relationship between a class and an application instantiation. If you had used a global variable right from the very beginning, as opposed to learning over, then waffling over singletons, then posting on GameDev, you'd already be done with this part of your app. People warn newbies away from global variables, but you'd have to see some newbie code, where EVERYTHING is global and globals are used to pass things in and out of functions, to understand where this advice comes from and how there's a middle ground.3. (The modern architectural response:) Use loose coupling to provide texture-loading services to other loosely-coupled services in the app that need it. Of course, this doesn't help you with separation of concerns, and requires the implementation of a loose coupling system. (To quote JWZ: "Now they have two problems.") I wouldn't recommend spending time on it.   ;  Thanks for you reply!Quote:1. (The OOP response:) Refactor your project so you don't NEED to get access to TextureManager from any point in the software. Will your sound system be loading textures? Will your pathfinding function be loading textures? One problem with singletons is that they lose you the opportunity to carefully delimit interactions, and this addresses that problem.Lets say I have some sort of engine (framework/wrapper over d3d/ogl..), a better name would be Graphics Subsystem.Its coupled with the TextureManager, or even provides one in a manner of:GraphicsSubsystem gs;...Code..gs.getTextureManager().loadTexture("..");..Code..Now lets say I writing a MD2 class, at some point Ill have to load the texture but I dont have direct access to the GS.Or actually maybe I'm just making problems that does not exists, I could pass the GS to the MD2. I'm confused, probably because I'm at my early stage of design.Quote:2. (The pragmatic response:) Use a global variable. Singletons are bad in ways that global variables are not: They complicate creational and access patterns, they obscure functionality, and they lock in a relationship between a class and an application instantiation.I see. But I think that global should not be used, it makes the code harder to maintain (at least for me).Quote:3. (The modern architectural response:) Use loose coupling to provide texture-loading services to other loosely-coupled services in the app that need it. Of course, this doesn't help you with separation of concerns, and requires the implementation of a loose coupling system. (To quote JWZ: "Now they have two problems.") I wouldn't recommend spending time on it.I didn't really get it, maybe because I'm not familiar with the term "loose coupling" (either english problem, or lack of knowledge in software design), but since you recommend not to spend time on it, then I probably wont.Anyway if I may, I would like to rephrase my question a bit:So I agree singletons are bad, and we should avoid using them, but does this means singletons should not be used at all? Or they are acceptable at some places?   ;Quote:Original post by Sneftel2. (The pragmatic response:) Use a global variable.HERESY!In the old days of GDN, people have been burned at the stake for such exclamations!(Not that I wish these days back. Carry on.)   ;Quote:Original post by s.kweeLets say I have some sort of engine (framework/wrapper over d3d/ogl..), a better name would be Graphics Subsystem.Using classes with names like "subsystem" or "manager" is a symptom of the problem. A subsystem isn't a thing. I'm looking at the items on my desk, and while I can see plenty of objects -- papers, pens, a coffee cup -- I don't see any subsystems or managers. I don't even see anything that I could possibly classify as a manager. Maybe my filing cabinet is a FileManager? But I wouldn't call it that, because that would only serve to conceal its true nature, and encourage people to add behaviors to it later that are not intrinsic to a filing cabinet. Perhaps my cat is a PurringSubsystem? But again that conceals his nature, and suggests that any purring that goes on anywhere has to involve him.These names do not indicate OO code. They indicate procedural code, designed in terms of function flow rather than ontology, then partitioned by general topic and shoved into classes with vague enough names to contain them.Quote:But I think that global should not be used, it makes the code harder to maintain (at least for me).The maintenance burden of globals and singletons is nearly identical: Small if used wisely, large if used unwisely.Quote:Anyway if I may, I would like to rephrase my question a bit:So I agree singletons are bad, and we should avoid using them, but does this means singletons should not be used at all? Or they are acceptable at some places?"Acceptable" implies that there's someone sitting in judgment of you, who's overall not okay with singletons, but who will just this once let you do it and not take away your programmer's license. Perhaps you meant "Preferable"? I've been coding for a while now, and I've run into exactly one situation where a singleton actually had significant advantages over a global variable; this was on an embedded platform, and the advantages were specific to the vagaries of the memory layout on that platform. Perhaps someday you too will be unlucky enough to find yourself in such a situation, but I wouldn't count on it.   ;  Its just names... How else would you call OpenGL wrapper? OpenGLDevice? OpenGLWrapper? OpenGLSubsystem? How would you name a particle system other than ParticleSystem?I've that feeling that everything I do is wrong, but I see others doing it. I'm interested in creating wrapper over OpenGL for example, that instead of writing 10 lines of code to change the projection every time I need it I would write OpenGLWhateverIsGoodName.setProjection(fovy, aspect, near, far).I'm not complaining, and I'm willing to learn, and I read books/articles/other open source engines/games, and I see them using something, have names for that something, but when I myself try to do it, I get notices from people that what I do is bad.Its a bit frustrating.Quote:The maintenance burden of globals and singletons is nearly identical: Small if used wisely, large if used unwisely.Ok I'll revisit my position on globals.Quote:"Acceptable" implies that there's someone sitting in judgment of you, who's overall not okay with singletons, but who will just this once let you do it and not take away your programmer's license. Perhaps you meant "Preferable"? I've been coding for a while now, and I've run into exactly one situation where a singleton actually had significant advantages over a global variable; this was on an embedded platform, and the advantages were specific to the vagaries of the memory layout on that platform. Perhaps someday you too will be unlucky enough to find yourself in such a situation, but I wouldn't count on it.Ok I got you. Thanks!   ;  The question is if you really need to enforce having just a single instance. There are extremely few cases where you really need to. Most of them time, you might perhaps only use one instance of a class, but there's actually no need to enforce it through prevention of more instances than that.Just design your classes normally and just have 1 instance if 1 instance is all that is needed. For > 99% of cases, singleton is overkill.I feel singleton as a pattern is hugely over-discussed compared to its very narrow use.   ;Quote:Original post by s.kweeIts just names... How else would you call OpenGL wrapper? OpenGLDevice? OpenGLWrapper? OpenGLSubsystem?Well, keep in mind that I advised you not to go the pure OO route. So rather than answer from my point of view, I will give you the point of view of Sven, the Hypothetical OO Programmer. Sven has never used a global variable in his life. Sven would probably use OpenGLContext, as it directly corresponds to what's going on -- you can have several OpenGL contexts separately, and OpenGL calls affect a specific context. But Sven doesn't really care so much about this stuff -- interfacing with low-level system libraries is not what Sven spends most of his time doing, and it's not the best use of his OO expertise. Most of the code in Sven's game is not OpenGL calls.Quote:How would you name a particle system other than ParticleSystem?Sven suggests that "ParticleSystem" is not a real thing. A ParticleEmitter uses a ParticleFactory to create Particles from a memory pool; these Particles are given a pointer to a ParticleBehavior object composed from the various forces (gravity, wind) that affect a particle. Particles are also given to the ParticleRenderer to actually render them, and to a ParticleKiller to handle removing them from the renderer and then deleting them after their lifetime is over. But Sven might be persuaded to put all these things into a thin utility class named ParticleSystem, to simplify access to the structure. Sven cares deeply about multiple levels of encapsulation, as it lets you have fine object decomposition and simple interfaces simultaneously.(Note that Sven's particle system code is somewhat slower than mine, due to its reliance on AOS data and virtual function calls.)Quote:I've that feeling that everything I do is wrong, but I see others doing it. I'm interested in creating wrapper over OpenGL for example, that instead of writing 10 lines of code to change the projection every time I need it I would write OpenGLWhateverIsGoodName.setProjection(fovy, aspect, near, far).How many lines does gluPerspective() take? In any case, short code is not something that Sven excels at writing. Quote:I'm not complaining, and I'm willing to learn, and I read books/articles/other open source engines/games, and I see them using something, have names for that something, but when I myself try to do it, I get notices from people that what I do is bad.Relax. Make games. Don't worry too much about architecture. In particular, Do not worry about architectural problems you have not, yourself, personally, actually run into. Most of these issues are difficult to understand if you don't have experience with codebases large enough for them to matter, and internalizing them before you understand the forces behind them is dangerous.   ;Quote:Its just names... How else would you call OpenGL wrapper? OpenGLDevice? OpenGLWrapper? OpenGLSubsystem? How would you name a particle system other than ParticleSystem?Names have meaning. All of those names are not terribly ideal -- largely because the very concept of an "OpenGL wrapper" as a single entity is not ideal. An OpenGL wrapper should consist of a number of objects that interact with eachother in particular ways, each with its own proper name and collection of properties and behaviors (so you might have a texture class, and a class that represents the render context state, et cetera, but you don't have "class OpenGLWrapper { ... " anywhere)."ParticleSystem" is generally fine because, despite the presence of the word "system" in the name, "particle system" generally means the discrete single instance of a collection of particles and not the "manager" of all such particle collections.   ;Quote:Original post by s.kweeIts just names... How else would you call OpenGL wrapper? OpenGLDevice? OpenGLWrapper? OpenGLSubsystem? How would you name a particle system other than ParticleSystem?I've that feeling that everything I do is wrong, but I see others doing it. I'm interested in creating wrapper over OpenGL for example, that instead of writing 10 lines of code to change the projection every time I need it I would write OpenGLWhateverIsGoodName.setProjection(fovy, aspect, near, far).I'm not complaining, and I'm willing to learn, and I read books/articles/other open source engines/games, and I see them using something, have names for that something, but when I myself try to do it, I get notices from people that what I do is bad.Its a bit frustrating.It's not about doing anything "wrong."  It's about being clear.  "FooProcessor" and "FooManager" don't tell me what they do, other than that they do stuff with Foo.  The perceived advantage of that is two-fold: you can put whatever you want in there, so long as it's kind of related to Foo; and when you add stuff later on, you don't need to refactor to consider what you're adding.  Just drop it in the bucket with everything else.  It's nice and simple and saves you from having to deal with boring refactoring, right?  A few months later, you want to let your players download custom banners from other players over the net, and your NetworkBucket needs access to your TextureCabinet, because that's where you keep your image loading function, and a Singleton is born.Actually, that gives me an idea!  Whenever you want to call something XManager, or XSystem, try calling it XBucket.  If it still makes sense given what's inside, refactor it into objects that represent things, or take it for what it is (a pile of procedural code, and NOT an object) and refactor it as such.Like your OpenGL wrapper, what's it do? Does it provide a mostly one-to-one mapping of OpenGL API functions to some new language or naming convention?  Then call it OpenGLWrapper.  If it's a bucket of functions meant to batch some OpenGL calls you make all the time, then why have a class at all?  Why not just kweeSetProjection() and kweeLoadTexture()?Edit: jpetrie described the "ParticleSystem" bit much better.   