Using _G to store access to a framework - good or bad idea?

I wrote a framework for the things I do a lot in my game - setting up interfaces, unit testing, and access to a variety of locations for other modules (eg. constants, helper code & template objects).

The way I’m doing it right now is that every service gets a reference to the framework variable, so they have full access to everything. The issue comes about when code inside these services needs to access the framework (as an example, I have a main service for controlling AI; inside that service, I have code for controlling the AI’s character; that code has no reference to the framework).

I’ve been thinking about how best to allow everything to access the framework and come up with two solutions. Either I can pass it around to every module that needs it (so it becomes an extra argument into that module’s constructor), or I can reference it through the global table (_G.Framework).

I’m just wondering, is there any reason why I shouldn’t use _G.Framework for this? It seems like the best option but I’ve heard people say not to use _G in the past, so I want to see if there’s any actuality to that or if it’d be fine to go with that option.

Thanks!

2 Likes

You might find this thread with a similar topic interesting. In spite of the title, the answers pretty much turned into the same discussion you’re looking for.

1 Like

If you happen to use another script from someone and the script assigns _G.Framework to something else, you’re gonna have some issues.

Generally it’s best practice to avoid using _G if possible, because anything can arbitrarily write/overwrite things to it.

3 Likes

Storing widely-used, immutable variables in _G or shared is fine.
Storing mutable game state in _G or shared is not fine.
Your use case is fine.

Lock down _G after you load it up to mitigate the overwrite issue.

_G.Framework = blah

setmetatable(_G, {
    __index = error,
    __newindex = error,
    __metatable = "Locked",
})
8 Likes

This doesn’t really help, as it would just break other scripts that need to use _G

It won’t break other scripts reading valid values from _G.

It will break scripts trying to write values and read nonexistent values from _G, which is what we want.

1 Like

I don’t think we want any scripts to be broken if we can avoid it? Which is why it’s generally reccomended not to use _G

2 Likes

I don’t think we want any scripts to be broken if we can avoid it?

If you are doing something bad with a global table, you want your script to break. Loudly.

2 Likes

It would be best to make the Framework with Module Scripts and use require (path.to.Framework), and, if another script starts before the Framework, even for a few microseconds, errors can occur.

1 Like