Refactor SetConstant to use a lookup table#20
Conversation
Coffilhg
left a comment
There was a problem hiding this comment.
That makes sense. You might also make setters perfectly safe, e.g. ProfileStore.SetConstant("AUTO_SAVE_PERIOD") would reset the value to default, like you could make the setter callback be:
AUTO_SAVE_PERIOD = function(v)
if type(v) ~= `number` then
warn(`[{script.Name}]: SetConstant "AUTO_SAVE_PERIOD" ~> A number expected, got {type(v)}; Resetting to default value of 300`)
AUTO_SAVE_PERIOD = 300
return
end
AUTO_SAVE_PERIOD = v
end
Good idea; I’ve updated the setters to reflect this suggestion. Each one goes through a SafeSet utility, which enforces the type check and returns either the valid number or the default. That means even if someone bypasses SetConstant and calls a setter directly, it still goes through SafeSet and can’t corrupt the constant. |
Coffilhg
left a comment
There was a problem hiding this comment.
Yup! This is almost perfect now.
I'm surprised all of the settings are numbers. But for convenience of future changes we might make it more flexible. There's also a little thing we forgot about that errors if we input non-number value instead of setting the defaultValue at the start of the SetConstant method.
The changes would look something like:
-- a lot of original code
local function SafeSet(name, v)
-- we could cache DEFAULTS[name] once (micro-optimization to reduce table accesses]
local defaultValue = DEFAULTS[name]
local defaultType = type(defaultValue)
local inputType = type(v)
if inputType ~= defaultType then
warn(`[{script.Name}]: SetConstant {name} ~> A {defaultType} was expected, got {inputType}; Resetting to default value of {defaultValue}`)
return defaultValue
end
return v
end
-- note: type() is limited to basic datatypes, if we want to support Roblox datatypes too, we could use typeof() instead of type() in SafeSet
-- a lot of original code
function ProfileStore.SetConstant(name, value)
-- this one is not necessary, we have SafeSet to handle this
-- if type(value) ~= "number" then
-- error(`[{script.Name}]: Invalid value type`)
-- end
-- everything else unchanged
local setter = ProfileStore._constantSetters[name]
if setter then
setter(value)
else
error(`[{script.Name}]: Invalid constant name was provided`)
end
end
-- a lot of original codelastly you could make the type ConstantName become the product of doing keyof of DEFAULTS, so this becomes very flexible - you only change DEFAULTS and it works.
Once you're done, you could commit to the V2 fork I made - https://github.com/Coffilhg/ProfileStoreV2
(Only if you want to)
The current implementation of
ProfileStore.SetConstantrelies on a long if/else chain to assign values. While it works, this approach:Solution
Refactored
ProfileStore.SetConstantto use a private lookup table (_constantSetters) scoped inProfileStore.Benefits