Are there guidelines on how many parameters a function should accept?
I've noticed a few functions I work with have 6 or more parameters, whereas in most libraries I use it is rare to find a function that takes more than 3.
Often a lot of these extra parameters are binary options to alter the function behaviour. I think that some of these umpteen-parametered functions should probably be refactored. Is there a guideline for what number is too many?
A lot of people here saying that this isn't really the way to go with a on of parms. However what about object constructors. Taken an ORM with a class and its INIT method. I have had cases where i would need 10 or more params that have to be set to something that can't default well. I hate looking at the init function because its hard to work with and hard to remember. Is a constructor an OK edge case or is there a better way to do it?
@Ominus: The idea is that you want to keep your classes focused. Focused classes usually do not have as many dependencies/attributes therefore you'd have less parameters to the constructor. Some buzz word people throw in at this point is *high cohesion* and *single responsibility principle*. If you feel that these are not violated and still need lots of params, consider using the Builder pattern.
Definitely don't follow the example of MPI_Sendrecv(), which takes 12 parameters!
A non negative amount. If the amount is too big for comfort, consider using complex parameters, object fields/properties, optional parameters, overloads.
@Ominus you should ask that in a question, not a comment. Also the answer is no.
The project I'm currently working on uses a certain framework, in which methods with 10+ parameters is commonplace. I'm calling one particular method with 27 parameters in a couple of places. Every time I see it I die a little inside.
Never add boolean switches to alter function behavior. Split the function instead. Break out the common behavior into new functions.
Yes, there are guidelines. One of the guidelines says at most three parameters. Another guideline says up to five. Another guideline says use 0 and use global variables to transfer data around. Another guideline says as many as necessary and definitely don't do what the previous guideline said.
One practical consideration when designing your API is Java is limited to 255 parameters (minus one for every long or double typed parameter). I try to stay under 200 just to be safe.
I just wanted to point out that there are very legitimate libraries with 25-parameter constructors. In this case, it's actually quite necessary!
I've never seen a guideline, but in my experience a function that takes more than three or four parameters indicates one of two problems:
- The function is doing too much. It should be split into several smaller functions, each which have a smaller parameter set.
- There is another object hiding in there. You may need to create another object or data structure that includes these parameters. See this article on the Parameter Object pattern for more information.
It's difficult to tell what you're looking at without more information. Chances are the refactoring you need to do is split the function into smaller functions which are called from the parent depending on those flags that are currently being passed to the function.
There are some good gains to be had by doing this:
- It makes your code easier to read. I personally find it much easier to read a "rules list" made up of an
ifstructure that calls a lot of methods with descriptive names than a structure that does it all in one method.
- It's more unit testable. You've split your problem into several smaller tasks that are individually very simple. The unit test collection would then be made up of a behavioral test suite that checks the paths through the master method and a collection of smaller tests for each individual procedure.
Parameter abstraction has been turned into a design pattern? What happens if you have 3 parameter classes. Do you add 9 more method overloads to handle the different possible combinations of parameters? That sounds like a nasty O(n^2) parameter declaration issue. Oh wait, you can only inherit 1 class in Java/C# so that will require some more biolerplate (maybe some more subclassing) to make it work in practice. Sorry, I'm not convinced. Ignoring the more expressive approaches a language may offer in favor of complexity just feels wrong.
Unless you use the Pattern Object pattern to package variables in an object instance and pass that in as a parameter. That works for packaging but it may be tempting to create classes of dissimilar variables just for the convenience of simplifying the method definition.
@EvanPlaice I'm not saying that you have to use that pattern whenever you have more than one parameter - you're absolutely correct that that becomes even nastier than the first list. There may be cases where you really do need a large number of parameters and it just doesn't work to wrap them up in an object. I've yet to meet a case in enterprise development that did not fall into one of the two buckets I mentioned in my answer - that's not saying one doesn't exist though.
@MichaelK If you have never used them, try googling 'object initializers'. It's a pretty novel approach that significantly reduces definition boilerplate. In theory, you could eliminate a classes constructors, parameters, and overloads all in one shot. In practice though, it's usually good to maintain one common constructor and rely on the 'object initializer' syntax for the rest of the obscure/niche properties. IMHO, it's the closest you get to the expressiveness of dynamically typed languages in a statically typed language.