The Design of Software (CLOSED)

A public forum for discussing the design of software, from the user interface to the code architecture. Now closed.

The "Design of Software" discussion group has been merged with the main Joel on Software discussion group.

The archives will remain online indefinitely.

Correct number of parameters for a function.

A while back, somebody was asking an interview question about "How many parameters a function should have" or something like that.

Just now, I'm looking through some old code of mine, and I found a single function call that is 135 lines long, full of parameters. This is due to this little pattern:


...all of the parameters are newed Objects(), all of which constructors ALSO have the foo(Object...obj) pattern. Seems like the average line length is about 150 characters.

I'm wondering if anybody can beat that.
Tuesday, February 20, 2007
"Beat that"? -- that sounds horrible.
Tuesday, February 20, 2007
I thought a good answer would be "no more than 7, +- 2, and preferably less."

That's like asking what's the correct number of rivets when attaching a metal panel.  "It depends" -- on the size of the panel, the size of the rivets, and how strong it has to be.

As few as possible, but no fewer?
Tuesday, February 20, 2007
Wow...  personally I was thinking 4 +/- a couple...  150 is pretty sick.
KC Send private email
Tuesday, February 20, 2007
The correct number, as for many other things in programming, is 0 or 1.  For anything else, using currying (or as Dr. Hiz used to say, Schoenfinkelization):
Will Dowling Send private email
Tuesday, February 20, 2007
Oh, I MUCH prefer the term "Schönfinkelisation" -- Currying sounds like something you do to a chicken.

And of course, every Structured Programming statement (you know, those pesky "IF-THEN","WHILE-DO", "REPEAT-UNTIL", "SUB ENDSUB") can be reduced to a decision and a goto.

But just because you CAN doesn't mean you SHOULD.  And the "correct number" seems to imply doing things that are a good idea -- not merely the minimum possible.

In short -- good math maybe, but poor engineering practice.
Tuesday, February 20, 2007
I thought a good answer would be "no more than 7, +- 2, and preferably less."

Terrible answer. What does short term memory limits have to do with anything. This is not quite as foolish as the common and incorrect claim that menus should have "7, +- 2" items in each menu, or forms should only have "7, +- 2" elements.

Please, for goodness sakes, read the darn research findings before deciding to apply magic numbers to everything under the sun with no understanding and a haughty attitude.

Example: 1,000,000 parameters to a function is not a problem, when it's a 1000x1000 array.
Meghraj Reddy
Wednesday, February 21, 2007
The minimum necessary to achieve the function's goal(s). 

When designing a new function, the objective should be to define the function to do 1 clearly-defined thing, and do it well, with least dependency possible on global state/data.

There may of course be special circumstances which affect the definition of the "minimum necessary".

If backward compatibility is required for the function with previous versions (for example in API call which other code depends on),  it may be unrealistic to change the function signature, in which case, you may have more more or less parameters than ideal.

If anticipation of future need for backward compatibility is required (again an API call, which may do extra things in future), it may be wise to include extra currently unused parameters in anticipation of these future needs.  For example, if designing a graphics API with a line function, you might include a linestyle parameter for future needs, even though, the present version of the library only could draw solid lines.
S. Tanna
Wednesday, February 21, 2007

In every way that actually matters, a 1000x1000 array would be *one* parameter.  I'd feel really, really bad about myself if I made someone else use a function that required even as many as 7+-2.
Notorius L
Wednesday, February 21, 2007
I think the answer "As few as possible and no fewer" is best in terms of design, but in terms of optimisation I have vague recollections that there's a maximum number of parameters which will be stored on the registers and the rest are thrown on the stack. In which case there's probably an optimal answer depending on that (which depends on the hardware in question).
MikeD Send private email
Wednesday, February 21, 2007
Okay, you've coaxed me out of lurk mode.

The problem with function parameters in most programming languages is they're a list that has to be given in a certain order. The meaning of an argument is determined entirely by its order in the list. That makes it hard to follow a long parameter list. It starts to get unmanageable at about seven.

If you really think you need to feed more than six independent pieces of data to a function and that making them all parameters is the way to do it, maybe it's time to refactor?

Perl has a way to pass arguments as a "hash" created on the fly. Most Perl syntax is horrible but this feature is actually very nice.
Rowland Send private email
Wednesday, February 21, 2007
BillT Send private email
Wednesday, February 21, 2007
> How many parameters a function should have?

How about ... "Ideally, no more than 2"?

0 => a property
1 => a method
2 => less common than 0 or 1 ... for example, one of the solutions to might be

class Display
  void display(Tile tile,Strategy strategy);
Christopher Wells Send private email
Wednesday, February 21, 2007
Old Fortran code is notorious for functions with hundreds of parameters.

Somebody said, "if your function has more than nine parameters, you have probably forgotten one." Really if you have more than four or five, you should start thinking about bundling up the data somehow. That was something that Fortran provided no help for, so the you had to have Jupiter's mass, and the mean temperature on Neptune, and all 1250 parameters of your orbital computation in the parameter list. But we can do better with modern languages, including, I hope, modern Fortran.
dot for this one
Wednesday, February 21, 2007
"no more than 7, +- 2, and preferably less."

7 +/- 2 is the limit of the number of things one can contemplate at once. If your function has nine parameters, then you drive everything else you were thinking about from your short term memory while you get the parameter list right.

For example, compare C's standard library function fopen, where you have

filePtr = fopen(file_name, "w")

two parameters, with the Windows API call to CreateFile which has 7. Okay, who remembers them all? And hopefully you have abstracted CreateFile, if you use it in more than a few places in your program.

And if youare only able to keep 5 things clear, instead of 9, then CreateFile itself will put you on overload briefly.
dot for this one
Wednesday, February 21, 2007
"7 +/- 2 is the limit of the number of things one can contemplate at once. "

The "7 +/- 2" refers to the human "digit span". It's the average of the average scores of test subjects listening to and repeating back random digit streams. The +/-2 represents roughly the standard deviation.

It IS the reason phone numbers used to be limited to seven digits; because most people can reasonably easily repeat a stream of seven digits back.

But it's probably not a good measure to use for routine prototypes. Firstly it's a cyclical memory. It's theorised that it works by having you internally "say" the stuff out of the end of it and fed back to the start...[1][2] which isn't really how routine parameters work.

Secondly the symbols in that space are digits/letters and not complicated symbols such as variables and their interpretation.

[1] The next stage of memory is "trained" by the repetition and can then hang onto the information long enough for long term storage to pick it up.

[2] Kind like a mercury delay line.
Katie Lucas
Thursday, February 22, 2007
I recently ran again into the definitions of "Module Cohesion" and "Module Coupling".

Large parameter lists were done in the days BEFORE we understood what makes good coupling between modules.  Like Unix command line options, and the Windows API, and FORTRAN programs (don't even get me started about COMMON blocks, oy).

A whole lot of parameters means you have a whole lot to understand (and keep in your head at the same time) about what the 'called' routine is going to do about each of those parameters. 

Good design principles say that a called routine should do ONE function -- it may be quite an intricate function, like "figure out how many people live in America" -- but one function.  And it may call lots of subordinate modules to do that work.

Allowing LOTS of parameters means you can have a 'switch' control parameter that lets that module do LOTS of unrelated things.  Not a good thing.

Personally, I like two input parameters and one output parameter, with the 'return()' value reserved for a 'success' or 'error' indicator.  However, often this is not practical.  If you've gotten beyond 9 parameters, that just cries out for refactoring to me.

So "as few as possible, but no fewer" still seems to apply.
Thursday, February 22, 2007
Oh, and note the Unix API (system calls, standard library) itself tends to be quite cohesive, with not a whole lot of parameters for each library call.

And yes, I know the "printf" "(...)" operator allows variable lists of parameters, but I'm not fond of that either.
Thursday, February 22, 2007
Will, what makes currying simpler? It doesn't seem simpler.
son of parnas
Thursday, February 22, 2007
Currying has nothing to do with the number of parameters taken by a given function at the point of defining that function so I'm not sure why it was even mentioned here.  I guess some people just like to feel smart by throwing around terms that they don't really understand.  Currying allows you to adapt functions with greater-than-n number of parameters to fit a context that expects a function that takes n parameters.  Currying would be fairly pointless in a world where no functions had greater than zero or one parameters.
SomeBody Send private email
Thursday, February 22, 2007
The correct number of parameters for a function is based upon the number it needs to do its job. 

There is a limited set of alternatives to providing parameters:

1) Use class data
2) Create an internal instance
3) Use global data

If the data is used by more than one function in a class, make the data into a class variable defined at class construction.  If the data is only used by a single function, do not include it as a class variable.  Avoid using properties that must be set prior to calling a method - violating this rule is bound to lead to strange operation when someone forgets to set a property.

Objects used by a method can be constructed within the method.  A stream class is a good example.  Martin Fowler, however, recommends paasing these types of objects into the class as parameters.  I have found that Mr. Fowler's recommendation  simplifies unit testing.

Lastly, global data or objects can be declared.  This  is not typically a best practice, but I have found it useful for a limitted set of capabilities such as logging.  It becomes quite tedious to pass a logging object into every class and this is one of the few places where a global object seems beneficial.

I don't believe there is any hard and fast rule for the correct number of parameters for a function.  The function needs the data necessary to do its job.  If a function list starts to get subjectively long, I will look at it to see if the parameter list can be pruned, but I would not jump through hoops to reduce the size.
Wayne M.
Friday, February 23, 2007
Some people define "Simpler" as "a function is simpler if it has only zero or one parameter.  Simpler, in any event, than one that has MORE parameters."

This is the problem with using "simpler" as a design criteria -- there's so many different ways it can be interpreted.

Let's say you had an application that had a module with 5 parameters that returned a result.  Now, if you "Curry" that module into 5 modules, each with ONE parameter, each of which does 1/5th of the computation, is that simpler?  Each MODULE almost HAS to be simpler.  But is the APPLICATION simpler?

And if it was a non-trivial module, which didn't conveniently break out into 5 pieces, then some of the 5 might have to re-do some of the computation of the other 4 modules.  Would that still be simpler?  Would it be more redundant?

I'm assuming you don't use Global Memory to store some of the results, and get around the limitation that way, because that's just sweeping what was a visible issue "under the rug". 

You could define a data structure, and pass THAT as a single parameter, and store your 'intermediate results' in there.  That moves some complexity from code into data, which is often a valid thing to do, but does it make this solution "simpler"?
Friday, February 23, 2007
> This is the problem with using "simpler" as a design criteria

Simpler is like saying I want a painting to be beautiful. It doesn't give the artist much useful guidance and when you are done everyone will have a different opinion on the result.
son of parnas
Friday, February 23, 2007
As many as you need?
Jason Send private email
Friday, February 23, 2007
This is sort of related to the concept of objects. An object, as I guess we all know,is a bunch of related data items with an interface wrapped around them. The object tends to have a coherent meaning of its own.

So pass objects to functions, not lots of little bits of data - this probably violates encapsulation. If you're passing 135 parameters, it suggests that either lots of those parameters are related and probably ought to be objects, or that you really have 135 distinct types of thing - all different and unrelated - which need to be processed in one function. I'd hate to see the problem that really needed that.

Less than 4 is best. Up to 7 - ok. More than 10 - no thanks. Unless you really have no choice.

Duncan Sharpe Send private email
Monday, February 26, 2007

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics
Powered by FogBugz