One of the most frequent problems I’ve been having with my project recently is organization, and I find myself revamping it more than actually creating new systems. I’ve been looking into other topics about module loaders, frameworks, and single-script architectures for a while now, and I’ve put together a basic system from that, but I’m still not completely satisfied with it.
Right now I have a basic module loader setup of a single script (in ServerScriptService) and localscript (in StarterPlayerScripts) that loop over all of their modules, require them and add them to a table, then call their Init() and Start() functions. Something like this:
local modules = {}
local function Setup(path)
for _, module in pairs(path:GetDescendants()) do
if module:IsA("ModuleScript") then
modules[module.Name] = require(module)
end
end
end
Setup(script)
Setup(ReplicatedStorage)
for _, module in pairs(modules) do
if module.Init then
module.Init(modules)
end
end
for _, module in pairs(modules) do
if module.Start then
module.Start()
end
end
From there, the ModuleScripts usually follow this basic stucture:
local Module = {}
-- Services here
-- Other modules here
local Module1
local Module2
-- Module-specific functions here
-- Init (Optional, generally used if module creates connections or requires other modules)
function Module.Init(modules)
Module1 = modules.Module1
Module2 = modules.Module2
end
-- Start (Optional, generally used if module changes other objects)
function Module.Start()
end
return Module
This setup is fully functional and prevents cyclic require() calls, but there are a few points I dislike about it:
- Every time I want to use another module, I have to add a new variable at the top of the script and set that variable in the Init() function.
- It doesn’t support autocompleting module functions because it isn’t requiring them directly.
- I used this to allow modules to require eachother, but I should probably be avoiding that outright.
Additionally, a different pattern I have seen is to store module references in a “core” ModuleScript and have other modules require that instead of using the Init() function as seen above. Would that be a better alternative?
Regardless, I’d like to know if there’s anything I’m doing wrong with this and if anyone more experienced with organizing projects can give advice or examples.