Using C++ Classes to handle commonly used parameters

Viewed 113

My team works on an HTTP web server in C++. The codebase has aged over time, and has a widespread problem of 12+ parameters being passed to every function.

A fake example: We need to build a Car, but in order to do that, we have the following function:

MaybeBuildCar(engine_params, steering_params, interior_params, fuel_params, available_inventory, parts, &debug);

Someone on our team has proposed that we create a wrapper CarBuilder class whose constructor takes in the params and "stateful" objects like available_inventory, then has a separate function for BuildCar as follows:

CarBuilder car_builder(engine_params, steering_params, interior_params, fuel_params, available_inventory, &debug);

auto car = car_builder.BuildCar(parts);

Personally, I don't see much value in having a class with a single public function that is always called. We'll always need these parameters, and we'll always need the parts, so this just adds more steps to build the car. It could even add confusion, as now a user of CarBuilder must know to both construct it and call BuildCar.

Admittedly, this simplifies our helper functions within car_builder.cc, as they also require passing these params, but to me that's misusing what a class is for: maintaining state.

Is creating this CarBuilder a misuse of the class, or is simply cleaning up function signatures a valid use? Does anyone have any suggestions on how to tackle this problem?

2 Answers

Minimizing function parameters can be a blessing for heavily used functions in a performance-sensitive environment:

If you pass 6 references to a function, that is 6 pointer copies pushed to the stack;
If you pass a single CarBuilder, it is one "reference-that-contains-6-other-references".

It depends on your situation.

you could define a class that contains all parameters and in each function just passed this object.

struct CarComponent
{
 public:
    EngineParams engine_params;
    SteeringParams steering_params;
    InteriorParams interior_params;
    FuelParams fuel_params;
    AvailableInventory available_inventory
};

MaybeBuildCar(car_component);
other_function(car_component);

Advantage:

  • Function's signature is decoupled from changing members of the struct (CarComponent). easy to change.
  • Refactor all the parameters in each function with a specific object. it prevents repetition and it becomes easier to read the code.
Related