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?
parts
parameter indicates a certain usage pattern: perhepsparts
changes more often than the others (e.g., maybe you can construct the car_builder once, but create several car objects with different parts - that's less code to write). Or you can create several preconfigured builders - maybe that's useful. You can also pass the builder object around to other components.parts
change more than the other params.auto just_add_parts = [=](auto parts_arg) { MaybeBuildCar(engine_params, steering_params, interior_params, fuel_params, available_inventory, parts_arg, &debug); };
. That lets you doauto car = just_add_parts(parts);
later, and you don't have to design a builder class mechanism. Which is best varies.