Jump to content
  • Advertisement
Sign in to follow this  
Harry Hunt

Class registration mechanism (Now: Singleton: good or bad?)

This topic is 3826 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

Oh no, not another Singleton thread!!! Hi! I have exactly one singleton in my engine and I would very much like to get rid of it. The problem is, that it's just so darn convenient ;-) I have an extensible Entity-System that is built around an EnityFactory class which is currently a singleton. Through the use of the following macro magic, each entity class registers with the EntityFactory, and it does so more or less "automatically":
#define RegisterEntityClass(entityClass) static bool   entity##entityClass##__LINE__ =   EntityFactory::GetDefaultFactory()->   RegisterClass(#entityClass,   &EntityFactory::FactoryMethod<entityClass>)

class MyCustomEntity : public Entity
{
...
};

RegisterEntityClass(MyCustomEntity);

EntityFactory* factory = EntityFactory::GetDefaultFactory();
Handle<MyCustomEntity> myEntity = factory ->Create<MyCustomEntity>(L"MyCustomEntity", L"id");


I'm using a singleton and not just a class with static member functions to avoid the "static initialization order fiasco". So here's the thing: apart from the EntityFactory class, my engine is 100% singleton free(TM) and I'm not really comfortable with EntityFactory being a singleton. I tried to hide the fact that it's a singleton by calling the singleton method "GetDefaultFactory" and making the constructor public (so in theory you could create more than one EntityFactory), but that's mostly for show. So I'm looking for ideas on how to get rid of the Singleton without losing too much of the convenience of this system. Cheers and thanks! [Edited by - Harry Hunt on May 26, 2008 1:48:26 PM]

Share this post


Link to post
Share on other sites
Advertisement
You can't, unless you explicitly register all the classes during some initialization process.

In your case, you do need a global point that any piece of code can access. And, because you don't define proper initialization order, you need to guarantee that there is only one of those, so that all classes register with exactly same one.

In your case, you really do need a globally accessible instance, which must be the same for all. Having two would break the system, since classes would register with either one.

Share this post


Link to post
Share on other sites
Thanks Antheus!

Now I have to struggle with myself... but I think I will manually register each class with the factory.

Share this post


Link to post
Share on other sites
This is the pain of using singletons from the get go. They bite you in the butt later on when you figure out they're useless (There is that 1% when you have a physical hardware limitation that needs one, then again just make one ;-) ). Refactoring this late can be a real pain, I don't envy you at all. Best of luck.

Share this post


Link to post
Share on other sites
Quote:
Original post by Harry Hunt
I have exactly one singleton in my engine and I would very much like to get rid of it. The problem is, that it's just so darn convenient ;-)
I hardly believe it! ;-)
Quote:
Original post by Harry Hunt
I have an extensible Entity-System that is built around an EnityFactory class which is currently a singleton. Through the use of the following macro magic, each entity class registers with the EntityFactory, and it does so more or less "automatically":
Don't do this. Macros are outside standard rules. They will likely bite you where it hurts sooner or later. Macros are BAD, sometimes magic, use them with care.
Quote:
Original post by Harry Hunt
I'm using a singleton and not just a class with static member functions to avoid the "static initialization order fiasco".
Go for class. Having a this pointer to mess with always comes useful in the long run.
EXAMPLE:
NewLoadQuery(ResourceResolver &resolver, String &resourceName)

Have "phun" in passing a static object down this road. Think you don't need it? Think well.
Quote:
Original post by Harry Hunt
So here's the thing: apart from the EntityFactory class, my engine is 100% singleton free(TM) and I'm not really comfortable with EntityFactory being a singleton. I tried to hide the fact that it's a singleton by calling the singleton method "GetDefaultFactory" and making the constructor public (so in theory you could create more than one EntityFactory), but that's mostly for show.
I'm not yet sure of what this "EntityFactory" is meant to do.

Share this post


Link to post
Share on other sites
If the singleton works and is convenient, why do you want to get rid of it?

Share this post


Link to post
Share on other sites
Thanks for the replies!

The whole point of the entity factory is that I can create new entity classes in the game DLL and they will immediately show up in the map editor, without me writing any additional code. It also allows me to serialize entities using a unified interface and then re-instantiate them using just the class name.
In a way, this is a homegrown replacement for real introspection. In Java, you have Class.forName() and this is my version of it if you will.

Of course it doesn't have to be a singleton and it most likely won't be in the future, but initially this seemed like a natural choice.

Quote:
I hardly believe it! ;-)


It's true. Whenever I felt compelled to use a singleton, I spent some time thinking about it and always came up with a better solution (with the exception of the entity factory).

Quote:
Don't do this. Macros are outside standard rules.


I agree, macros are evil and that's one reason why I don't like my current solution.

Quote:
If the singleton works and is convenient, why do you want to get rid of it?


Good question. I guess I simply don't like singletons and I need to prove to myself that I can live without them ;-)

Share this post


Link to post
Share on other sites
Quote:
Original post by Hnefi
If the singleton works and is convenient, why do you want to get rid of it?


This is exactly my mantra. People say its bad design, but I say its bad decision making. A singleton is a tool, much like a hammer, that does a specific job. You wouldn't use a hammer in places that do not need hammering, such as tightening a bolt. I believe this is where people run into problems with it. For example, I use singletons in my engine. One class that I have that uses it is called my EventManager class. It funnels and directs events to all portions of the system. It is coupled to other parts of the system via interfaces, not by classes themselves. Other classes that choose to send and receive events would have to include the eventSystem regardless if it was a singleton. I think this is a great example of when to use one, especially on a class that does not depend on memory management order.

In other places, such as window class, a singleton seems counter productive because your engine would only support having one window. In this case I would not use a singleton, rather I would register that window with my EventManager and let it route events to it as they come.

Also, if designed correctly, a singleton class can become a regular dynamic class with very little change. For example, I have a ResourceManager class, that manages a resource pool. Currently its a singleton class because I assumed that people would only want one of these classes. After careful research, I found that people may need more then one. So, I just took out the getInstance() function and made the constructor public. Now the user is faced with registering all resource-related objects manually, rather then automatically by the interfaces that make the resourceManager work.

So, in the end, a singleton is a tool that, if used properly, has the potential of clearing up code, but if used badly, can make refactoring a nightmare.

Share this post


Link to post
Share on other sites
Quote:
Original post by RealMarkP
This is exactly my mantra. People say its bad design, but I say its bad decision making. A singleton is a tool, much like a hammer, that does a specific job.
A singleton is a tool, like an oil filter wrench, that does a specific job. A lot of people, for various reasons, have decided to use this oil filter wrench to hammer everything in sight. Even if you take "hammer everything in sight" as a reasonable construction technique, using an oil filter wrench for it is sort of a stupid idea.

If you want global variables, you know where to get them.

Share this post


Link to post
Share on other sites
Quote:
So, in the end, a singleton is a tool that, if used properly, has the potential of clearing up code, but if used badly, can make refactoring a nightmare.


How exactly does it clear up code? It actually pollutes it I find. Hunting down bugs becomes much harder. Your basically disguising a global as something else. If you need a global use it. Just be aware of it's downsides. If you need just one instance, make just once instance. Unless you have a physical requirement (hardware) then a singleton is most likely not the right hammer for the job.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!