Hacker News new | comments | show | ask | jobs | submit login

I'm disappointed that of all the patterns presented, most of them actually increase the complexity to some extent, and none of them are the use of a lookup table/array. IMHO that is the "real anti-if pattern" here, and it can immensely simplify code. I've taken long, convoluted nested if/else chains with plenty of duplication and turned them into a single array lookup. A bonus is that performance and size often benefit as well, since the code is far less branchy.


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

If you have several levels of nested if-else (as opposed to a linear chain of "if"-"else if"), then you probably need a more complicated table than a linear array.

The moving appart that gets hidden away is the table (or more often, Hack mandictionary) that is stored somewhere in memory. If you are lucky, it is stored statically. It is never defined in quite the same place as the decision that it implements.

Personally I don't like switch statements at all, especially the ones that require manual control flow management. I can vividly remember multiple bugs over the years caused by forgetting to add "break" to a switch statement.

Unless you're optimizing for performance (which is rare in my domain), control-flow statements are a smell and should be avoided. Each branch has some "implicit" state that is being fragmented and has to be manually managed by the programmer.

C# will optimise something like >7 items in a switch statement to a lookup. Funny how this doesn't play nice with code contracts!

"turned them into a single array lookup."

Midway between nested conditionals and lookups is using flags and a tablesque series of conditionals. Redundant but easily understood (and therefore testable).

I first learned about this technique from Code Complete (linked in the TFA). IIRC, McConnell used the term "truth tables".

"...since the code is far less branchy."

Code construction GoF style Design Patterns just introduce another level of indirection. That's it. (Insert cliche here.)

"Design Patterns" are overused, especially in the Java world (eg J2EE/Spring, Service Providers, Strategies, DI, IoC).

The "design" part is figuring out the least complicated balance between conditional branches and call stack depth, between composition and inheritance.

Rant over.

"Polymorphism" kind of counts, it replaces the switch-case with a vtable lookup.

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact