Remix.run Logo
OskarS 5 days ago

You're correct in principle, but I'm saying that "in practice", boolean arguments are usually feature flag that changes the behavior of the function in some way instead of being some pure value. And that can be really problematic, not least for testing where you now aren't testing a single function, you're testing a combinatorial explosions worth of functions with different feature flags.

Basically, if you have a function takes a boolean in your API, just have two functions instead with descriptive names.

hamburglar 5 days ago | parent [-]

> Basically, if you have a function takes a boolean in your API, just have two functions instead with descriptive names.

Yeah right like I’m going to expand this function that takes 10 booleans into 1024 functions. I’m sticking with it. /s

OrderlyTiamat 5 days ago | parent | next [-]

If your function has a McCabe complexity higher than 1024, then boolean arguments are the least of your problems...

crazygringo 5 days ago | parent [-]

Not really.

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.

atoav 5 days ago | parent [-]

Yes but this is about the difference between:

  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()
  )
crazygringo 4 days ago | parent [-]

Did you mean to reply to a different comment?

I absolutely agree named arguments are the way to go. But my comment wasn't in the thread about that.

crazygringo 4 days ago | parent [-]

(follow-up) BTW thank you for introducing me to turbo encabulators -- I did not know about them and they seem exceptionally useful! TIL...

https://en.wikipedia.org/wiki/Turbo_encabulator

Viliam1234 5 days ago | parent | prev [-]

Hopefully you could refactor it automatically into 1024 functions and then find out that 1009 of them are never called in the project, so you can remove them.

hamburglar 4 days ago | parent [-]

I think you might have missed the “/s”