Thoughts/Problems with a script architecture like this?

Would the following script architecture be effective? I have a local script that has child module scripts. The local script will call a bootstrap function to get all the child modules and then check if they have a public “init” or “bootstrap” function. This can later be expanded to giving the modules public “playerAdded” functions and calling them from the local script. This would mean I only have to write event connections once on the local script and then call the modules’ functions from inside those event connections there. Here is the code:

Local Script:

local function getModules()
    local _a = {} -- Make a temporary holder table
    for _, v in pairs(script:GetChildren()) do -- Loop through all the modules in the Common folder and put them inside our _a
        if v:IsA("ModuleScript") then -- Check if it is a module
            _a[v.Name] = require(v) -- Put the required version in the table indexed to its name
        end
    end
    return _a -- Return our holder table
end

local function activateModules()
    for name, mod in pairs(modules) do -- Loop through the modules in the modules table

        if mod["init"] then -- Check if the module has the init function
            mod.init() -- Call the init function
        end

        if mod["update"] then -- Check if the modules has the update function
            local _a = runService.RenderStepped:Connect(function(deltaTime) -- Connect the update function to renderstep
                mod:update(deltaTime) -- Call the update function
            end)
            renderSteps[name] = _a -- Add the connection to the renderSteps table for cleanup
        end
        
    end
end

local function bootstrap()
    -- Activate all modules
    modules = getModules() -- Gets all the child modules in this script
    activateModules() -- Require all modules and set up their init and update functions
end

example of a child module script

local testModule = { }

function testModule.init()
    print("This function has been called by the parent local script!")
end

function testModule.update()
    print("This function has been called by the parent local script inside of a render step connection!")
end

return testModule

My goal for this post is to learn the possible downsides (if any) of using this method. So far it’s advantages seem to be: OOP orientated, Less repeating code, easy cleanup for memory since only 1 shared event connection per module. Those are only a few I can think of off the top of my head.

This is a really small nitpick, but I don’t think mod:update() needs to be an OOP method and you should just keep it as a regular function. Because that way, you don’t need to wrap it in a new function for the RenderStepped connection, thus saving a bit of performance by avoiding redundant function calls.

local _a = runService.RenderStepped:Connect(mod.update)
1 Like

Whoops, you are correct I didn’t mean to make it a colon thanks for the fix!