I recently wrote a small function. And thought of different ways of implementing it.
Basically the function accepts a parameter and do string manipulation.
Which would be preferred?
function (arg) {
let optionResult = ''
if (arg === 'option1') {
optionResult = // do stuff for option1
} else if (arg === 'option2') {
optionResult = // do stuff for option2
} else if (arg === 'option3') {
optionResult = // do stuff for option3
}
return optionResult
}
or instead
function (arg) {
let optionResult = {
'option1': // do stuff for option1,
'option2': // do stuff for option2,
'option3': // do stuff for option3
}
return optionResult[arg]
}
Top comments (25)
Either way I'll not use
if
for more than 2 options, and because the devs are usually lazy and do not refactor and just add a new option, I tend to never use it.The answer depends a lot on the size of the do stuff code blocks.
1-2 liners I suggest using a
switch
If there are more I would suggest using a map, similar to your 2nd version but it can be replaced with other functions. This is how actually some compilers transform the
switch
.Because of the size of the function (now in the x * 10s) I would transform this function to a module, and declare the option functions outside of the main function.
The code can grow independently, the functions will not be "compiled" until they are called for the first time and they can be tested independently, if needed.
3 . 2 can be future extended, if needed to one of Plugin/Services/Inversion of control pattern, mainly to inject new functionalities in the map as more modules are active in your project.
This is a great improvement over the second version.
The only issue I find is that the code for the function is no longer inside the function itself but outside. Maybe this will solve the issues:
Functions in functions I would say is smelly code, anyway if there are 5 options each with 7+ LOC then the main function will become too big, that is why I said to make a distinct object/module, with a size of 50+ LOC would probably required its own module. Then the functions being outside is ok, because they are encapsulated by the module.
The second example looks a lot nicer to me.
Note 1: you can use const instead of let in your second example because you do not transform the object anywhere in your function.
Note 2: second example will return undefined instead of
''
if the key in the object does not exist. I think you'd handle that as well.*because you do not reassign the reference.
You can transform an object variable declared with
const
.Thanks for pointing out the difference between
let
andconst
, I'll keep that in mind.The first option is best here for 3 reasons:
optionResult
is actually aswitch
orif else
arg
has an unexpected value, whereas in the second version you can't do that unless you check ifoptionResult
doesn't have the property which further adds to the complexity of the function.You can also straight up return the
optionResult
inside the if statements if no post-processing is needed.Thanks for the detailed response,
I agree that in the code above I haven't considered doing some validation.
I agree with the other responses that the second function looks much cleaner in this example, though it could also become less intuitive as the complexity of the logic that replaces
// do stuff for option(n)
increases.Ternary Operator:
That looks ugly
I had to say why do I prefer it and why, right?
switch
, no fall-through footgun here.if-else-return
.While it might not be the prettiest code to see - it's what we currently have in the language, also it's pretty straightforward to understand.
Let's split on the principles that describe the needs:
Results:
I see often people trying to replace a switch with an object.
On the eye it's pleasant but in reality it's not using the simplest language construct to do the job, it's allocating memory for an object only to perform a string comparison.
Moreover many people don't take in account the "key not found" scenario leading to functions that errors or return undefined.
Using an object, where the keys are unique and translate to an action or value, is preferred because it reduces the complexity to a single path instead of multiple with switch or if. Can be externalized into a constant and have the function be
If only one of the string manipulation functions should be run, then I would recommend ramdajs.com/docs/#cond which will only run the first condition which matches. The switch statement could run multiple times if a break or return is forgotten.
2 option is much better, but the function still not the best in the best form , optionalResult is created everytime function is used, if its used multiple times, that is a waste of time, so it should be initialized out of scope, and best passed as an argument to the function to avoid sideefects.
Why not just switch?
developer.mozilla.org/en-US/docs/W...
Yeah, been thinking of using
switch statement
.It's just that for me it looked much harder to read at first compared to using
if statement
.