views:

123

answers:

7

In most other OO languages it would be sacrilege to have each function receive a single associative array of Objects rather than enumerating each in the method signature. Why is it acceptable and commonly used in most popular frameworks for both of these languages to do this?

Is there some justification beyond wishing to have concise method signatures?

I do see a benefit in this -- that the API could remain unchanged as new, optional parameters are added. But Javascript and PHP already allow for optional parameters in their method signatures. If anything, it seems like Java or another OO language would benefit from this more... and yet I rarely see this pattern there.

What gives?

+7  A: 

In my opinion, a lot of these functions are climbing in the number of arguments they accept, over 10 is not uncommon. Even if you do optional parameters, you still have to send them in order.

Consider a function like:

function myFunc(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13){
    //...
}

Say you want to use arguments 3 and 11 only. Here is your code:

myFunc(null, null, null, 'hello', null, null, null, null, null, null, null, 'world');

Wouldn't you rather just:

myFunc({
    a3 : 'hello', 
    a11 : 'world' 
});

?

Jage
+1  A: 

First of all such technique is very simple for the coders.

They do not need to remember order of all of the parameters of the all functions in your application. The code becomes more readable and more robust.

Any future development, improvements or refactoring will be no so hard to provide. The code becomes more maintainable.

But there is some pitfalls. For example, not every IDE will give you a simple code completing with such functions and their parameters.

Sergey Kuznetsov
+4  A: 

There are a couple of reasons for this.

The first is that not all argument lists have a natural order. If there is a use-case to only supply the 1st and 6th argument, now you have to fill in four default placeholders. Jage illustrates this well.

The second is that it's very hard to remember the order the arguments must occur in. If you take a series of numbers as your arguments, it's unlikely to know which number means what. Take imagecopyresampled($dest, $src, 0, 10, 0, 20, 100, 50, 30, 80) as an example. In this case, the configuration array acts like Python's named arguments.

erisco
A: 

In my opinion there 2 reasons why this has evolved:

  1. Array's are very easy to create and manipulate, even with mixed types.
  2. PHP/JS programmers have often a non academic background and are less indoctrinated from languanges like Java and C++.
elias
+2  A: 

Ruby follows this methodology as well, and has even devised a more succinct syntax meant specifically for using hashes as initializers, as of Ruby 1.9:

# old syntax
myFunc(:user => 'john', :password => 'password');

# new syntax
myFunc(user: 'john', password: 'password');

The problem being addressed is that, within these languages, you cannot overload functions based on argument type. This results in complex classes with a single constructor that can have a huge and unwieldy argument list. Using hash-like objects to supply parameters allows for a sort of pseudo-overloading by parameter name rather than by type.

My only real problem with this practice is it becomes difficult to document your arguments: http://stackoverflow.com/questions/2009122/phpdoc-for-variable-length-arrays-of-arguments

meagar
+2  A: 

One of the most important reason why you don't see this in other OO languages is that you are probably referring to compiled languages like C++ or Java.

The compiler is responsible to determine, at compilation time not during execution, which method you want to call and this is normally done based on the signature, so basically it has to be done this way. This is also how method overload is done in these languages.

SBUJOLD
+2  A: 

The major reason is that those particular languages simply do not support having multiple calling conventions for the same function name. I.E. you can't do the following:

public function someFunc(SomeClass $some);
public function someFunc(AnotherClass $another);
public function someFunc(SomeClass $some, AnotherClass $another);

So you must find another way to create simpler ways to pass your variables around, in PHP we end up with someFunc(array('some'=>$some, 'another'=>$another)) because it is the only convenient way. In JavaScript we end up using objects, which isn't as bad: someFunc({some: something, another: anotherthing})

gnarf