Live data from Hacker News

Anti-if: The Missing Patterns

code.joejag.com

51–60 of 74 posts

Re: Anti-if: The Missing Patterns

#52
post #23

Earlier quoted context omitted.

I do this a lot too. Often long chains of if statements are really performing a manual mapping from one set of values to another. Just keep a map and perform a lookup! Easier to read, easier to change, and easier to extend since the mapping is a data structure instead of code.

Efficiency-wise I agree, but if I don't care about efficiency then I often prefer an if-chain (or better still, a switch-case). The point is that the desired mapping is known not just at compile time, but is explicitly known to the programmer. So it is clearer if it right there in the executable code rather than hidden away in some moving part (the mapping data structure).

switch-case is often compiled to a table lookup, but if your expressions are constant (at least for the part where the table is being used), the latter is definitely less verbose.

So it is clearer if it right there in the executable code rather than hidden away in some moving part (the mapping data structure).

Following several levels of nested if/else is "clearer" than going to the right array index? I don't know what you mean by "hidden away in some moving part".

Re: Anti-if: The Missing Patterns

#53

Earlier quoted context omitted.

> This makes the code clearer, IMO. Depends on how much state you need to pass between A, B1, B2 and C.

It also depends on the semantic value of A, B1, B2 and C. If you cannot express them as senseful steps of your overall algorithm, then you are bound to end up with very confusing method names like calculateFooAndCreateBarAndAlsoInitializeBaz, or (even worse) prepareForFoo. EDIT: By the way, an anecdote. Years ago, I was working with an offshore developer who was producing huge scripts without any modularization whats…

Could have been worse: He could have made 1000 functions two lines each.

Re: Anti-if: The Missing Patterns

#54
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…

> like user input, you just moved your single if statement in the method out to every call site.

I guess the author would argue that the boolean should be pushed up to UI code. Arguably that domain logic belongs in the UI. Possibly a utility method in the UI package.

That being said, with all patterns there are exceptions. Following something to absolute purity is going to result in unclear code - polymorphism purity can rapidly cause a spaghetti codebase. Even GoF patterns can easily result in messy code. All patterns are blueprints, not rules.

On the topic of boolean values, I'm becoming more and more convinced by the anti-bool pattern. Normally this involves using an enum (usually bit field) when you first declare a parameter.

    FileOptions options = FileOptions.None;
    options |= temporary.checked ? FileOptions.Temporary : FileOptions.None;
    options |= encrypted.checked ? FileOptions.Encrypted : FileOptions.None;
    FileUtils.createFile("name_temp.txt", "file contents", options);
createFile now includes an 'if' and is at odds with anti-if (which is a pattern that I agree with). This is exactly my point, irrespective of whether you use multiple methods (createFile, createTemporaryFile, createEncryptedTemporaryFile, etc.) or polymorphism (File, TemporaryFile, etc.); you're going to end up with unclear code. Increasing clarity is the whole purpose of patterns. Composition (which bitfields are a form of) is the clear winner here and so the anti-if pattern has to be eliminated.

Re: Anti-if: The Missing Patterns

#56
Pattern 5 is all about removing semantic value from null references, but has nothing to do with if statements... In fact, the if-else remains (albeit hidden because of an early return inside an if, which is even worse in my opinion).

Re: Anti-if: The Missing Patterns

#57

I had a professor in university who was frequently saying he developed a thousand application and he didn't use any if. I know it's extreme but is there any way to reduce (lets say 5 to 1) conditions? I think he was developing Fortran apps. Anecdote: This very same professor asked us to do a matrix operation (I don't remember what) without using if once. He said it would be faster than using ifs. Many of us couldn't.…

Programs with lots of deep branches are generally not well thought out and prone to bugs. In my view, every branch represents an "exception" to the main execution path. The explosion of combinations of taken/not taken branches is what brings your program to an unpredictable state. The performance side is debatable, but with fewer branches a program is definitely simpler and more elegant.

Re: Anti-if: The Missing Patterns

#60
post #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 whatso…

> 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.

Yeah, the benefit is not really the Option (which you still have to check), the benefit is when there's no Option. I'm not really sold on there being a benefit in Java (looks like those are the code samples in the article?), but in languages where `null` is not a part of the type, and your parameter is just a plain, `int`, say, then you know you don't need to check if it's `null`. In other languages, you either have to always check, or rely on a convention or code flow that has the null checks happening earlier.

Post reply on HN