Feedback on my framework setup

Good evening dev forum. I am looking for feedback with my game framework/loader and ways I can improve it. I’ve made this framework to address the following issues:

  • Modules being unable to efficiently require other modules directly. While I am aware that it IS possible in the case you require another module into a separate thread, I believe that it is inefficient.

  • Organization.

This is how the setup looks in studio.

image

The core folder is where “core” scripts are stored that are basically the most important scripts. The modules folder is where I store modules meant to be used across multiple scripts for versatile use. And the objects folder is where I store objects that can be created (OOP).

This is how the loader script itself looks.

--[[
	
	This script is basically the server framework. Woohoo!
	
]]--

-- Services --

local ReplicatedStorage = game:GetService("ReplicatedStorage")

-- Variables --

shared.Server = {}

local Modules = {}

-- Main Code --

function shared.Server:Require(name)
	return require(Modules[name])	
end

for _, folder in pairs(script:GetChildren()) do
	for _, module in pairs(folder:GetChildren()) do
		Modules[module.Name] = module
	end
end

for _, module in pairs(ReplicatedStorage:WaitForChild("Shared"):GetChildren()) do
	Modules[module.Name] = module
end

for _, module in pairs(Modules) do
	spawn(function()
		require(module):Init()
	end)
end

Known cons of what the loader has:

  • Circular dependency.
  • You can’t have any script have duplicate names.

I am asking for your feedback on how I chose to organize everything and improvements I can make.

2 Likes

First of all, recursive(or circular) modules are highly discouraged. Second of all, instead of using

SPAWN

Use coroutine!

spawn(function() -- Not this
    -- code
end)

coroutine.wrap(function()
    -- code
end)() -- Don't forget the last 2 brackets

The reason for this is because spawn can take time (like, many, many, seconds) to actually execute. coroutines don’t.


Edit: Spawn is only bad when used in excessive amounts
Thank you, @sjr04.

3 Likes

Belongs in #help-and-feedback:code-review, but for review, I would stay away from using shared. What if someone who uses your framework uses shared and wants to share a global variable of “Server” across scripts? Nobody should use shared or _G, ever. You are potentially interfering with other scripts, which modules should never do. Modules are better for this. Reusability. Using shared or _G kinda defeats the whole purpose of modules

I’m not sure if making a loader like this is even a good idea? It seems more maintainable to directly require every module as-needed in a file. (Also, what limited intellisense Roblox Studio provides actually persists if you do so)

Thank you guys for your feedback!

I primarily made this loader so modules can easily communicate with each other with ease, as right now, it’s not necessarily possible to do such unless you create a seperate thread to require each module (which is inefficient and sloppy imo). The purpose of the loader is primarily to store each module in a table. So the module can access another one by having a global function within the script return the requested module.

Yeah. That’s definitely an issue I’ve been wary of. While I don’t have any plans to open source this (this is rather a private thing for me), it’s definitely an issue to use global variables in general due to the conflicts you’ve mentioned.

Thank you for the feedback! I had no idea about that. I’ll definitely switch over to using coroutines.

It looks like you might see some use out of AeroGameFramework.
Find it here: https://github.com/Sleitnick/AeroGameFramework