If your function has a McCabe complexity higher than 1024, then boolean arguments are the least of your problems...
Tons of well-written functions have many more potential code paths than that. And they're easy to reason about because the parameters don't interact much.
Just think of plotting libraries with a ton of optional parameters for showing/hiding axes, ticks, labels, gridlines, legend, etc.
engage_turbo_encabulator(True, False, True, False, True, False, True, False)
and: engage_turbo_encabulator(
enable_hydrocoptic=True,
allow_girdlespring=False,
activate_marzelvanes=True,
sync_trunnions=False,
stabilize_panametric=True,
lock_detractors=False,
invert_logarithms=True,
suppress_lunar_wane=False
)
The latter is how you should use such a function if you can't change it (and if your language allows it).If this was my function I would probably make the parameters atrributes of an TurboEncabulator class and add some setter methods that can be chained, e.g. Rust-style:
encabulator = (
TurboEncabulator.new()
.enable_hydrocoptic(True)
.allow_girdlespring(False)
.enable_marzelvane_activation(True)
.enable _trunnion_syncing(False)
.enable_param_stabilization(True)
.enable_detractor_locking(False)
.enable_logarithm_inversion(True)
.enable_lunar_wane_supression(False)
.build()
)I absolutely agree named arguments are the way to go. But my comment wasn't in the thread about that.