Page 1 of 1
Separate methods or "mixed" types?
Posted: Tue Nov 21, 2006 9:52 am
by Chris Corbyn
I'm sort of split on what people would see as the cleanest approach here.
Lets say you've got a method someMethod() which takes a string as a parameter. At some point down the road you realise you need the same functionality to operate over an array of strings. Do you:
a) make a new method to carry out the procedure on the array
b) allow the original method to accept both a string, or an array
In other langauges you'd be able to overload the method and have the best of both worlds. In PHP you either end up creating new methods with the original method invoking them, or you create a condition inside the method and keep all the logic together.
With just two input types it's not really that bad but if you then create an object which you also want to operate on you'd have three different types allowed to go in.
Do you go down the route:
void setX( mixed input )
or do you go down the route:
void setStringX( string input )
void setArrayX( array input )
void setObjectX( object input )
?
EDIT | For those thinking wtf the real case scenario right now is:
Code: Select all
$mail->setHeader("To", array("Joe Bloggs <joe@bloggs.tld>", "Jeoff Banks <jeoff@banks.it>"));
//vs
$mail->setGroupHeader("To", array("Joe Bloggs <joe@bloggs.tld>", "Jeoff Banks <jeoff@banks.it>"));
//when it's always just been
$mail->setHeader("To", "Joe Bloggs <joe@bloggs.tld>");
Posted: Tue Nov 21, 2006 10:13 am
by Jenk
For that exact scenario, an if(is_array()) would satisfy me, but for the other examples, this is why I have been wishing for the more traditional overloading, for some time now

Posted: Tue Nov 21, 2006 10:15 am
by GeertDD
I'd go for the mixed input setup.
The set() function of my template class looks like this for example:
Code: Select all
// set a template variable
// @param $name string - name of the template variable
// or array - array with vars: e.g. http://withcake.com/posts/view/batch_set_calls
// @param $value mixed - value of the template variable, neglected if $name is an array
public function set($name, $value = '') {
if (is_array($name)) {
foreach ($name as $k => $v)
$this->set($k, $v);
return; // stop function
}
$this->vars[$name] = $value;
}
Also native php functions go this route. Take str_replace() for example. It accepts strings and arrays as well.
In your situation I don't think there is much room for confusion neither when inserting an array with email addresses to the setHeader() function. In general I don't see real advantages to go for the second setup.
Posted: Tue Nov 21, 2006 10:23 am
by Chris Corbyn
Yeah I think my main reason for considerng using separate methods was to save confusion but arrays are fairly commonly used as lists I guess.
~Jenk, sadly I don't think it's even possible to add overloading support to PHP right now purely because you need to know a bit more about some native types in order for it to work. It is why i would like to see things like string and array work for type-checking but only if the developer actually puts that constraint in the code (just in the same way PHP5's type checks are optional for objects).
Posted: Tue Nov 21, 2006 11:46 am
by Maugrim_The_Reaper
I would have gone with making a plural method - setHeaders().
Me realises I'm currently a small ethnic group in this topic however...

.
Posted: Tue Nov 21, 2006 12:15 pm
by John Cartwright
I prefer mixed. Such a small distinction I don't see the need for another method.
Posted: Tue Nov 21, 2006 12:31 pm
by Christopher
I think it depends on circumstances and on whether you are trying to maintain backward compatablity. In your example it was BC because in hindsight you realized that $mail->setHeader() should really take an array of values -- but you are allowing a string to be considered an array with one element.
The question is whether going forward in a design if you consider mixed parameters a design requirements (e.g. a function that needs to handle both numbers or strings differently but correctly) or if you are providing a convenience worth the performance hit of the type check. Remember that if you are providing a method that will probably be used in a loop then you are adding a if() to each iteration (rather than just requiring up front array('one item') ).
Posted: Tue Nov 21, 2006 12:36 pm
by John Cartwright
The question is whether going forward in a design if you consider mixed parameters a design requirement
What about doing to force a certain type? (although I guess this still depends on the circumstances) Thoughts?
Posted: Tue Nov 21, 2006 1:45 pm
by Chris Corbyn
Jcart wrote:The question is whether going forward in a design if you consider mixed parameters a design requirement
What about doing to force a certain type? (although I guess this still depends on the circumstances) Thoughts?
Well, for the example of string vs array you can always force it to be an array so even if a string is passed you get an array with one element:
Code: Select all
public function foo($input)
{
$input = (array) $input;
foreach ($input as $value) { ... }
}
I was thinking more about the lack of constraint on the type being used as possibly being seen as sloppy coding.
It wasn't a hindsight thought on an existing design as such, but just something I was lead into in a TDD session. Sat writing the test I was in two minds as to whether to just use the exisiting API with a new type, or invoke a new method.
I'm going the mixed-type route anyway thanks

Posted: Tue Nov 21, 2006 4:08 pm
by Christopher
d11wtq wrote:I was thinking more about the lack of constraint on the type being used as possibly being seen as sloppy coding.
This quote gets to the heart of the ideas about scripting language vs traditional languages. To the new generation it is a "lack of constraint" where no constraint is needed, whereas traditionalists would consider it "sloppy coding."
Posted: Tue Nov 21, 2006 4:38 pm
by feyd
In this specific case, I would likely rename it so it makes more sense for arrays, a la Maugrim's post, but use
is_array()/
is_string(), a la Jenk's post, to quickly test the type and convert as necessary to array then while the whole thing to operate on arrays.
Posted: Tue Nov 21, 2006 4:54 pm
by wei
i think any of the methods mentioned so far is fine as long as they are used consistently throughout the application/library/framework. It is the inconsistencies that can make it difficult to understand and use the API (php itself is quite famous for inconsistency).