views:

3486

answers:

33

Routines can have parameters, that's no news. You can define as many parameters as you may need, but too many of them will make your routine difficult to understand and maintain.

Of course, you could use a structured variable as a workaround: putting all those variables in a single struct and passing it to the routine. In fact, using structures to simplify parameter lists is one of the techniques described by Steve McConnell in Code Complete. But as he says:

Careful programmers avoid bundling data any more than is logically necessary.

So if your routine has too many parameters or you use a struct to disguise a big parameter list, you're probably doing something wrong. That is, you're not keeping coupling loose.

My question is, when can I consider a parameter list too big? I think that more than 5 parameters, are too many. What do you think?

+5  A: 

For me , when the list crosses one line on my IDE, then it's one parameter too many. I want to see all the parameters in one line without breaking eye contact. But that's just my personal preference.

Learning
This is good until you with with some devs would will try foo(int a, float b, string c, double d). Best to try to avoid working with them I guess. :D
Rontologist
If someone else has given classes ridiculously long names I wouldn't let that influence how I define or call my routines.
finnw
May I introduce you to the "carriage return" ?
Stuart
+6  A: 

I generally agree with 5, however, if there is a situation where I need more and it's the clearest way to solve the problem, then I would use more.

JTA
+3  A: 

According to Perl Best Practices, 3 is okay, 4 is too many. It's just a guideline, but in our shop that's what we try to stick to.

Adam Bellaire
A: 

Forty-two.

wnoise
:D Funny, but I won't upvote this.
Auron
Agreed. As much as I love it...
chills42
Mildly funny, but I wouldn't downvote it. It's already at -6: we get the point.
Just Some Guy
wnoise has wisely set his answer as community wiki from the beginning. He knew what to expect :D
Auron
It was intended to be funny, but there's a point that any hard cut-off is just as silly as 42. Programming is not engineering. Organization of code is an art because it depends on human factors, which depend too much on context for any hard rule.
wnoise
9 months on it's still funny!
Patrick McDonald
Lol, don't laugh I just got done coding against a web service and one of the methods took 41 params.
Funny. But really no need to make a comments that its funny but I won't upvote/downvote/lick/etc it
Stuart
+8  A: 

If you start having to mentally count off the parameters in the signature and match them to the call, then it is time to refactor!

Rob Walker
+8  A: 

It seems like there are other considerations than mere number, here are some that come to mind:

  1. logical relation to the primary purpose of the function vs. one-off settings

  2. If they are just environment flags, bundling can be very handy

John Mulder
A: 

It heavily depends on the environment you're working in. Take for example javascript. In javascript the best way to pass in parameters is using objects with key/value pairs, which in practice means you only have one parameter. In other systems the sweet spot will be at three or four.

In the end, it all boils down to personal taste.

Joeri Sebrechts
+1  A: 

I stop at three parameters as a general rule of thumb. Any more and it's time to pass an array of parameters or a configuration object instead, which also allows for future parameters to be added without changing the API.

Eran Galperin
If the API changes, then the API should actually change, not just have a stealth change where the incompatibility might still happen, but be less obvious.
wnoise
however, if you need one more parameter for configuring an edge case, it shouldn't propagate to non related components using the API
Eran Galperin
+4  A: 

I'd draw the limit for public functions at 5 parameters myself.

IMHO, long parameter lists are only acceptable in private/local helper functions that are only meant to be called from a few specific places in the code. In those cases, you may need to pass a lot of state information along, but readability isn't as big of a concern since only you (or someone who will maintain your code and should understand the fundamentals of your module) have to care about calling that function.

Kip
A: 

I'd say as long as you have overloads that have 2-4 than you're good to go up higher if you need it.

Chad Moran
+1  A: 

I'll agree with 3 is okay, 4 is too many as a guideline. With more then 3 parameters, you are inevitably doing more then one task. More then one tasks should be split into separate methods.

However, if I looked at the latest project I've worked on, the exceptions would abound and most cases would be hard to get down to 3 parameters.

kae
A: 

I think the actual number really depends on what makes logical sense with the context of the function. I agree that around 4-5 parameters starts getting crowded.

In the case of setting flags, a great way to handle this situation is to enumerate the values and OR them together.

j0rd4n
+31  A: 

When is something considered so obscene as to be something that can be regulated despite the 1st Amendment guarantee to free speech? According to Justice Potter Stewart, "I know it when I see it." The same holds here.

I hate making hard and fast rules like this because the answer changes not only depending on the size and scope of your project, but I think it changes even down to the module level. Depending on what your method is doing, or what the class is supposed to represent, it's quite possible that 2 arguments is too many and is a symptom of too much coupling.

I would suggest that by asking the question in the first place, and qualifying your question as much as you did, that you really know all of this. The best solution here is not to rely on a hard and fast number, but instead look towards design reviews and code reviews among your peers to identify areas where you have low cohesion and tight coupling.

Never be afraid to show your colleagues your work. If you are afraid to, that's probably the bigger sign that something is wrong with your code, and that you already know it.

Nick
+17  A: 

In Clean Code, Robert C. Martin devoted four pages to the subject. Here's the gist:

The ideal number of arguments for a function is zero (niladic). Next comes one (monadic), followed closely by two (dyadic). Three arguments (triadic) should be avoided where possible. More than three (polyadic) requires very special justification -- and then shouldn't be used anyway.

Patrick McElhaney
Does that absolute upper limit of 3 include or exclude "this" in OO languages?
Steve Jessop
I doubt it includes "this" because that is the context of execution. In functional programming, the context is global and in oop, the context is the object on which you're applying the method. Also, if you'd include "this" in the parameter list, then it would be impossible to have 0 params (ideal).
Tom
No, it doesn't include "this."
Patrick McElhaney
Furthermore, Martin should have a word with the C++ standard committee. Half of <algorithm> takes more than 3 parameters, because just one iterator range is 2 already. It's just the nature of programming with iterators (i.e. generic programming with STL collections).
Steve Jessop
+6  A: 

This answer assumes an OO language. If you're not using one--skip this answer (this is not quite a language-agnostic answer in other words.

If you are passing more than 3 or so parameters (especially intrinsic types/objects), it's not that it's "Too many" but that you may be missing a chance to create a new object.

Look for groups of parameters that get passed into more than one method--even a group passed into two methods almost guarantees that you should have a new object there.

Then you refactor functionality into your new object and you wouldn't believe how much it helps both your code and your understanding of OO programming.

Bill K
Please, name a language that doesn't use routines nor parameters. I can't think of one, even assembly could be considered to have routines (labels).
Auron
x86 assembly definitely has routines (call/return). Others may require cmp/jmp combos.
Brian Knoblauch
Sorry, "ret", not "return". Sighs. It's been a long day already.
Brian Knoblauch
Sorry about the ambiguous phrasing Auron, I believe I fixed it. It was my answer that was language-specific, not the question.
Bill K
Er... It's okay :)
Auron
Using an OO language is irrelevant. The object can be a structure, likewise the function parameters can be constructor parameters...
Stuart
Not all languages allow passing structures. Also, passing a structure means that the receiving method has to have the code to handle the structure and may, therefore, need more parameters. Also, in a non-oo language, you generally need an extra parameter--all OO languages have a "Hidden" parameter of "this" that should otherwise be passed in (or, in a more horrific language/design, might be globally accessible)
Bill K
+14  A: 

Some code I've worked with in the past used global variables just to avoid passing too many parameters around.

Please don't do that!

(Usually.)

Jeffrey L Whitledge
+2  A: 

A length restriction on a parameter list is just one more restriction. And restriction means applied violence. It sounds funny, but you can be non-violent even when programming. Just let the code dictate the rules. It is obvious that if you have many parameters, the body of the function/class method will be big enough to make use of them. And big code snippets usually can be refactored and split into smaller chunks. So you get solution against having many parameters as free bonus, since they are split among the smaller refactored pieces of code.

Anonymous
+2  A: 

One more than necessary. I don't mean to be glib, but there are some functions that necessarily need quite a few options. For example:

void *
mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t offset);

There are 6 arguments, and every one of them is essential. Furthermore, there's no common link between them to justify bundling them. Maybe you could define "struct mmapargs", but that would worse.

Just Some Guy
+22  A: 

A function can only have too many parameters if some of the parameters are redundant. If all the parameters are used, the function must have the correct number of parameters. Take this often used function:

HWND CreateWindowEx
(
  DWORD dwExStyle,
  LPCTSTR lpClassName,
  LPCTSTR lpWindowName,
  DWORD dwStyle,
  int x,
  int y,
  int nWidth,
  int nHeight,
  HWND hWndParent,
  HMENU hMenu,
  HINSTANCE hInstance,
  LPVOID lpParam
);

That's 12 parameters (9 if you boundle the x,y,w and h as a rectangle) and there's also the parameters derived from the class name as well. How would you reduce this? Would you want to reduce the number more to the point?

Don't let the number of parameters bother you, just make sure it's logical and well documented and let intellisense* help you.

Skizz

  • Other coding assistants are available!
Skizz
Why do you have to specify so many things when you create a window? Can't you specify that later in the code?
Auron
I'm voting this up. I am amazed at all the other answers saying "3" and "4"! The correct answer is: the minimum necessary, which can sometimes be quite a few.
Tony Andrews
@Auron - I've seen system like the type your are talking about. They were horrible because people the act of setting those parameters later in the code required the window to be destroyed and recreated. It was very slow.
Torlack
@Auron - that function is from the Win32 API. The window can be drawn before the function returns so all the parameters are necessary.
Skizz
Ok, I find that in very specific cases, like a call to an OS API, a long parameter list is acceptable.
Auron
If that function were designed today it would probably look a little different. x, y, nWidth and nHeight can be bundled in a Rectangle object. style and xStyle could be combined into a set of enums or strings. Now you have only 8 parameters.
finnw
"Now you have only 8 parameters." Exactly! Double the maximum stated by others. @Skizz - I agree with you on this one.
Jeffrey L Whitledge
@finnw If that function were designed today? It already has been redesigned. Form f = new Form(); has 0 parameters.
Nick
@Nick Guess what is called inside f.show() ? :) Easy to wrap this stuff up and make it warm and cuddly.
Stuart
A: 

IMO, the justification for a long param list is that the data or context is dynamic in nature, think of printf(); a good example of using varargs. A better way to handle such cases is by passing a stream or xml structure, this again minimises the number of parameters.

A machine surely wouldn't mind a large number of arguments, but developers do, also think of the maintenance overhead, the number of unit test cases and validation checks. Designers also hate lengthy args list, more arguments mean more changes to interface definitions, whenever a change is to be done. The questions about the coupling/cohesion spring from above aspects.

questzen
You crazy, man? A xml structure? For parameter passing? What do you have so much against using arrays that you must go through the whole overhead of writing the xml, and then parsing it 5 cpu cycles after?
Leahn Novash
+1  A: 

If I have 7-10 parameters in one routine I look at bundling them into a new class but not if that class would be nothing but a bunch of fields with getters and setters - the new class has to do something other than shuffle values in and out. Otherwise I'd rather put up with the long parameter list.

finnw
I will bundle it with a data-only class if it is used in more than one place, but even then I usually create both constructors.
Leahn Novash
+1  A: 

It's a known fact that, on average, people can keep 7 +/- 2 things in their head at a time. I like to use that principle with parameters. Assuming that programmers are all above-average intelligent people, I'd say everything 10+ is too many.

BTW, if parameters are similar in any way, I'd put them in a vector or list rather than a struct or class.

Milan Babuškov
+4  A: 

One of Alan Perlis's well-known programming epigrams (recounted in ACM SIGPLAN Notices 17(9), September, 1982) states that "If you have a procedure with 10 parameters, you probably missed some."

Peter S. Housel
+7  A: 

Thank you very much for all your answers:

  • It was a bit surprising to find people who also think (like I do) that 5 parameters is a good limit for the sanity of the code.

  • Generally, people tend to agree that a limit between 3 and 4 is good rule of thumb. This is reasonable as people usually have a bad time counting more than 4 things.

  • As Milan points, on average people can keep more or less 7 things in their head at a time. But I think that you can't forget that, when you are designing/maintaining/studying a routine, you have to keep in mind more things than just the parameters.

  • Some people consider that a routine should have as many arguments as it needs to. I agree, but only for a few specific cases (calls to OS APIs, routines where optimization is important, etc). I suggest to hide the complexity of these routines by adding a layer of abstraction just above these calls whenever possible.

  • Nick has some interesting thoughts on this. If you don't want to read his comments, I summarize for you: in a nutshell, it depends:

    I hate making hard and fast rules like this because the answer changes not only depending on the size and scope of your project, but I think it changes even down to the module level. Depending on what your method is doing, or what the class is supposed to represent, it's quite possible that 2 arguments is too many and is a symptom of too much coupling.

    The morale here is don't be afraid of showing your code to your peers, discuss with them and try to "identify areas where you have low cohesion and tight coupling".

  • Finally, I think wnoise much agrees with Nick, and concludes his satirical contribution with this poetical vision (see comments below) of the art of programming:

    Programming is not engineering. Organization of code is an art because it depends on human factors, which depend too much on context for any hard rule.

Auron
+1  A: 

I would base my answer on how often the function is called.

If it is an init function that is only ever called once then let it take 10 parms or more, who cares.

If it is called a bunch of times per frame then I tend to make a structure and just pass a pointer to it since that tends to be faster ( assuming that you are not rebuilding the struct every time as well ).

KPexEA
+1  A: 

According to Jeff Bezos of Amazon fame, no more than can be fed with two pizzas:

Kevin Pang
+1  A: 

A related question you should be considering is how cohesive the routine is. A large number of parameters may be a smell that's telling you that the routine itself is trying to do too much and hence it's cohesion is suspect. I agree that a hard and fast number of parameters is probably impossible but I would guess that a high cohesion routine would imply a low number of parameters.

Onorio Catenacci
+1  A: 

According to me there could be cases where you will exceed 4 or some fixed number. Things to lookout could be

  1. Your Method is doing too much and you need to refactor.
  2. You might want to consider using a collection or some data structure.
  3. Rethink your class design, maybe some things do not need to be passed around.

From an angle of ease of use or ease of reading code, I think when you need to kinda "word wrap" your method signature, that should make you stop and think,Unless you feel helpless and all efforts of making the signature smaller lead to no result. Some very good libraries in past and present use more than 4-5 prams.

Perpetualcoder
+1  A: 

According to Steve McConnell in Code Complete, you should

Limit the number of a routine's parameters to about seven

Paul Reiners
+2  A: 

My rule of thumb is that I need to be able to remember the parameters long enough to look at a call and tell what it does. So if I can't look at the method and then flip over to a call of a method and remember which parameter does what then there are too many.

For me that equates to about 5, but I'm not that bright. Your mileage may vary.

You can create an object with properties to hold the parameters and pass that in if you exceed whatever limit you set. See Martin Fowler's Refactoring book and the chapter on making method calls simpler.

Mike Two
+1  A: 

I agree with Robert Martin's quote in Clean Code (as cited above): the fewer parameters the better. More than 5-7 parameters and method calls become pretty hard to comprehend. Things get especially bad if some of the parameters are optional (and so take null values), or if all the parameters have the same type (making it even harder to figure out which parameter is which). If you can bundle parameters into cohesive domain objects like Customer and Account, your code will be much more pleasant to work with.

There is an edge case: if you have a method call that takes a variable number of parameters which form a logical set, there's less cognitive overhead having more parameters. For example you may need a method that specifies a number of HTTP request retries, in terms of the number of milliseconds between retries. Three retries at 1s, 2s, and 3s intervals could be specified as:

retries(1000, 2000, 3000)

In this limited case, adding more parameters to a call doesn't increase the mental overload that much.

Another consideration is if your language supports named parameter lists and allows you to leave out optional parameters. Larger named parameter lists are easier to comprehend than larger unnamed parameter lists.

But I'd still err on the side of fewer rather than more parameters.

Jim Ferrans
A: 

Worst 5 Code Snippets, check the second one, "Is this a constructor", it has like a 100 params.

medopal
+1  A: 

One thing I would point out from a performance perspective is that depending on how you pass parameters to a method, passing lots of parameters by value will slow the program down because each parameter has to be copied and then placed on the stack.

Using a single class to encompass all of the parameters would work better because a single parameter passed by reference would be elegant and cleaner, and quicker!

Dominic Zukiewicz