Cleaner way to handle a lot of args and parameters

Most of the the time my functions only need one or two arguments, but sometimes there are functions that will use a bunch, mainly for settings

for example

Movement.Jump(rootPart, yOffset, timePerWaypoint, jumpTime, jumpDistance, jumpHeight, jumpCurve, maxFinishHeight, maxFallheight, debugMode, debugWaypointsFadeTime)

one solution I thought of is using a table

local jumpData = {
   RootPart = character.PrimaryPart,
   YOffset = y,
   -- .. etc
}
Movement.Jump(jumpData)
function Movement.Jump(jumpData)
   print(jumpData.RootPart.Name, jumpData.YOffset)
end

the table version is nicer on the eyes, and prevents misalignment of args and parameters, but it also requires you to either remember all the jumpData args or have to go back to whatever script called it and see what they are

any better ways?

1 Like

Functions that require that many parameters are a poor indicator; it often means that the function’s purpose is ill-conceived and should be refactored in favor of readability and maintainability. In fact, in this case, I’m almost sure of it.

As for the formatting of it, it doesn’t hurt to have the function call span multiple lines, consider your example:

This could be written as follows:

Movement.Jump(
    rootPart,
    yOffset,
    timePerWaypoint,
    jumpTime,
    jumpDistance,
    jumpHeight,
    jumpCurve,
    maxFinishHeight,
    maxFallHeight,
    debugMode,
    debugWaypointsFadeTime
);
2 Likes

This is what I believe is correct,

You seem to have some variables indicating a “max” amount of something, I am guessing those are constant variables anyways so it would be weird to send them as arguments instead of localizing them so that the function sees it without needing to have them as parameters.

1 Like

I think this is the case, that constants don’t necessarily need to be supplied through parameters and can just be declared as some local variable that’s treated as immutable.

In the chance @Quoteory needs to supply the constants, I recommend the following design pattern:

--- A function that does things.
--- @param {any} parameterOne - The first parameter.
--- @param {any} parameterTwo - The second parameter.
--- @param {table} options - The options to use.
--- @param {any} options.optionOne - The first option.
--- @param {any} options.optionTwo - The second option.
local function foo(parameterOne, parameterTwo, options)
    -- Do things here
end

The reason I was passing args that should be variables is because I just wanted to split certain functions into different modules to make the base script a bit more readable (where I keep all the variables like jumpTime etc), but it didn’t really work

If that’s the case, you could create a submodule of some base module that exports a table containing all your constants for said module to be required by all other submodules. I definitely recommend you keep your projects DRY – Don’t Repeat Yourself.