tags:

views:

2078

answers:

18

I just came from Simple Design and Testing Conference. In one of the session we were talking about evil keywords in programming languages. Corey Haines, who proposed the subject, was convinced that if statement is absolute evil. His alternative was to create functions with predicates. Can you please explain to me why if is evil.

I understand that you can write very ugly code abusing if. But I don't believe that it's that bad.

+2  A: 

The only problem with a predicates (in terms of replacing if statements) is that you still need to test them:

function void Test(Predicate<int> pr, int num) 
{
    if (pr(num))
    { /* do something */ }
    else
    { /* do something else */ }
}

You could of course use the terniary operator (?:), but that's just an if statement in disguise...

Matthew Scharley
With lazy evaluation or if expressions have no side effects, you could also use predicates returning venerable Lambda booleans, where `true = (a,b) => a` and `false = (a,b) => b`, but that's also just an 'if' in disguise.
outis
+6  A: 

I'll agree with you; he was wrong. You can go too far with things like that, too clever for your own good.

Code created with predicates instead of ifs would be horrendous to maintain and test.

Rap
+12  A: 

I think it depends on what you're doing to be honest.

If you have a simple if..else statement, why use a predicate?

If you can, use a switch for larger if replacements, and then if the option to use a predicate for large operations (where it makes sense, otherwise your code will be a nightmare to maintain), use it.

This guy seems to have been a bit pedantic for my liking. Replacing all if's with Predicates is just crazy talk.

Kyle Rozendo
I'm not fan of switch statements. I prefer to use strategy pattern instead when I can.
Vadim
I'm with Kyle, it's just crazy talk. You can't program without conditionals in the way that you can program without GOTOs. Switches, predicates, dispatch tables, etc, are just syntactic sugar for IF.
High Performance Mark
Beyond that conditional jumps perform better than v-table lookups and method calls
Matthew Whited
@High-Performance Mark: I disagree, predicates are **not** syntactic sugar for IF. They allow decoupling of code which would otherwise be placed in a single if/switch block, possibly scattered all over the program.
Groo
@Matthew: static methods perform better than instance methods, but that is not something that you should consider when programming. @Kyle: I wouldn't say that using predicates would make your code a nightmare, quite the opposite actually, but their use is simply not always justified (due to extra work involved in refactoring when not necessary).
Groo
@Groo: why not know how a system really works. It can help find bottle necks before you run into them. I find knowing how the underworkings of the entire system works help me build cleaner and faster code.
Matthew Whited
+49  A: 

There is another sense in which if can be evil: when it comes instead of polymorphism.

E.g.

 if (animal.isFrog()) croak(animal)
 else if (animal.isDog()) bark(animal)
 else if (animal.isLion()) roar(animal)

instead of

 animal.emitSound()

But basically if is a perfectly acceptable tool for what it does. It can be abused and misused of course, but it is nowhere near the status of goto.

flybywire
I agree with this one. It's the same problem I have with switch statement. In this case we can a strategy pattern.
Vadim
I've had a professor who said exactly that - polymorphism should be used to hide type `if`s. He even warned not to use `is(obj is Foo), because this reflection implied a design flaw.
Kobi
+1 for replacing if with a more generic inheritance solution, but I think Corey has been talking about FP more than anything else.
Lee B
Eric mentions that in response to a comment from Aaron G in his as/cast article at http://blogs.msdn.com/ericlippert/archive/2009/10/08/what-s-the-difference-between-as-and-cast-operators.aspx
Brian
In dynamic languages, `if(obj is Foo)` is quite sensible, since you don't have typed parameters. Most of the time, you really want to duck-type instead, but sometimes with built-in types, nothing but the real thing will suffice, and in such circumstances, you want to raise an error for anything but `Foo`, and for that you need `if(obj is Foo)`.
Bob Aman
Don't forget about ToolKit libraries. They have different design needs then business apps. It is common to make toolkits that check an objects type before deciding what to do with the object.
Matthew Whited
Originally, when books/people said that "if" was bad, it was exactly in this context of polymorphism; which I totally agree with. At some point later, some people repeated that without knowing the original context nor why, which is a shame.
Bruno Rothgiesser
Absolutely. If you are using the type of an object as a flag that you test, this is just pointless. If for whatever reason you can't execute the appropriate code by overloading the function, that is, if in context what you really need is a flag, then just create a flag and be done with it! About the only time I use "instanceof" is when a parameter can have multiple types that can't be determined at compile time.
Jay
+9  A: 

There is the Anti-If campaign which started earlier in the year. The main premise being that many nested if statements often can often be replaced with polymorphism.

I would be interested to see an example of using the Predicate instead. Is this more along the lines of functional programming?

Keith Bloom
Hadn't even heard of the anti-if campaign. Seems a bit extreme, but I agree with the basic tenants of what they're saying.
Jason Baker
This looks and sounds like another for-profit subreligion started in hopes of getting coders to buy books about something that they'll better and more completely learn with practice.
Mike Burton
Looks like they're not anti-if, they're anti-switch-written-as-ifs.
Alex Feinman
I haven't heard of the campaign, but I ripped up some hugely complex code full of if blocks recently, and replaced it with OOP. The code went from incomprehensible buggy rubbish to a solution that was very elegant, clean, easy to understand, and easy to extend. Definitely recommended. if(possible) ;)
Lee B
@Mike and Alex, I agree that the anti-if campaign is a poor example of what I was trying to express. Thanks to Lee for doing that. Another way is summarised here http://www.refactoring.com/catalog/index.html
Keith Bloom
**sigh** So, basically, I have to radically complicate my code just to get rid of an 'If' statement? This is tantamount to employing code obfuscation to satisfy code purists. Thank you, but no.
Mike Hofer
@Mike Hoffer - No, you shouldn't complicate your code to get rid of an if statement. It *is* good to simplify your code by getting rid of an if statement though.
Jason Baker
@Jason - It is good to simplify your code by any means necessary. If your code actually becomes simpler and easier to understand by using a `goto` then you use a `goto` however "evil" it may be. If it doesn't become simpler with a `goto` (as is so often the case), then don't use it.
Chris Lutz
+3  A: 

I have to say that I recently have begun to view if statements as a code smell: especially when you find yourself repeating the same condition several times. But there's something you need to understand about code smells: they don't necessarily mean that the code is bad. They just mean that there's a good chance the code is bad.

For instance, comments are listed as a code smell by Martin Fowler, but I wouldn't take anyone seriously who says "comments are evil; don't use them".

Generally though, I prefer to use polymorphism instead of if statements where possible. That just makes for so much less room for error. I tend to find that a lot of the time, using conditionals leads to a lot of tramp arguments as well (because you have to pass the data needed to form the conditional on to the appropriate method).

Jason Baker
Martin Fowler says comments are a **sweet smell not a bad smell**. Let me quote from the "bad smells" chapter in *Refactoring*. "...comments aren't a bad smell: indeed they are a sweet smell... [but] they are often used as a deodorant. It's surprising how often you look at thickly commented code and notice that the comments are there because the comments are bad."
MarkJ
@MarkJ finally! Someone actually quoting Fowler correctly. +1.
reccles
@MarkJ: I agree. 100%
Jason Baker
+2  A: 

Hmmm

Perhaps with quantum computing it will be a sensible strategy to not use IF statements but to let each leg of the computation proceed and only have the function 'collapse' at termination to a useful result.

Regards

Mark

High Performance Mark
+83  A: 

"f" is the sixth letter of the alphabet. "i" is the ninth letter. 9 rotated by half is six. Half is the opposite of two. Two sixes plus six = 666 The Number Of The Beast. It's pretty obvious that "if" is evil.

Kinopiko
Oh deer jeebus, it's all perspex now!
random
I find this amusing, but this should really be CW.
Jason Baker
I've changed it for you. Somehow marking it as community wiki doesn't show up as an edit, but I have changed it.
Kinopiko
Some things are pretty obvious.
Groo
I don't know how I failed to see it myself.
Vadim
why are you so worried about if? there are much worst, like the cursed 'int', the unholy 'typedef' and the horrible '#include'
Oren S
Also, could be misheard as one of the words The Knights of Ni cannot hear. Then again, they wouldn't get very far in life not saying the word 'if'.
steamer25
+11  A: 

A good quote from Code Complete:

"Code as if whoever maintains your program is a violent psychopath who knows where you live." --Anonymous

IOW, keep it simple. If the readability of your application will be enhanced by using a predicate in a particular area, use it. Otherwise, use the 'if' and move on.

j0rd4n
+1 LoooooooooooooooL
Groo
Ah, but the quote from Code Complete contains an if statement and is therefore evil. :-)
Jason Baker
he he...... :^)
j0rd4n
+3  A: 

Predicates come from logical/declarative programming languages, like PROLOG. For certain classes of problems, like constraint solving, they are arguably superior to a lot of drawn out step-by-step if-this-do-that-then-do-this crap. Problems that would be long and complex to solve in imperative languages can be done in just a few lines in PROLOG.

There's also the issue of scalable programming (due to the move towards multicore, the web, etc.). If statements and imperative programming in general tend to be in step-by-step order, and not scaleable. Logical declarations and lambda calculus though, describe how a problem can be solved, and what pieces it can be broken down into. As a result, the interpreter/processor executing that code can efficiently break the code into pieces, and distribute it across multiple CPUs/cores/threads/servers.

Definitely not useful everywhere; I'd hate to try writing a device driver with predicates instead of if statements. But yes, I think the main point is probably sound, and worth at least getting familiar with, if not using all the time.

Lee B
+1  A: 

It probably comes down to a desire to keep code cyclomatic complexity down, and to reduce the number of branch points in a function. If a function is simple to decompose into a number of smaller functions, each of which can be tested, you can reduce the complexity and make code more easily testable.

madlep
+2  A: 

IMO: I suspect he was trying to provoke a debate and make people think about the misuse of 'if'. No one would seriously suggest such a fundamental construction of programming syntax was to be completely avoided would they?

Gordon Mackie JoanMiro
On the one hand I agree with you, on the other hand i'm sure they were saying that about gotos 10-15 years ago :), +1
RCIX
+15  A: 

One of common refactoring practices is to Replace conditional with polymorphism, meaning it should lead to cleaner and more maintainable code.

I consider refactoring an if statement if I clearly see that there is a branching in behavior based on a type-code. If I believe that my future modifications won't benefit much from that change, I leave it, or I just refactor it when there is a need to do it.

It is simply quicker to do it sometimes, and in simple cases it doesn't do much harm. So, a summary would be: you need to have a purpose for refactoring.

Groo
+4  A: 

I find it amusing that half of these responses couldn't even be written if we didn't use the word if itself.

Therefore, the answers themselves are evil.

We are all going to Hell.

Mike Hofer
+2  A: 

if is not evil(I also hold that assigning morality to code-writing practices is asinine...).

Mr. Haines is being silly and should be laughed at.

Paul Nathan
+1 for your thoughts on morality.
Chris Lutz
+1 for refreshing
reccles
+5  A: 

Just like in the bible verse about money, if statements are not evil -- the LOVE of if statements is evil. A program without if statements is a ridiculous idea, and using them as necessary is essential. But a program that has 100 if-else if blocks in a row (which, sadly, I have seen) is definitely evil.

Kaleb Brasee
A: 

Good that in ruby we have unless ;)

But seriously probably if is the next goto, that even if most of the people think it is evil in some cases is simplifying/speeding up the things (and in some cases like low level highly optimized code it's a must).

j t
+1  A: 

'if' isn't the code smell so much as indentation is.

If it needs an indented block, it probably needs to be extracted into a method.

Dustin Getz