1

A lot of frameworks, most like jQuery plugins uses the "optional" parameter. Basically a dictionary (or key/value structure) with a bunch of additional parameters instead of send in the parameter's function.

As an example:

function (param1, param2, param3, param4, param4) {

  ...
}

Is replaced for:

function (opts) {
  opts.param1
  opts.param2, 
  opts.param3
  ...
}

IMO using opt is almost equal to use a lot of parameters in the constructor. I think is a little hard to maintain the configurations (sometimes) and understand what is inside of it.

Maybe it is for non typecheck of javascript, and the IDES normally doesn't help easily to know what is inside of opt.

But I don't know how to improve the creation of a configurable object.

Someone knows better solution or how to improve the design in this situations?

5
  • 1
    Funny, because not using opts is also considered a code smell.
    – Eric King
    Mar 31, 2015 at 22:26
  • I think both are smells.
    – vmariano
    Mar 31, 2015 at 23:28
  • 4
    There is no question here. Mar 31, 2015 at 23:50
  • Then make it a 'bag of useful related somethings'. If there are multiple groups of 'related somethings' use multiple parameters. Apr 1, 2015 at 6:00
  • @StevenBurnap I edited my question, to claryfy, I was trying to know if is a better way to write a better code/design for a configurable object.
    – vmariano
    Apr 1, 2015 at 23:20

3 Answers 3

5

I would say it depends of the language. In a strongly typed language like Java, pasing a Map<String, Object> means that you risk using the wrong type for a parameter.

That said, I have seen this been used in frameworks like ExtJS and, for some tasks that require lots of parameters (like initialization, configuration) it is worth it. It actually helps, because when building the objects you have the param name right next to the value, instead of having to count which parameter it is in the function argument list and count which parameter you are actually using.

Compare this code

function createWindow({
  top: 10,
  right: 10,
  width: 100,
  height: 200,
  title: 'My title',
  text: 'My text',
  buttons: [button1, button2],
  borderStyle: myBorderStyle
});

to

function createWindow(
  10,
  10,
  100,
  200,
  `My title`, /* I am sure it is the right order? or is text before title? */
  `My text`,
  null, /* I do not need this param, or the next other 3*/
  null,
  null,
  null,
  [button1, button2],
  null,
  null,
  null,
  myBorderStyle /* This is the 13th or the 12th parameter? */
);

Which one is easier to understand?

Additionally, you can use the builder pattern to set parameters in the dictionary, something like

var conf = {}
setTop(conf, 10);
setRight(conf, 10);
...

although IMO you are not improving the first version (and I don't actually see it being used much).

Now, for strongly typed languages, I would use a ConfigurationClass, where each parameter is defined as an attribute and its type is defined, but in JS there is little use for that since, if you write the attribute name wrong, the compiler won't tell you.

1
  • Ok, externally one friend explain me about this is a very common problem about object settings. Particularly he suggested , i should read the Gamma book, specially creational patterns. I like the builder solution, but the approach of @9000, anyway, bot answers are ok for me. (i can't vote up for now)
    – vmariano
    Apr 1, 2015 at 2:06
2

One way to fight the large amount of parameters is a builder pattern + fluid interface.

Consider:

widget = makeWidget(100, 200)
         .withSize(384, 256)
         .withColors(foreground, background)
         .withBorder('solid', 'black', 1)
         .withDialogButtons('OK', 'Cancel', 'Help')

This approach groups related sets of parameters so that each set is named and observable, allows to vary the order and omit the parts where default values oar OK.

1

JavaScript does not support parameter defaults for function declarations.

function foo(x) {
    console.log(x);
}
foo(); // outputs undefined

You would have to add extra code per parameter to set the default value.

function foo(x) {
  if(typeof x === 'undefined') {
    x = 0;
  }
  console.log(x);
}
foo(); // outputs 0

This becomes a pain when there are a number of parameters like function foo(param1,param2,param2).

You can quickly define default values using an object as the parameters.

function foo(opts) {
   opts = $.extend({x:0,y:0,z:0},opts);
   console.log(opts.x);
}
foo(); // outputs 0

That's basically why most people use key/value objects to hold parameters.

1

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