A small method to clean up code while dealing with networking

Hey there, I was programming my game and stumbled on this small tip.
It is to make a code much cleaner when dealing with module scripts, automation, and networking.
Take it this way:
You are programming your project, and you often use RemoteEvent/Function,
Especially in module scripts, you need to write Game:GetService("RunService"):IsServer() often to determine if the code execution on the ModuleScript is weather on the client or the server.
Some people like to do something like this:

local RunService = Game:GetService("RunService")

----------Using Remote Event----------
if(RunService:IsServer()) then
    ExampleEvent:FireClient()
else
    ExampleEvent:FireServer()
end

Or you might like to write like this:

local RunService = Game:GetService("RunService")
local IsServer = RunService:IsServer()

And use IsServer variable to check weather this is client or server.
But I know a way to make it more cleaner, Here it is:
Use a ModuleScript Initializer script to Initialize ModuleScript.
Now, before initializing, you can write code like this in the Initializing Script

_G.IsServer = Game:GetService("RunService"):IsServer --If initializing using ModuleScript
_G.IsServer = true --If Using Script
_G.IsServer = false --If Using LocalScript

In my game, I like to use ModuleScript to initialize other ModuleScript’s because it could be forked by a PreInitializing LocalScript And Script to fork these Initializing scripts to avoid Code Repetition.

You can also add properties that are often used in Scripts to _G table to avoid a little bit of code repetition.
Thanks!

2 Likes

I remember someone said this in my topic about custom services about _G

You’re not meant to use _G, global scope is messy and prone to initialization flow problems.

1 Like

What do you mean by :

Is it that if I use _G.Apple = 5 and _G.Apple = 10 in another script would override one another, If it is that, Let me tell you that I like to structure my _G table.
For Example:
_G.ImportantFunction --A Table For Some Functions
_G.ObjRegistry --Another Table To Store Custom Registered Objects

If you meant this, I would say it is up to Developer on how he manages His _G global scope.

The usage of _G and shared is not recommended. It’s not idiomatic and has race condition issues. Modules load at random so knowing if something will be overrode/expecting it to have a value is not assumable. It is also not very readable and developers rather easily be able to find their modules and their functionality. It doesn’t mess with Luau optimizations though, it’s just bad practice.

1 Like

I am just learning, can you tell me what could be a good practice to achieve a similar goal?

Not necessarily exact same goal, but you should primarily focus on using Modules. Modules are easy to track and when being required won’t have a race condition as require yields. Avoid anything that breaks Luau optimizations too like getfenv which would have the same issue as _G.

Can you explain how _G could break Luau optimization? Just curious to know.

It doesn’t. _G is simply bad practice and considered unreadable. It makes tracing where something came from difficult and is just not necessary when require functions the exact same without reading or race issues.

1 Like

In my game/project, I have implemented it in a hefty amount, I’ve categorized the _G into groups of tables, which are further divided into category tables, and I have also prepared a cheat sheet. So according to you, as you are more experienced, shall I still continue using it or I should replace it?

I’m not alex but you should replace the _G with the modules

2 Likes

Alright, So I would try to replace _G, Thanks!