Closed garystephens closed 7 years ago
IMO it would completely depend on the role of those parameters. For example if those parameters are there to fill the placeholders, then it is easy to test. But if they are boolean ones, then it would require more testing.
Moreover if function execution is strict i.e. requires all params (not more, not less) then it is easy to test but it would go difficult when function is coded otherwise.
And as Boolean params are already covered as bad practice, this section will more or less gets doubtful.
I completely agree with @garystephens, it's shifting complexity from arguments to an object. What you are also doing is forcing the caller of the function to know about the implementation ie. The caller now has to know what properties the object requires and what ones are optional in order to be valid, whereas, a function signature displays clearly what is required and what is not --- especially with ES2015 and using argument defaults eg. (required, notRequired = 'some-default') => {}
.
Another byproduct is, since this is Javascript, that the passed object can contain anything, which usually results in poorly thought out function scope eg. "Oh I now need loginButtonText
, signupButtonText
and username
in my Menu
, I'll just put them in the object too"; it's still just 1 argument, but the complexity has increased significantly. Combining the arguments alone does not solve the complexity issue.
A better example is:
// BAD
function createUser(name, email, addressLine1, addressLine2, city, state, country)
// Good
function createUser(name, email, address)
function createAddress(line1, line2, city, state, country);
So now you only pass 3 args, name, email, address
and address
is an object (DTO) that contains line1, line2, city, state, country
.
Note; For an address
to be valid, it requires all of those properties (well, line2
is debatable), so there's no reason to reduce this down to a single object argument ie. Even though there are 4 arguments for address
, I would still suggest this is valid, despite the guidelines in "Clean Code" requiring less.
I don't believe you need a rule to say "reduce args to a maximum of 2 at all costs" because there are so many exceptions to that rule. I believe if you follow the single responsibility "rule" in SOLID, your arguments will naturally be reduced as a result. Large numbers of arguments typically suggest that your function is doing more than 1 thing. If you encapsulate the data and abstract the logic into other functions, it usually reduces the number of arguments any one function requires.
Shifting to an object does keep some complexity you're right, it makes sense in many cases to break the function into multiple functions if you need a lot of arguments (that's probably another good subsection to have) There are three main benefits to using objects over a bunch of individualized paramters:
"Limiting the amount of function parameters is incredibly important because it makes testing your function easier. Having more than three leads to a combinatorial explosion where you have to test tons of different cases with each separate argument."
That's true, but the example "Good" code shown consolidates 4 parameters into an object, but they are still four separate input values, with the same number of possible permutations that need testing. So I don't see how this "make testing your function easier" (as compared to the "Bad" code example)?