67

Sometimes (rarely), it seems that creating a function that takes a decent amount of parameters is the best route. However, when I do, I feel like I'm often choosing the ordering of the parameters at random. I usually go by "order of importance", with the most important parameter first.

Is there a better way to do this? Is there a "best practice" way of ordering parameters that enhances clarity?

8
  • 5
    Named parameters make this less than an issue. Python takes it to the extreme, look into it. A good example is in C# - the many ways to call MessageBox.Show. Look into that as well.
    – Job
    Commented Aug 16, 2011 at 1:54
  • 9
    In Haskell, the possible usefulness of partial function application usually suggest a natural argument ordering.
    – tdammers
    Commented Aug 16, 2011 at 6:00
  • What would you consider a decent amount of parameters?
    – Chris
    Commented Aug 17, 2011 at 2:01
  • 2
    What programming language are you using. In theory, this shouldn't matter, but, in real world, it does
    – umlcat
    Commented Mar 8, 2012 at 23:01
  • 4
    @tdammers this is also true of any language which has direct support for currying
    – jk.
    Commented Mar 9, 2012 at 10:47

15 Answers 15

61

In general: use it.

Write a test for your function, a real world test.
Something you would actually like to do with that function.

And see in what order you did put those down.

Unless you already have (or know of) some functions that do something similar.
In that case: conform to what they do already, at least for the first arguments.

e.g. Do they all take a document/object/file-pointer/series-of-values/coordinates as the first argument(s)? For god's sake conform to those arguments.

Avoid confusing your coworkers and your future self.

1
  • 17
    "Avoid confusing ... your future self" sounds like a good philosophy in general. Commented Aug 16, 2011 at 3:45
39

I usually go with these rules, though not always with the same precedence. I guess it's an automatic thought-process now, and I don't over-think it, except for public API design.

Selection Funnel

  1. Semantics
  2. Importance / Relevance
  3. Frequency of Use
  4. I/O Concerns

1. Semantics First

Especially in OOP, pick parameters based on their semantical significance for the action or message. The signature of a well-named method with a well-named parameter should:

  • feel natural to call,
  • be self-descriptive in terms of intent and behavior.

(For these reasons, sometimes using custom types or aliases instead of primitives might increase the expressiveness of your signature.)

2. Then Importance

The most "significant" parameter comes first (or next...)

3. Then Frequency

The frequency matters as well, especially in a language where you don't have named parameters but can have default values on positional parameters. That implies that the order of the parameters doesn't vary, and that obviously you cannot set the N + 1 parameters if you want to force the default value of the Nth parameter (except if your language has a concept of a place-holder parameter).

The good news for you is that usually, frequency relates to importance, so that goes hand in hand with the previous point. And then it's probably up to you to craft your API for it to have the appropriate semantics.

4. Let's Not Forget I/O

if your method/function takes some input and produces an output, and the latter is not to be "returned" (via a return statement) or "thrown" (using an exception system), then you're left with the option to pass values back to the caller using your other parameters (or the input parameter). That relates to semantics, and in most cases it will make sense to have the first parameters define the output, and the last parameters receive the output.

Additionally, an other approach to have less parameters and maximise semantics would be to use a functional approach, or to define a Builder pattern, so you can clearly stack up your inputs, define your outputs, and retrieve them when need be.

(Notice I don't mention global variables, because why would you use one, right?)


Some Things to consider

  • Usability

    Most of the above will show naturally if you follow ZJR's advice: Use It!

  • Consider Refactoring

    If you worry about parameter ordering, maybe this worry finds its root in the above and in the fact that your API is badly designed. If you have too many parameters, something can most probably be componentized/modularized and refactored.

  • Consider Performance

    Keep in mind that some languages' implementations will incur very important impacts on your runtime memory management when using parameters. Hence the reason why many languages' style-books recommend to keep the parameter list simple and short. At 4 parameters max, for instance. I leave it as an exercise for you to figure out why.

  • Bevan's answer and mention of Clean Code's recommendations are definitely relevant as well!

1
  • 3
    have the first parameters define the output, and the last parameters receive the output - Did you mean "have the first parameters define the input"?
    – BornToCode
    Commented May 23, 2021 at 14:50
24

I'd respectfully submit that worrying about parameter ordering is worrying about the wrong thing.

In Uncle Bob's book "Clean Code" he advocates, persuasively, that methods should never have more than two arguments - and most should have only one, if any. When this is the case, ordering is either obvious or unimportant.

However imperfectly, I'm trying to follow Uncle Bob's advice - and it's improving my code.

In the rare cases where a method seems to require more information, introducing a parameter object is a good idea. Usually, I find this is the first step towards discovery of a new concept (object) that's key to my algorithm.

8
  • I definitely agree with you! My first statement was aimed to get at the point that this isn't a typical thing for me, haha. But in the case that I find I really do need to pass some parameters and it's not worth it to refactor the whole program, I wonder about ordering. Commented Aug 16, 2011 at 4:06
  • 4
    cough PHP cough. I'm sorry - you were saying something about not worrying about the order of parameters?
    – Craige
    Commented Aug 16, 2011 at 15:26
  • Won't you then just have a constructor for your parameter object that takes just as many arguments?
    – detly
    Commented Mar 9, 2012 at 2:02
  • No - because the parameter object can be "built up" over several statements in a way that's more readable.
    – Bevan
    Commented Mar 9, 2012 at 3:17
  • 4
    @Bevan: this is highly debatable. Building up objects this way means they can't be immutable anymore; keeping your objects immutable whenever possible however is another great way of increasing maintainability.
    – tdammers
    Commented Mar 9, 2012 at 16:49
12

I try to put the IN parameters first, OUT parameters second. There are also some natural ordering, e.g. createPoint(double x, double y) is strongly preferrable to createPoint(double y, double x).

4
  • 5
    Sometimes the opposite is better, e.g., when there's always just one OUT argument and a variable number of in arguments, like in addAllTo(target, something1, something2).
    – maaartinus
    Commented Aug 16, 2011 at 4:02
  • Though I follow the same rule, I try to avoid OUT parameters whenever possible, and most good programmers, too. So the number of functions where this recommendation actually helps the OP should be rather small.
    – Doc Brown
    Commented Feb 9, 2015 at 19:02
  • 9
    @DocBrown You really shouldn't try to avoid good programmers, they can be useful to have around. Commented Feb 17, 2015 at 14:28
  • @RyanfaeScotland: damn, I should read my comments twice before posting them (or it least within the five minutes I can change them) ;-)
    – Doc Brown
    Commented Feb 17, 2015 at 15:17
6

I've never seen a documented "best practice" regarding this particular topic, but my personal standard is to list them either in the order in which they will appear in the method they're being used for or if the method is more of a pass-through to a data layer I will list them in the order they would appear in the db schema or data layer methods.

Also, when there are multiple overloads of a method, I notice that the typical manner is to list them starting with parameters that are common to all (or most) of the methods with each different method being appended to the end for each method overload like:

void func1(string param) { }
void func2(string param, int param2) { }
void func3(string param, string param3) { }
void func3(string param, int param2, string param3) { }
6

Order: input(s), output(s), optional parameters.

1
  • What is the difference between "input(s)" and "output(s)"?
    – carloswm85
    Commented Mar 18 at 12:09
3

I often follow the C/C++ convention of placing the const parameters first (that is, the parameters you pass in by value), and then those that you pass in by reference. This may not necessarily be the correct method of calling functions but, if you are interested in how each compiler handles parameters, have a look at the following links for the rules governing and/or the order that parameters are pushed onto the stack.

http://msdn.microsoft.com/en-us/library/zthk2dkh%28v=vs.80%29.aspx

http://en.wikipedia.org/wiki/Calling_convention

1
2

Sometimes (rarely), it seems that creating a function that takes a decent amount of parameters is the best route.

Using several parameters is often a clear indicator, that you violate the SRP in this method. A method, which needs many parameters is unlikely to do only one thing. Excpetion may be a mathematical function or a configuration method, where indeed several parameters as such are needed. I would avoid multiple parameters as the devil avoids the holy water. The more parameters you use within a method, the higher the chance, that the method is (too) complex; the more complexity means: harder to maintain and that is less desirable.

However, when I do, I feel like I'm often choosing the ordering of the parameters at random. I usually go by "order of importance", with the most important parameter first.

In priniple you are choosing at random. Of course you might think paramter A is more relevant than parameter B; but that might not be the case for users of your API, who think B is the most relevant parameter. So even if you were attentive in choosing the ordering - for others it could seem random.

Is there a better way to do this? Is there a "best practice" way of ordering parameters that enhances clarity?

There are several ways out:

a) The trivial case: Do not use more than one parameter.

b) As you did not specify, what language you've chosen, there is the chance, that you chose a language with named parameters. This is nice syntactic sugar which allows you to loosen the significance of the ordering of paramters: fn(name:"John Doe", age:36)

Not every language allows such niceties. So what then?

c) You could use a Dictionary/Hashmap/Associative Array as parameter: e.g. Javascript would allow the following: fn({"name":"John Doe", age:36}) which is not far away from (b).

d) Of course if you work with a statically typed language like Java. you could use a Hashmap, but you would loose typeinformation (e.g. when working with HashMap<String, Object>) when parameters have different types (and need to cast).

The next logical step would be to pass an Object (if you are using Java) with appropriate properties or something more lightweight like a struct (if you write e.g. C# or C/C++).

Rule of thumb:

1) Best case - your method needs no parameter at all

2) Good case - your method needs one parameter

3) Tolerable case - your method needs two parameters

4) All other cases should be refactored

1

I usually just go with the "what looks less cyprtic" parameter ordering. The fewer times that I need to go to the method/function definition the better. And it's nice to have named parameters that are descriptive as to what they are used for, that way when the little tooltip pops up (VS) then it makes it even easier.

If you have lines and lines of parameters you may want to consider a different design. Step back and see how you can break that up into more functions/methods. Just an idea, but when I have a dozen parameters in my function it's almost always not a parameter issue, but a design issue.

4
  • 2
    "cyprtic": a great way to make the point.
    – Bevan
    Commented Aug 16, 2011 at 3:40
  • 2
    You've never had a typo before, @Bevan?
    – user29981
    Commented Aug 16, 2011 at 4:06
  • 1
    I have typos all the time - writing cyprtic was so good I thought it was on purpose. Please do change it back, it helps to make your point, even if it was an accident.
    – Bevan
    Commented Aug 16, 2011 at 4:14
  • 1
    @Bevan, haha okay I see what you're saying. Good point! Its changed back =)
    – user29981
    Commented Aug 16, 2011 at 10:38
0

Oftentimes a complex object as a parameter is better -- a poor man's version of named parameters that works on most platforms. And opens the door to parameters with behavior to boot.

For an example of most things you shouldn't do you might want to try reading PHP's standard library documentation.

0

I usually order them with required first, than by some combined measure of importancy and frequency of use according to a "feeling" (can be seen as ORDER BY required DESC, SOME_MAGIC_FEELING(importancy,frequency)) and not according to any specific practice.

However, as others have noted, I think the underlying problem that makes this an issue is using too many parameters (IMHO, anything >3 is too many) and that's the real problem that you should be addressing. There's an interesting post about that at rebecca murphey's blog.

I think that when you only have 1-3 arguments, the correct ordering is quite obvious and you just "feel" what's right.

0

Similar to @Wyatt Barnetts' answer, anything more than a few parameters or very explicit parameters for the method, I'd recommend passing an object instead. This is typically easier to update/maintain, clearer to read, and removes the necessity for worrying about ordering. Also, too many parameters for a method is a code smell and there are common refactoring patterns you can follow to help correct it.

Explicit example:

public int add(int left, int right)
{
  return left + right;
}

Since this is a pretty clearly defined example and addition is commutative (order doesn't matter) then just go with it.

However, if you add something more complex:

public SomeComplexReturnValue Calculate(int i, float f, string s, object o)
{
  // do work here
}

Would become:

public class SomeComplexInputForCalculation
{
  public int i; 
  public float f;
  public string s; 
  public object o;
}

public SomeComplexReturnValue Calculate(SomeComplexInputForCalculation input)
{
  // do work here
}

Hope this helps...

0

Order it in whatever way you think currying will most likely benefit from. For example, function parameters first.

0

"Important first" does not mean a whole lot. There are some conventions.

If you pass the calling object (often named sender), that goes first.

There should be some fluency to the list, meaning you should know what an argument is about by the time you read it. Example:

CopyFolder(string path, bool recursive);

If you were to put recursive first, it would be confusing because there is no context yet. If you already now it is about copying (1), a folder (2), then the argument recursive starts to make sense.

This also makes IntelliSense-like features work well: the user learns as he fills in the arguments, he builds up an understanding of the method and what it does. Likewise, overloads should maintain the same order for the parts that are equal.

Then you may still find there are arguments that are "equal" in this respect and you may be tempted to let the order depend on the type of the argument. Just because having a couple of strings in a row and then a couple of booleans looks nicer. At some level this will become an art rather than a skill.

I do not care much for the statement that you should wrap all arguments into an object just to end up with a single argument. That is just fooling yourself (it does not make the method any less complex, it still has all these arguments, you just hid them). This may still be convenient to do if you pass on the set from method to method a couple of times, refactoring will sure become a lot easier, but design-wise it is just pretending you are making a difference. It is not like you will end up with a meaningful object that represents something, it will just be a bunch of arguments, no different from the list in the method declaration. It won't make uncle Bob happy.

-2

It depends on a lot of things previous answers have already cleared out pretty well. However here are my two cents:

I order parameters so that arguments for which I expect to see repeated values are first.

This adds alignment to the code and thus improves readability. See this example:

int print_error(char const *msg, char const *progName) {
    return fprintf(stderr, "%s: %s\n", progName, msg);
}

int main(int argc, char *argv[])
{
    print_error("Failed to open file", argv[0]);
    print_error("Expected valued for argument", argv[0]);
    print_error("Expected semicolon after statement", argv[0]);
}

Reordering the parameters to print_error creates an alignment that makes the code read better. It's also easier to see that the same value is passed everywhere.

int print_error(char const *progName, char const *msg) {
    return fprintf(stderr, "%s: %s\n", progName, msg);
}

int main(int argc, char *argv[])
{
    print_error(argv[0], "Failed to open file");
    print_error(argv[0], "Expected value for argument");
    print_error(argv[0], "Expected semicolon after statement");
}

Not the answer you're looking for? Browse other questions tagged or ask your own question.