Posts Tagged ‘Named Parameter Idiom’

A common problem of (not only) C++ is that it only supports positional parameters: a caller of a function has to list its parameters according to the order declared in the method’s signature. Suppose you are refactoring an old code that supports the manufactoring of a big car company. You have to create cars by using a constructor that receives a bunch of parameters (assume you have neither setters nor other ways to fully construct a car):


Car* car = new Car (model, hp, year, doors_number, ... );

I find this code terribly bad. What about readability? (what does the first paramater mean? And the second? …) Modifiability? (what if I’d like to add other information?). Etc.

Why not writing something like:


Car myCar = CarMaker (year)

   .model (myCarModel)

   .hp (myCarHP)

   .doors_number (myCarDoorsNumber)

   . ...

The idea is to change the function’s parameters to methods of a newly created class, where all these methods return *this by reference. Notice how the “parameters” are in random order and they all have names. You can implement some variants of this approach but the concept is always the same: to avoid positional parameters.

Ok, let’s go through implementation details.

First, we create a class (CarMaker) that houses all the parameter values as private data members. The required parameters (the year, in our example – assume you can’t set a default year) is implemented as normal (positional parameter) on CarMaker’s constructor, but that constructor does not actually create the car. Then, all the optional parameters become methods. They return a reference to their “this object”, so the method calls can be chained.

class CarMaker {

public:

     CarMaker (uint year);

     CarMaker& model (string const&); // changes the model
     CarMaker& hp (uint); // changes the hp
     CarMaker& doors_number (uint); // changes the number of doors

     // ...

private:

      friend class Car;

      uint year;
      string model;
      uint hp;
      uint doors_number;

      // ...
};

inline CarMaker::CarMaker(uint _year) // some "standard" values
      : year (_year)
      , model ("unspecified")
      , hp (1000) // we sell sport cars!
      , doors_number (5)
{ }

inline CarMaker& CarMaker::model (string const& _model)
{
     model = _model;
     return *this;
}

inline CarMaker& CarMaker::hp (uint _hp)
{
     hp = _hp;
     return *this;
}

inline CarMaker& CarMaker::doors_number (uint _doors_number)
{
     doors_number = _doors_number;
     return *this;
}
// ...

CarMaker declares Car as its friend, that way it does not need a bunch of public get methods.

At this point you have (at least) two possibilities: you can modify the (old) Car class or you can’t. In the first case you make out with defining a constructor for class Car that takes a CarMaker object:


class Car {

public:

     Car (CarMaker const&);

     // ...
};

In this way you can just call the old constructor getting the parameters from the CarMaker object (remember they are good friends!).

But if you are unable to change the old class then you can cook up some workarounds. For example,┬áby adding a “create” method to CarMaker. It will return a brand new car calling the old constructor (passing it all the required parameters). The Car class no longer needs to be a friend of CarMaker. No matter when you call this method (in case you’ll get a car with “default” values):

Car myCar = CarMaker (year)

   .model (myCarModel)

   .hp (myCarHP)

   .create();

// Ready to hurtle!

Remember this idiom if you get annoyed at positional parameters!

Advertisements