Live data from Hacker News

Get rid of those boolean function parameters (2015)

mortoray.com

71–80 of 119 posts

Re: Get rid of those boolean function parameters (2015)

#71
post #41

Earlier quoted context omitted.

Religiously splitting functions with boolean arguments doesn't always result in more maintainable code. Instead of trigonometry functions, how would you refactor JS's fetch() with many of its behaviour-altering flags?

> how would you refactor JS's fetch() as @flavius29663 said ( https://news.ycombinator.com/item?id=28593669 ) you can use the builder pattern FetchBuilder() .withUrl(ur) .withMode("cors") .withCache(true) .withHeader('Content-Type', 'application/json') .accept('*/*') .post() .then(response => response.json()) .then(data => console.log(data));

I'm not following how moving the options out of the function parameters and into the call chain makes the actual function more maintainable. It's still doing the exact same thing with the exact same options it's just pulling them from elsewhere. If anything you now have more functions to maintain on top of the function that does many different things based on the calling info.

    // The original "misses the point"
    trig(mode="cos", type="hyperbolic")
    
    // The style fetch() uses today
    trig({mode: "cos", type: "hyperbolic"})
    
    // The builder refactor
    trigBuilder().withMode("Cos").withType("hyperbolic").calculate()

Re: Get rid of those boolean function parameters (2015)

#72

Earlier quoted context omitted.

> how would you refactor JS's fetch() as @flavius29663 said ( https://news.ycombinator.com/item?id=28593669 ) you can use the builder pattern FetchBuilder() .withUrl(ur) .withMode("cors") .withCache(true) .withHeader('Content-Type', 'application/json') .accept('*/*') .post() .then(response => response.json()) .then(data => console.log(data));

I see the builder pattern as a way to manage lack of keyword arguments. I see very little difference between your example and the actual fetch API that takes an object as JS's version of keyword arguments. Languages with good support for named/keyword arguments have more features such as required arguments and preventing duplicate arguments. With builder patterns your only real option is to make the builder construct…

> . I see very little difference between your example and the actual fetch API that takes an object as JS's version

true

the only difference is in the tooling

code completion for methods names works much better than autocompletion for objects' fields.

And you can't mistype a method name, it would not run and give you back a - hopefully - meaningful error, while the same is not true for objects' fields.

Re: Get rid of those boolean function parameters (2015)

#73

Earlier quoted context omitted.

I see the builder pattern as a way to manage lack of keyword arguments. I see very little difference between your example and the actual fetch API that takes an object as JS's version of keyword arguments. Languages with good support for named/keyword arguments have more features such as required arguments and preventing duplicate arguments. With builder patterns your only real option is to make the builder construct…

> . I see very little difference between your example and the actual fetch API that takes an object as JS's version true the only difference is in the tooling code completion for methods names works much better than autocompletion for objects' fields. And you can't mistype a method name, it would not run and give you back a - hopefully - meaningful error, while the same is not true for objects' fields.

> code completion for methods names works much better than autocompletion for objects' fields.

That is true for vanilla JS, unknown parameters will be ignored and unset will be set to undefined. However for languages that support keyword arguments (or even TypeScript[1]) the tooling should be even better than for the keyword argument case.

[1] https://www.typescriptlang.org/play?#code/GYVwdgxgLglg9mABMO...

Re: Get rid of those boolean function parameters (2015)

#74

Earlier quoted context omitted.

function pizza(boolean pepperoni, boolean bacon, boolean mushroom, boolean artichoke) now becomes 16 distinct functions.

not necessarly. First of all, this function pizza(boolean pepperoni, boolean bacon, boolean mushroom, boolean artichoke) breaks down when you want to add ham, potatoes and sausages to the pizza. Secondly, you can optimize for the common case: fn pizza() # -> default pizza e.g. margherita fn pizza(list_of_ingredients) # -> your custom pizza if you we are talking of simple functions and not more complex patterns, such…

What kind of monster puts potatoes on a pizza?

Re: Get rid of those boolean function parameters (2015)

#75
post #47

Earlier quoted context omitted.

In JS we can use JSON/object literal syntax and object destructuring to serve a similar purpose: myFunc({ aBoolFlag : true, anotherBoolFlag : false, aString : "Hello World" }); const myFunc = ({ aBoolFlag, anotherBoolFlag, aString }) => { /* do something with them... */ };

I started doing this because of React but at this point ({}) is my default way of starting a function. The only thing I dislike is that it's not super ergonomic for explicit typescript declarations (but great when using typescript to check .js files).

I don't find it too bad to do

  interface IFunctionParameters {
    userId: string;
    name: string;
    age: number;
  }

  const example = ({userId, name, age}: IFunctionParameters) => {...}

Re: Get rid of those boolean function parameters (2015)

#76

Earlier quoted context omitted.

function pizza(boolean pepperoni, boolean bacon, boolean mushroom, boolean artichoke) now becomes 16 distinct functions.

pizza is very suitable for the builder pattern: CreatePizza() .WithBacon() .With(artichoke) .Build(); or any combination of the above: CreatePizza() .WithMussroom() .Build() Even better, you can add new ingredients without changing any of the existing signatures: CreatePizza() .WithProsciuto() .WithTomatoSauce() .Build()

What is the difference of this and doing an object paramater, similar to JS?

createPizza({bacon: true, artichoke: true});

This has the same benefit you describe of being able to add parameters without altering any old call sites

createPizza({prosiuto: true, tomatoSauce: true});

Re: Get rid of those boolean function parameters (2015)

#77
post #76

Earlier quoted context omitted.

pizza is very suitable for the builder pattern: CreatePizza() .WithBacon() .With(artichoke) .Build(); or any combination of the above: CreatePizza() .WithMussroom() .Build() Even better, you can add new ingredients without changing any of the existing signatures: CreatePizza() .WithProsciuto() .WithTomatoSauce() .Build()

What is the difference of this and doing an object paramater, similar to JS? createPizza({bacon: true, artichoke: true}); This has the same benefit you describe of being able to add parameters without altering any old call sites createPizza({prosiuto: true, tomatoSauce: true});

In my example the could matter, or not. I see this all the times. In your example, can you make the order matter? In my example, after each selection, you can limit or expand the further options.

Re: Get rid of those boolean function parameters (2015)

#78
This reminds me of a time I worked with Typescript, and the team kept reopening discussions around the use of the "Any" type.

Trying to mitigate the boolean param dilemma, I would lean on Erlang and its multiple function signatures. It tends to force your solutions into initially harder but eventually more graceful form.

Generally, when my code starts showing these kinds of warts (silly parameters getting tagged on to function signatures), I take it as a sign that the initial tack I've taken no longer addresses the problem I'm trying to solve. More often then not it goes all the way back to an incomplete / outdated understanding of the business logic.

Re: Get rid of those boolean function parameters (2015)

#79
post #32

If someone submitted a PR where all of their boolean parameters were actually enums I would reject it, open a PR of my own from the same branch, and reject that one too. These clever micro-optimizations are a pathology of bored, well-meaning developers.

Could you please elaborate? To me, it looks like the article posits using boolean flags instead of enums is a code legibility issue, not a performance matter. There may still be good reason to reject a large PR such as the one you described. But, I don't get where the micro-optimization appears.

It's a readability optimization, not a performance optimization.

Re: Get rid of those boolean function parameters (2015)

#80
post #66

Earlier quoted context omitted.

Fully agree. No need to change the source code to fix what isn't broken.

Code is for humans, not for computers. Choose: AddElement(object, true, false); AddElement(object, true, true); AddElement(object, false, false); AddElement(object, false, true); or AddElement(object, visible::on, deletable::off); AddElement(object, visible::on, deletable::on); AddElement(object, visible::off, deletable::off); AddElement(object, visible::off, deletable::on); The latter is more readable, you can spot…

With a good IDE, the first one can be configured to look like the 2nd one.

But the 2nd one will always be more verbose, no matter if you need it or not.

So I'd choose the first one.

Post reply on HN