views:

220

answers:

6

In a PHP web application I'm working on, I see functions defined in two possible ways.

Approach 1:

function myfunc($arg1, $arg2, $arg3)

Approach 2:

// where $array_params has the structure array('arg1'=>$val1, 'arg2'=>$val2, 'arg3'=>$val3)
function myfunc($array_params)

When should I use one approach over another? It seems that if system requirements keep changing, and therefore the number of arguments for myfunc keep changing, approach 1 may require a lot of maintenance.

+5  A: 

Using a params array (a surrogate for what is called "named arguments" in other languages") is great - I like to use it myself - but it has a pretty big downside: Arguments are not documentable using standard phpDoc notation that way, and consequently, your IDE won't be able to give you hints when you type in the name of a function or method.

Pekka
This would be my greatest worry, what arguements are required. I come from a VS.NET Background and am just starting to get back into php. In VS, I rarely pass arrays as parameters, unless they are meant to be grouped, because If I don't get all the data, I can't continue. The worst is when you have long functions or complicated functions. Now other programmers have to look through the code to ensure that everything is passed. With good documentation, this shouldn't be an issue, but if you are documenting, it's almost the same as updating parameters.
JohnathanKong
+11  A: 

If the system is changing so often that using an indexed array is the best solution, I'd say this is the least of your worries. :-)

In general functions/methods shouldn't take too many arguments (5 plus or minus 2 being the maximum) and I'd say that you should stick to using named (and ideally type hinted) arguments. (An indexed array of arguments only really makes sense if there's a large quantity of optional data - a good example being configuration information.)

As @Pekka says, passing an array of arguments is also liable to be a pain to document and therefore for other people/yourself in 'n' months to maintain.

Update-ette...

Incidentally, the oft mentioned Code Complete examines such issues in quite a bit of detail - it's a great tome which I'd highly recommend.

middaparka
+1 Good points. Although using configuration arrays is not necessarily a sign of poor design: Sometimes, you will simply need only 1 or 2 arguments set, and which ones those are, can change. And nobody likes a (exaggerated) `function(null,null,null,null,null,"hello");`
Pekka
@Pekka - Totally agree, but from a maintenance (and indeed remembering the args) perspective I always try and go down the named args route first.
middaparka
Yup, same here. The proper solution would be introducing real (freely ordered) named arguments in the programming language, but the PHP team has rejected that repeatedly as far as I know.
Pekka
A: 

There are pros and cons to each way.

  • If it's a simple function that is unlikely to change, and only has a few arguments, then I would state them explicitly.

  • If the function has a large number of arguments, or is likely to change a lot in the future, then I would pass an array of arguments with keys, and use that. This also becomes helpful if you have function where you only need to pass some of the arguments often.

An example of when I would choose an array over arguments, for an example, would be if I had a function that created a form field. possible arguments I may want:

  • Type
  • Value
  • class
  • ID
  • style
  • options
  • is_required

and I may only need to pass a few of these. for example, if a field is type = text, I don't need options. I may not always need a class or a default value. This way It is easier to pass in several combinations of arguments, without having a function signature with a ton arguments and passing null all the time. Also, when HTML 5 becomes standard many many years from now, I may want to add additional possible arguments, such as turning auto-complete on or off.

GSto
+2  A: 

with the first approach you are forcing the users of your function to provide all the parameters needed. the second way you cannot be sure that you got all you need. I would prefer the first approach.

flurin
This is the big upside to named arguments, and why I love them too, yes
Pekka
+1  A: 

If the parameters you're passing in can be grouped together logically you could think about using a parameter object (Refactoring, Martin Fowler, p295), that way if you need to add more parameters you can just add more fields to your parameter class and it won't break existing methods.

Bedwyr Humphreys
A: 

I find using an optional array of arguments to be useful when I want to override a set of defaults in the function. It might be useful when constructing an object that has a lot of different configuration options or is just a dumb container for information. This is something I picked up mostly from the Ruby world.

An example might be if I want to configure a container for a video in my web page:

function buildVideoPlayer($file, $options = array())
{
  $defaults = array(
    'showAds' => true,
    'allowFullScreen' = true,
    'showPlaybar' = true
  );

 $config = array_merge($defaults, $options);

 if ($config['showAds']) { .. }
}

$this->buildVideoPlayer($url, array('showAds' => false));

Notice that the initial value of $options is an empty array, so providing it at all is optional.

Also, with this method we know that $options will always be an array, and we know those keys have defaults so we don't constantly need to check is_array() or isset() when referencing the argument.

Bryan M.