1

After writing some classes where class initialization requires multiple options, instead of writing several parameters into constructors or setters, I started passing an associative array of parameters, which I called $options, where, for example:

$options = {'productLine' = $productLine, 'modelNumber' => $modelNumber, ... };

My concern is that using such structure can lead to undesirable consequences.

Consider the following code, where by reading private variables, you pretty much know what this class needs to operate itself:

class Generator
{
    private $productLine;
    private $modelNumber;
    private $motorPresent; 
    //... 5 similar lines

    function __construct($options)
    {            
        $productLine = $options['productLine'];
        $modelNumber= $options['modelNumber'];
        $motorPresent= $options['motorPresent'];
        //... 5 similar lines
    }
}

Now, consider this code, where by reading private variables, you do not really know what is being passed to it, other than some "parameters".

class Generator
{
    private $options;

    function __construct($options)
    {
        $this->options = $options;
    }
}

It is not immediately clear what parameters are being passed from the source -- you have to know the actual $options array to know what is being passed. To know what's going on you have to read the code, and that takes time. Tests can be used to pass some sample parameters, but I wouldn't depend on tests as being the real answer.

My question is:

  • is there a way to keep assignments simple (like in my second code, code in constructor remains the same whether there are 10 parameters or 20), and yet still keep the class signature immediately apparent?

My current answer would be to either write code as in my first example, elaborating on which variable gets assigned what, but I feel that first way is needlessly verbose and I don't like it, because it introduces extra variable passing, when the variables are already in $options, just use $options['var_name'] instead.

Another way is to use comments, but that's not very good since comments are not always maintained as well as the code itself.

  • by the way, I intended to post this on SO, made it on PE by accident – Dennis Oct 9 '14 at 17:18
  • Could you create another structure called GeneratorOptions which contains clearly visible members: productLine, modelNumber,... ? – FrustratedWithFormsDesigner Oct 9 '14 at 17:36
  • I could and ... but then what... why not include it into this class? – Dennis Oct 9 '14 at 19:29
  • Well, you'd have to do it in such a way that the members of GeneratorOptions are visible/accessible. Then you write the constructor to take a GeneratorOptions object. So you refactor out the complicated set of parameters to a single parameter-containing object whose structure is known and well-defined. – FrustratedWithFormsDesigner Oct 9 '14 at 19:33
0

One possible answer is to check that all operating conditions have been set correctly as such:

function __construct($options)
{
    //check that everything is set properly
    if (!isset($options['productLine'])) 
        throw new \InvalidArgumentException("We need to know Product Line");
    if (!isset($options['modelNumber'])) 
        throw new \InvalidArgumentException("We need to know Model Number");
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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