Sign in to follow this  

using singletons

This topic is 4203 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I don't want to sound rude but have you searched these forums? This question has been asked and answered a few times already.

A run down from the ones I've read...

The majority are along the lines of:
Globals are bad, hard to debug. A singleton is basically a global.

Yet others say in some instances they're ok, like a logger but why not just make namespace protected functions, you don't NEED a class for a logger. Not everything needs to be in a class. Anyways in most cases a better design can get you around the "need" for a singleton. Who says you only need one renderer, scene graph or resource manager? I might want to load two resource managers so I can pre-load the next level...

There are times when singletons are ok, but there is almost always a better solution. But this is just my opinion.

Share this post


Link to post
Share on other sites
It's hard to not program using singletons everywhere for a beginning programmer. Its a natural first reaction to make a bunch of manager classes that are singletons, but pick up a book on software architecture. There are a lot of really cool programming paradigms out there that are really useful.

Share this post


Link to post
Share on other sites
I use them vary sparingly and usually for such things as an input system or the renderer. When considering using a singleton, think very hard if you really need to limit the class to one instance.

Share this post


Link to post
Share on other sites
Quote:
Original post by exorcist_bob
how useful are singletons

Not very.

Quote:
and are they considered good practice.

Not really.

Share this post


Link to post
Share on other sites
The architecture of Fleurin (server).

cData.cs
-> public partial class cMain()

cGridy.cs
-> public partial class cMain()

cMain.cs
-> public partial class cMain()

cNPC.cs
-> public partial class cMain()

cPacket.cs
-> public partial class cMain()

cPathfinding.cs
-> public partial class cMain()

cPhysics.cs
-> public partial class cMain()

cSocket.cs
-> public partial class cMain()

cUI.cs
-> public partial class cMain()

cTimer.cs
-> public partial class cMain()

cCommon.cs
-> public class cFleurinFlags()

cINI.cs
-> public class cINIReader()
-> public class cINIWriter()
-> public class cINIAppend()


Globals: LOTS
Locals: LOTS
Scope Confusion: NONE! (via variable prefixing)

Share this post


Link to post
Share on other sites
@Thevenin: Umm... How does that answer the OPs question really? You make us search google or the forums for "Fleurin" to get some obscure post about it (forth or fifth link down on google I think).

Few people (not a single coder I've ever talked too or known) think globals are anything close to good programming practice. Atleast with OO languages.

Btw hope you're projects going well, looked cool.

@OP: Like many have said, you can almost always find a better solution then a singleton. There is no reason to have only one renderer, what if I want to render, using your engine, a different view to a different monitor? Now I cannot do that easily, you've restricted me when you could just put in the documentation, "Only use one instance of this class". If they fail to read it, it's not your problem, you're not a babysitter. Why force someone to do something a particular way because you didn't see someone using your product/project differently then you :-).

Share this post


Link to post
Share on other sites
Quote:
Original post by Mike2343
@Thevenin: Umm... How does that answer the OPs question really? You make us search google or the forums for "Fleurin" to get some obscure post about it (forth or fifth link down on google I think).


Yah, I probably should have posted a screenshot of it or something. Anyways, I intended on showing him that not everyone in the field is using the latest OO design principles (Or any OO design principles at all, lol).

Quote:
Original post by Mike2343
Btw hope you're projects going well, looked cool.


Drawing my own art for it is going terrible, programming it is going terrific.

Free Image Hosting at www.ImageShack.us

Share this post


Link to post
Share on other sites
The problem with singletons is not just that they allow one instance, but alos they are a global (I believe). There is no reason to have a global renderer, or sound system, or scene manager, even if you truely only do need one of them. A far easier way is to create a regualr class and let the user know they only need to create one instance.

The only real case I can think of where a singleton makes sense would be for the logging system. Generally, you will only need acces to one class (though it may be able to write to multiple files) and it will be needed to report status and errors from every subsystem of your application.

Share this post


Link to post
Share on other sites
Not all design patterns are good. Syntax-wise, the singleton DP is one of the simplest DP. When it comes to software design, it is probably one of the hardest to use. It is error prone and might lead to complex design problems - the kind of problem that makes you think "OMG! I have to redo everything!".

Quote:
Original post by Sr_Guapo
The problem with singletons is not just that they allow one instance, but alos they are a global (I believe). There is no reason to have a global renderer, or sound system, or scene manager, even if you truely only do need one of them. A far easier way is to create a regualr class and let the user know they only need to create one instance.

Stricly speaking, singleton are not "global" - they encapsulate a unique global and give a centralized access to this global variable. This doesn't change the rightness of what you say.

Quote:
Original post by Sr_Guapo
The only real case I can think of where a singleton makes sense would be for the logging system. Generally, you will only need acces to one class (though it may be able to write to multiple files) and it will be needed to report status and errors from every subsystem of your application.


Log systems don't have to be singletons. In fact, if you have only one log file then it's a far better idea to use functions - remember that in a C++ world not everythig is required to be an object. If you have more than one log file, I don't see the point of having a singleton interface.

BTW, globals aren't inherently bad. In fact, I know at least one really useful C++ library that have at least 3 clever globals.

@Thevenin: are you the sole developper of this project? How long will you maintain it? How many code lines is there in your project?

I understand that not everyone follow the full set of OO design principles (I don't follow everything too; for example, I have some problems to correctly (and blindly) beleive that the Coad's rules (PDF, see slide 14 - the whole PDF is worth a reading) are really useful) - but explicitely doing the exact contrary is... weird.

Quote:
Scope Confusion: NONE! (via variable prefixing)

That deserves a "Huh?!?!?" [smile]

Share this post


Link to post
Share on other sites
The only benefit that singletons have over a global variable is that the programmer can control order of initialization. Globals are all initialized before you hit main and the order is not guaranteed, usually determined at link time. This can cause issues if the order of initailzation of objects need to be controlled - this is a good use of singletons. Aldo if you are using a custom memory allocator, you don't want any globals that do allocations in their constructor since your custom allocator probably won't be set up before main.

Share this post


Link to post
Share on other sites
Quote:
Original post by DGates
The only benefit that singletons have over a global variable is that the programmer can control order of initialization. Globals are all initialized before you hit main and the order is not guaranteed, usually determined at link time. This can cause issues if the order of initailzation of objects need to be controlled - this is a good use of singletons. Aldo if you are using a custom memory allocator, you don't want any globals that do allocations in their constructor since your custom allocator probably won't be set up before main.

This is one of my main problems with singletons. C++ programmers think "initialization order of non-local static objects? Singletons!", when actually this is not the singleton patterns main purpose (as evidenced by the fact that the singleton pattern exists in languages which do not suffer from initialization order problems). There are other techniques in C++ to solve the initialisation order of non-local static objects problem without using singletons. In my opinion the thought process should be more like:
  • Need to guarantee that only one object of this type is ever created? Consider singletons.

  • Need to guarantee that only on object of this type is ever created and deal with non-local static initialization issues? Strongly consider singletons.

  • Just need to deal with non-local static initialization issues? Consider other solutions.

My preferred "other solution" when I don't consider it feasible to pass instances around is to simply transform global objects (Logger log;) into global functions which return local static objects:
Logger & log()
{
// or a thread-safe double locking implementation for multithreaded environments
static Logger global_log;
return global_log;
}

Σnigma

Share this post


Link to post
Share on other sites
So, if singleton usage can be avoided by using better software architecture, can anyone offer some advice on learning this better software architecture? My search-fu is failing me, probably because I'm not sure what terms I'm seeking.

Share this post


Link to post
Share on other sites
Quote:
Original post by Enigma
// or a thread-safe double locking implementation


!! (Or does that only apply to Java's synchronization primitives?)

Hmm, how about this approach which just occurred to me now?


// I might not have gotten this quite right :/
#define SETUP(type, var, args) type var##local(args); var = &var##local;

Foo* f;

// If a global sets up some *other* global, then the "parent" will have to
// take responsibility, though.

void gameLoop() {
while(!hell.frozen_over()) {
f->doWonderfulThings();
}
}

int main() {
SETUP(Foo, f, (123, 456));
// extra parentheses needed to hold that macro argument together
gameLoop();
// At the end of main, even though we don't call 'delete f', the object is
// still destroyed via the destructor of flocal, and memory is reclaimed
// because it's on the stack.
}


Edit: @ykcx: Just hang out on the c2.com wiki. They're probably some of the best mentors around (although they don't exactly like C++; but then, most discussion of software design ought to be language-agnostic anyway).

Or you could look for the GoF book (Group of Four) "Design Patterns" (which also works as a search term).

Beware, lots and lots of people think they're better with this stuff than they actually are - witness the current discussion about Singletons. :)

Share this post


Link to post
Share on other sites
Quote:
Original post by Zahlman
!! (Or does that only apply to Java's synchronization primitives?)

I'm certainly aware of the discussion about it and I can't say either way for certain (threading is not my strongest area) but I was under the impression from The "Double-Checked Locking is Broken" Declaration that double checked locking could be safely performed in C++, from the quote:
Quote:
The "Double-Checked Locking is Broken" Declaration
Explicit memory barriers can be used to make it work in C++, but these barriers are not available in Java.

and further down in the same article, the section entitled "Making it work with explicit memory barriers".

Σnigma

Share this post


Link to post
Share on other sites

This topic is 4203 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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