Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it a bad practice to define class options through an array?

When we take a look at Javascript frameworks like Dojo, Mootools, jQuery, JS Prototype, etc. we see that options are often defined through an array like this:

dosomething('mainsetting',{duration:3,allowothers:true,astring:'hello'});

Is it a bad practice to implement the same idea when writing a PHP class?

An example:

class Hello {

    private $message = '';
    private $person = '';


    public function __construct($options) {

        if(isset($options['message'])) $this->message = $message;
        if(isset($options['person'])) $this->person = $person;
    }


    public function talk() {

        echo $this->person . ' says: ' . $this->message;
    }
}

The regular approach:

class Hello {

    private $message = '';
    private $person = '';


    public function __construct() {}


    public function setmessage($message) {

        $this->message = $message;
    }


    public function setperson($person) {

        $this->person = $person;
    }


    public function talk() {

        echo $this->person . ' says: ' . $this->message;
    }
}

The advantage in the first example is that you can pass as much options as you want and the class will only extract those that it needs.

For example, this could be handy when extracting options from a JSON file:

$options = json_decode($options);
$hello = new Hello($options);

This is how I do this regulary:

$options = json_decode($options);
$hello = new Hello();

if(isset($options['message'])) $hello->setmessage($options['message']);
if(isset($options['person'])) $hello->setperson($options['person']);

Is there a name for this pattern and do you think this is a bad practice?

I have left validation etc. in the examples to keep it simple.

like image 353
DADU Avatar asked Dec 28 '10 22:12

DADU


3 Answers

There are good and bad aspects.

The good:

  • No need for multiple method signatures (i.e. overloading, where supported)
  • In keeping with the previous point: methods can be invoked with arguments in any order
  • Arguments can be dynamically generated, without needing to specify each one that will be present (example: you dynamically create an array of arguments based on user input and pass it to the function)
  • No need for "boilerplate" methods like setName, setThis, setThat, etc., although you might still want to include them
  • Default values can be defined in the function body, instead of the signature (jQuery uses this pattern a lot. They frequently $.extend the options passed to a method with an array of default values. In your case, you would use array_merge())

The bad:

  • Unless you properly advertise every option, your class might be harder to use because few will know what options are supported
  • It's one more step to create an array of arguments when you know ahead of time which you will need to pass
  • It's not always obvious to the user that default values exist, unless documentation is provided or they have access to the source code

In my opinion, it's a great technique. My favorite aspect is that you don't need to provide overloaded methods with different signatures, and that the signature isn't set in stone.

like image 180
Chris Laplante Avatar answered Nov 15 '22 08:11

Chris Laplante


There's nothing wrong with that approach, especially if you have a lot of parameters you need to pass to a constructor. This also allows you to set default values for them and array_merge() them inside a constructor (kinda like all jQuery plugins do)

protected $default_params = array(
    'option1' => 'default_value'
);
public function __construct($params = array()) {
    $this->params = array_merge($this->default_params, $params);
}

If you want live examples of this "pattern", check out symfony framework, they use it almost every where: here's an example of sfValidatorBase constructor

like image 36
German Rumm Avatar answered Nov 15 '22 08:11

German Rumm


When you give the arguments names it's called "Named Notation" v.s. "Positional Notation" where the arguments must be in a specific order.

In PHP you can pass an "options" parameter to give the same effect as other languages (like Python) where you can use a genuine Named Notation. It is not a bad practice, but is often done where there is a good reason to do it (i.e. in your example or a case where there are lots of arguments and they do not all need to set in any particular order).

like image 43
chaimp Avatar answered Nov 15 '22 09:11

chaimp