Wich Method for Modules are better?

Hi everyone,

I’m working on a ModuleScript to handle the movement of an elevator in my project. I’m trying to decide between two approaches for structuring the module and wanted to hear your thoughts on which one is considered better in terms of readability, scalability, and maintainability.

Here are the two approaches I’m considering:

Approach 1:

local MoveElevator = {}


MoveElevator.move = function()
	
end


return MoveElevator

Approach 2:

return {
	move = function()

	end,
}

1st is better because it is more readable and is indexed as a global function. For example, if you wanted to index another function inside inside self inside another indexed function you can simply do as follows:

local t = {}

t.lerp = function(a,b,t)
    return a + (b-a) * t
end

t.getval= function(a,b,t)
    return t.lerp(a,b,t)
end

You’ll find that often you may want to reuse a function in another you are writing, so it’s always best to index the functions first.

1 Like

Just personal preference to be honest, and I use some in differing situations.

For example if i have a shared dictionary of functions (so that they could be inserted into other things), I use approach 2.

For example: Having an AI Pathfinding Component, It’s just a big list of functions that all achieve the same thing so i’d do it like this

local PathfindingComponents = {
  Default = function (self, Target)
        --...
  end);
  
  Spacing = function (self, Target)
        --...
  end);
}

return PathfindingComponents

If I have something for a more general purpose structure or oop related I usually do it like this:

local PublicClass = {}
local PrivateClass = {}
PrivateClass.__index = PrivateClass

function PublicClass:PublicMethod()

end

function PublicClass.newPrivateClass()
    return setmetatable({}, PrivateClass)
end

function PrivateClass:PrivateFunction()

end

return PublicClass
1 Like

Same, sometimes if all I want to return is a list of colors or string escape characters I will simply just do

return {
   color1 = Color3.new(1,1,1)
}

but for object purposes I will do the second

I while i was typing it out, people were replying so i might say some stuff thats the same

Well, both works the same.
If your trying to keep it simple, go with the first one.
BUT THIS IS A BIG DIFFRENCE
Lets say you make a script like this

local function moveElevator (studs:number)
	
end
local studsMax = 10
return {
	move = function(studs)
		moveElevator(studs)
	end,
	goUp = function()
		moveElevator(studsMax)
	end,
	goDown = function()
		moveElevator(0-studsMax)-- 0-varible makes varible negative
	end,
}

And, If You use the other way, this is the result

local MoveElevator = {}
local maxStuds = 10

MoveElevator.move = function(studs)

end

-- MoveElevator.move() YOU COULD CALL MOVE HERE

MoveElevator.goUp = function()
	MoveElevator.move(maxStuds)
end

MoveElevator.goDown = function()
	MoveElevator.move(0-maxStuds)
end

return MoveElevator

The Diffrence, If you call a functinon for a module and don’t return it yet, you could stilll call the function.

In the first way, we needed to create a function for a elevator to move for both module and script

It makes the script Simpler and shorter IF the move function is long

Also, i would recommend doing this:

local MoveElevator = {}
local maxStuds = 10

MoveElevator.move = function(studs)

end

MoveElevator.Finish = function(time)-- IDK if you need this but . . .
	
end

return {
	move = MoveElevator.move,-- CHECK IF THERE IS NO ()
	finish = MoveElevator.Finish,-- CHECK IF THERE IS NO ()
	goUp = function()
		MoveElevator.move(maxStuds)
	end,

	goDown = function()
		MoveElevator.move(0-maxStuds)
	end,
}

Neither, you should be using the normal function assignment method:

local module = {}

function module.DoSomething()

end

return module

If you only want to return an immutable table of the functions you can do this:

return table.freeze({
    DoSomething = module.DoSomething
})

It’s a very nice and neat way of putting functions into modules as opposed to setting a key in the table to a anonymous function.

This also supports the self syntax of making functions as well (used only for OOP).