Live data from Hacker News

Anti-if: The Missing Patterns

code.joejag.com

1–10 of 74 posts

Re: Anti-if: The Missing Patterns

#2
> Context: You have a method that takes a boolean which alters its behaviour

> Problem: Any time you see this you actually have two methods bundled into one. That boolean represents an opportunity to name a concept in your code.

This is only true if you're using literal booleans at you call sites. If the booleans are coming from somewhere else, like user input, you just moved your single if statement in the method out to every call site.

> Context: You are calling some other code, but you aren’t sure if the happy path will suceceed.

> Problem: These sort of if statements multiply each time you deal with the same object or data structure. They have a hidden coupling where ‘null’ means someting. Other objects may return other magic values that mean no result.

Passing a default value works, but in Java 8, returning an Optional is cleaner. And if you wanted a default value, you can still do

    repository.getRecord(123).orElse("Not found");
Edit: Also, the coping strategy link [1] he gave to remove exceptions sounds a lot like restarts in Commons Lisp's condition system.

[1] https://silkandspinach.net/2014/11/06/on-paperboys-newsagent...

Re: Anti-if: The Missing Patterns

#3
post #2

> Context: You have a method that takes a boolean which alters its behaviour > Problem: Any time you see this you actually have two methods bundled into one. That boolean represents an opportunity to name a concept in your code. This is only true if you're using literal booleans at you call sites. If the booleans are coming from somewhere else, like user input, you just moved your single if statement in the method ou…

This is why I never try to give prescriptions on code style.....whenever I think I have something good, someone else comes along with something better. And when I see someone else's advice, I can think of something better. And after I finish writing my own code, I can always look at it and think, "Oh, I could have done that better."

See also: efficiency. There's always a way to make it more efficient.

Re: Anti-if: The Missing Patterns

#4
post #2

> Context: You have a method that takes a boolean which alters its behaviour > Problem: Any time you see this you actually have two methods bundled into one. That boolean represents an opportunity to name a concept in your code. This is only true if you're using literal booleans at you call sites. If the booleans are coming from somewhere else, like user input, you just moved your single if statement in the method ou…

I think if your boolean is coming from user input then refactoring your method to accept user input, and then wrapping your method with a helper function that does the user input call would still be good advice.

At some point applying "anti-if" does involve major refactoring, so the outer style of your code might need to change a bit.

Of course like all design patterns it's more of a thought experiment than a total prescription IMO. But taking the thought experiment to its logical conclusion can also yield interesting results.

Some people might throw out strawman arguments about design patterns, but I'll end up reading the strawman and be like " yeah that does sound like a good idea". It's pretty hard to overestimate the value of regularity in code.

Re: Anti-if: The Missing Patterns

#5
This reminds me of something I read on HN a while back and forgot to bookmark. (Naturally I've been unable to find it since.)

I think the article was written by a company who made a static code analysis tool. They described how there wasn't a large difference in quality between FOSS and proprietary code, except for one detail: FOSS code used "else" statements much less.

Anyone have any idea what I'm thinking of or if I'm even remembering it correctly?

Re: Anti-if: The Missing Patterns

#7
I'm afraid the article has left me unconvinced. I'm open to having my mind changed on the matter, though.

The point of passing boolean params instead of named functions is that most of the time there is shared code between the two paths and not literally all the code is enclosed in either the if or the else block. If the author was intending just to restrict to that one specific case where there was no overlap whatsoever, then I guess I would agree but I'm not sure how often that happens.

Polymorphism has some advantages but it's certainly got it's own troubles in terms of understand-ability. The author links to an article which even states "I think that we hate conditionals more than we should. Introducing polymorphism too soon will complicate your code, making it hard to understand and test." It then goes on to give an example where it says polymorphism is actually the right choice, to avoid two switches. I'd say that at least this trivial example would be best handled by some data-driven approach. Look up salaries in a database instead.

The inline statement one can certainly be better in some cases, but the example given is quite poor. What does "foo && bar || baz" mean? Well, now I have to remember the order of operations ... 'or' after 'and' I guess. Surely this is easier to misread than the if statement example, which in my mind closely matches how I think. At least it should be "(foo && bar) || baz". But even then, that only works when the actual return type is boolean and there are no state changes made.

I don't really see how using an Optional type would remove the if(null) checks. It just makes the meaning explicit, which is good but not remedying the original problem.

5 seems nice.

Re: Anti-if: The Missing Patterns

#9
> Patten 3: NullObject/Optional over null passing

The solution here disperses the responsibility of keeping sumOf safe to its callers, all over the place, instead of a single location in sumOf.

Re: Anti-if: The Missing Patterns

#10
Generally speaking, for every refactoring you could do, the opposite move is sometimes useful too. For example, inlining a function and extracting a helper function could both be a way to simplify code, depending on what you're trying to do.

Similarly here, I think it's good to know how to get rid of an if statement, but keep in mind that sometimes you might want to introduce an if statement. Sometimes you want polymorphism and sometimes it's better to do the same thing as pattern matching.

Post reply on HN