Is it bad to use _G in this case?

Hello, I have a module that requires/loads other modules and creates a global variable for them
The only point is so I don’t need to 1, keep using local module = require(path) and for modules that need to load before their functions are needed can do so

! Before anyone says “just google it” I have, there were tons of different answers and none used in this case (that I found) !

Basically what it is/how it works:

local loader = {}
local loadedModules = {}

--// On script run
local Descendants = script:GetDescendants() -- Not always the same, might've spelled it wrong too.
for _, des in next, Descendants do
    _G[des.Name] = require(des)
    table.insert(loadedModules, _G[des.Name])
end

function loader:Reload()
    local Descendants = script:GetDescendants() -- Not always the same, might've spelled it wrong too.
    for _, des in next, Descendants do
        if _G[des.Name] == nil then
            _G[des.Name] = require(des)
            table.insert(loadedModules, _G[des.Name])
        end
    end
end

function loader:ClearGlobalModules() -- Not sure if this would be used but I have it
    for _, module in next, loadedModules do
        module = nil -- Should turn the _G into a nil
    end
end

return loader

Keep in mind I didn’t test this version, but that’s basically how it works. I thought of doing this for remotes too then randomizing names.

Yes I already know the remote thing is useless and an exploiter can go for _, global in next, _G do and get them all

I just want to know if this is a bad thing to do, I do it cause it’s also easier than typing out each thing for each script that can access it.
Exploiter wise on the modules makes no difference, since they can easily use game:GetService("ReplicatedStorage").Modules.ModulePath

Honestly, it’s probably not even bad.

It’s all preference. it’s not replicated so if it’s on the server it’s fine. If it’s on client, just simply not trusting the client will make it be fine.

They’re on the client, reason being is most of my modules there are client stuff. (ui, client interactions, etc)
Are those fine?

That’s fine. It’s the same as an exploiting just requiring the module anyway.

Always favor organization over typing speed. If you need to type

local chatModule = require(game.ServerScriptService.GameCode.Modules.ChatModule).initialize()

then do it in every script. Just do it. Type the extra letters, you’ll thank yourself later and your coworkers won’t yell at you. Coding isn’t about speed, it’s about writing good, clean, readable code that you can come back to and debug with ease.

I understand that this is a more organized approach but what exactly does this have to offer other than being a nuisance? If you type _G.ChatModule then you would easily be able to debug knowing that it is infact the chat module.

I also understand that there are slight performance differences but those are VERY small and do not affect your game.

In the end, save your fingers the effort and just use _G.

_G is a major footgun because it is a dynamic table that you can’t describe without traversing it. This means you can’t guarantee the script writing your key is going to run before the script that’s reading it will, causing a race condition.

That’s why ModuleScripts are more preferred, because you can guarantee that whatever you put into them will be there and will be the same whenever you require them.

3 Likes

So if you’re worried about your fingers you shouldn’t be scripting. I’m not disagreeing, but that is taking it out of proportion. Programming is typing, full stop.
Second, you are correct that you could organize _G a little better, but then it comes down to this: how do you know which script contains the logic for that particular entry in _G? Ideally it would be a container similar to a ModuleScript. game.ServerStorage.NotReallyModules.Chat_G might contain the _G logic for the chat stuff, but then why not use ModuleScripts?

ModuleScripts are cleaner and easier to edit, avoid race conditions, and because tables like _G are dynamic they disable certain potential for code optimization and intellisense. Seriously, you’ll be much better off by using ModuleScripts and just typing the whole 10 extra letters.

1 Like