Engine Design

Started by
2 comments, last by OrangyTang 16 years, 11 months ago
I was browsing the recent threads yesterday, when I saw a "Rate my Engine" thread or something along those lines. The OP mentioned that he/she was using singletons. Everybody on gamedev hates singletons from what I understand by reading the replies. My engine makes extensive use of singletons. I figured it would make coding easier, but I understand that it is bad practice, and a hallmark of poor design. So I decided that I should rewrite it, even though it is in a fairly complete state. I decided that I should put everything in a base engine class. So here is what I came up with for the base engine class:

class Engine{
	public:
	Engine();
	~Engine();
	File_System file_system; //provides access to file system, loads/frees game resources
	Renderer renderer; //abstract graphics rendering interface
	Physics_Manager physics_manager; //keeps track of game physics
	Script_Manager script_manager; //manages scripts and their types and methods
	Entity_Manager entity_manager; //keeps track, updates, draws, etc... of all game entities
};

The entity class would have access to the full engine class, but the Renderer, Physics_Manager, Script_Manager, and Entity_Manager classes would not have access to the full engine class or access to each other. My old engine did stuff like this:

Entity_Manager* entman = Entity_Manager::Instance();
Game_Map* game_map = Game_Map::Instance();
//etc...

It is very easy to code with. So my question is: Is it worth it to rewrite the engine just because singletons are considered poor design, or is it too much trouble? Is the preliminary design for a reworked engine valid or worthwhile to pursue?
Advertisement
Refactor, don't rewrite.

That said, however, it can become very difficult to refactor away heavy singleton usage. I think it's worth the effort -- you might learn a few things -- but just be aware it won't be easy. On the other hand, doing it now will be easier than doing it later.

Your preliminary redesign (encapsulating everything in an "Engine" aggregate) is probably a good starting point. Personally, I don't like the style, but it can be okay -- especially if, as one poster in the one of the engine/singleton threads suggested -- the "Engine" aggregate is optional and purely a helper for the user, who can manually construct or manage the subsystems as he or she needs. If nothing else, though, it's a step in the right direction and it's not so huge a step as to make the refactoring a Herculean task.

I'd recommend you refactor one subsystem at a time.
In the end, we are here to make games.
Sure we need to learn as we go, but if we are constantly rewriting the base code we'll never get to the fun part of making games!

Note this down and use it when ever making something new, and move on, don't go back and re-invent the wheel.
==============================
A Developers Blog | Dark Rock Studios - My Site
Singletons can be refactored out of a design without too much effort if you do it piecemeal when you come across it. Usually what I do when I find a singleton I want to remove is to tag it in some way (either with a comment in the class or with an ugly GetSingletonWhichWillBeRemoved() call). Then you can look through for uses of it and see what can be done. Appropriate uses get refactored to accept the singleton as an object, inappropriate uses usually means you've missed an abstraction layer somewhere which should be being used instead. Any new code can just pass the singleton object around directly.

Eventually you get to the point where theres no direct usage of the Get() of the singleton any more, at which point you can un-singleton-ise it and give it an appropriate lifespan.

This topic is closed to new replies.

Advertisement