# Alternative to global classes?

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

## Recommended Posts

Alright, I'm sure this is a common topic of discussion, but I've been searching the forums a while and haven't found anything that directly answers the issue I'm having. Right now, I have a lot of global classes in my engine, implemented as global functions returning references to static class instances. The idea being that I can access these classes from anywhere, and not have to worry about initialization order. However, I'm also aware of the problems with having lots of globals, and I'm having to deal with a lot of compiler dependencies as well. I'd like to redo this so that each class is created at run time and each can exist on its own, with specific ties to certain parts of the engine rather than being global. The typical "best practice" that I keep reading about. However, the problem I'm running into is with those classes that really are needed by a lot of other engine systems. For example, the logging class, or the settings class. Any part of the engine may need to output to the log or read settings. Other systems (like, say, the sound system) may have a small number of classes that interact with it, but those classes still need a way to access it to begin with (and passing numerous references to a class constructor just feels messy). Does this mean I'm forced to make some or all of my classes global just so they are accessible to classes that aren't directly related to it? The only other idea I read about here in the forums was creating a single global class instance, and creating all of these other "global" classes within that. I can see the merits of doing this, but it is still basically global, the only difference being that you have to go through another class to get to it rather than accessing it directly. I'm assuming that, since games are fairly interconnected systems, there must be some best-practice for allowing certain engine classes to interact with certain other engine classes without making it global for everyone to touch. I'd appreciate any ideas people have on this.

##### Share on other sites
Quote:
 Original post by Nairou(and passing numerous references to a class constructor just feels messy).

Your feelers are off. Plus, there shouldn't be (and you haven't described) 'numerous' instances, just a few.

One thing that I tend towards is allowing parameterization of the logger, settings, etc. but using a global by default if none is specified. This allows flexibility to change if needs be, ease of use if the complexity is not necessary, but you're not *just* using the globals so you get the pressure to not include too many into the class.

You'll still need to be wary of what *really* needs a logger/settings to keep coupling/dependencies down, but it seems to be a good pragmatic middle ground in my (admittedly limited) experience.

##### Share on other sites
Quote:
 Original post by NairouI can access these classes from anywhere, and not have to worry about initialization order.

Since when do using globals and not worrying about initialisation order go together? [grin]

Quote:
 I'd like to redo this so that each class is created at run time

Well globals are still instantiated at run-time, by using globals you weren't avoiding this.

Quote:
 However, the problem I'm running into is with those classes that really are needed by a lot of other engine systems.

This isn't really true, it is however what many people find after they're global or singleton mind-ified.

Quote:
 For example, the logging class, or the settings class. Any part of the engine may need to output to the log or read settings. Other systems (like, say, the sound system) may have a small number of classes that interact with it, but those classes still need a way to access it to begin with

The logger has always been a debatable exception to prove the rule. Never the less, globals are becoming more unnacceptable as we move into the massively concurrent processing era.

Just pass references to these into the constructor at startup.

Quote:
 (and passing numerous references to a class constructor just feels messy).

Why does it?
That's what constructor arguments are for after all; there shouldn't be that many different things any given class needs to interact with anyway considering that each class should have one a single responsibility.

Any class that require access to, say, the rendering and physics subsystem at the same time is likely taking on too much responsibility and should be split into separate classes.

Quote:
 The only other idea I read about here in the forums was creating a single global class instance, and creating all of these other "global" classes within that. I can see the merits of doing this, but it is still basically global, the only difference being that you have to go through another class to get to it rather than accessing it directly.

It's better, but no substitute for doing it right.

Quote:
 I'm assuming that, since games are fairly interconnected systems, there must be some best-practice for allowing certain engine classes to interact with certain other engine classes without making it global for everyone to touch.

There are ways of promoting loose coupling, yes.
There are existing design patterns to help with this, for example you could look into the observer and mediator patterns.

##### Share on other sites
Quote:
 Original post by dmatterSince when do using globals and not worrying about initialisation order go together? [grin]

Heh, well what I meant was that I didn't have to worry about what order they were initialized in. Using the global functions meant that the classes would be automatically initialized before the first time they were used.

Quote:
 Original post by dmatterWell globals are still instantiated at run-time, by using globals you weren't avoiding this.

Very true, I worded that badly and was referring to the process of initializing the classes manually, in a particular order, instead of just floating around omnipotently in global space.

Quote:
Original post by dmatter
Quote:
 (and passing numerous references to a class constructor just feels messy).

Why does it?
That's what constructor arguments are for after all; there shouldn't be that many different things any given class needs to interact with anyway considering that each class should have one a single responsibility.

Well, lets take the renderer for instance. It needs access to the logger, to report any problems it encounters or just to make note of what it is doing. It needs access to the settings, so it knows, for example, what API to use or which display devices to initialize. It also needs a reference to the material manager, to request shaders or textures. That's three classes I can think of off-hand that it will need access to. So you're saying you would put all three of those as references in the renderer's constructor?

Quote:
 Original post by dmatterThe logger has always been a debatable exception to prove the rule. Never the less, globals are becoming more unnacceptable as we move into the massively concurrent processing era.Just pass references to these into the constructor at startup.

I guess I'll have to look into this more then. Other than the fact that it still feels messy to be passing strings of references to every class I initialize, it does solve the main problems I was having.

It almost makes me want to create a common base class which automatically pulls in things like logging and settings, and have the other game components inherit from that. But that is probably just overkill. [grin]

##### Share on other sites
Quote:
 Heh, well what I meant was that I didn't have to worry about what order they were initialized in. Using the global functions meant that the classes would be automatically initialized before the first time they were used.

A loud kaboom was heard in the server room. According to early reports, there were no survivors.

It seems someone assumed variables were properly initialized when that wasn't the case.

##### Share on other sites
Quote:
 Original post by Nairou[It almost makes me want to create a common base class which automatically pulls in things like logging and settings, and have the other game components inherit from that. But that is probably just overkill. [grin]

Maybe you should split your settings up. after all why does the renderer need the physics settings or ai settings?

##### Share on other sites
Quote:
 Original post by AntheusA loud kaboom was heard in the server room. According to early reports, there were no survivors.It seems someone assumed variables were properly initialized when that wasn't the case.

Correct me if I'm wrong, but I don't think that applies to this:

// Global access pointixSettings& Settings(){	static ixSettings Settings_;	return Settings_;}

Quote:
 Original post by stonemetalMaybe you should split your settings up. after all why does the renderer need the physics settings or ai settings?

Very true, but what is the alternative? Having every class open it's own settings? Depending on how settings are stored, that might mean reprocessing the same file multiple times or maintaining multiple copies of settings in memory.

Although, now that I think about it, it would be kinda nice if there was a way for each class to initialize it's own settings or logging object if/when it needed it, and have that object automatically tie into the log or settings used by the rest of the system. Not sure how that would work though, and again it may just be overkill.

##### Share on other sites
Quote:
 Original post by NairouCorrect me if I'm wrong, but I don't think that applies to this:// Global access pointixSettings& Settings(){ static ixSettings Settings_; return Settings_;}

Yes, this is a typical C++ workaround (other languages have different ways of approaching the subject). However, it does not solve the order-of-destruction issue.

##### Share on other sites
Quote:
 Well, lets take the renderer for instance. It needs access to the logger, to report any problems it encounters or just to make note of what it is doing. It needs access to the settings, so it knows, for example, what API to use or which display devices to initialize. It also needs a reference to the material manager, to request shaders or textures. That's three classes I can think of off-hand that it will need access to. So you're saying you would put all three of those as references in the renderer's constructor?

This is a common question and different people have different opinions. I can tell you my thoughts.

You can decouple almost all of your subsystems using this same method.

For the logger, that's a tougher question. That's a case where I just bite the bullet and pass in a LOGGER subsystem when I create my other subsystems (RENDERER, etc). That method doesn't decouple them as much as I'd like, unfortunately. I think there are more elegant solutions for this out there, though.

##### Share on other sites
Quote:
Original post by Nairou
Quote:
 Original post by AntheusA loud kaboom was heard in the server room. According to early reports, there were no survivors.It seems someone assumed variables were properly initialized when that wasn't the case.

Correct me if I'm wrong, but I don't think that applies to this:

... read the 10.14 section of the link I provided, only one page further down down..

Actually, that entire site is a very good read.

1. 1
Rutin
24
2. 2
3. 3
4. 4
JoeJ
18
5. 5

• 14
• 14
• 11
• 11
• 9
• ### Forum Statistics

• Total Topics
631757
• Total Posts
3002142
×