The "Anti-If" campaign seeks to educate programmers about the dangers of the if statement, which seems on its face to be absurd. How can your program actually do anything without being able to make decisions about the data?
The focus of the Anti-If folks seems to be Java: there's a lot of talk in the Java community about whether or not the Anti-If people are nuts, or silly, or on to something, or just on something. However, I've been focusing recently on my code and trying to "anti-if" it as much as possible, and here's what I've discovered:
First, if statements and if expressions are two different beasts. An if statement creates two possible code paths; an if_ expression_ returns one of two possible values based upon an evaluation, and if you're a good programmer, the values will always be of the same type. (Yes, I know, I work primarily in Javascript and Python, a pair of weakly typed languages. This doesn't mean you can ignore typing. If anything, you should be paying more attention to it.) You can argue that there are still two code paths, and I agree with you, but the important consideration here is that both code paths have the same type as the ultimate result, so the testing burden is down to "does this function return what we expect it to return under all circumstances?" By narrowing the issue down to an if expression, you constrain your test to one value of one value type.
Secondly, the use of if expressions as guard conditions is good practice; it's basically insuring that your function meets the needs of the caller before returning the anticipated value, which is just Programming by Contract 101, and if you're a Haskell programmer you'll recognize a great place to use the Maybe pattern in place of null values or exceptions as signals to the caller that the function failed in some way.
Third, lots of excellent self-documenting programming techniques exist that allow you to avoid massive 'ifs' trees in the first place.
Recently, I was using Backbone to create an editor for the gene sequence alignment DSL we use at Spiral. We therefore had three possible code options: create a new Aligner, edit an existing Aligner, or run an existing Aligner. Each of these has a concrete URL associated with it, so it was possible to have separate method calls for each url by building a route association.
Instead, I had an uncomfortable mash-up of routes, all going to a single AlignerView full of if statements about "is this a launch" and "is this a new Aligner" and whatever. I spend two days refactoring, and came out with a rock-solid concrete collection of subclasses, each of which does one thing and does it well. There are still if expressions in there, and even a few if statements-- they're all in the code that manipulates the DOM, making visual decisions, what Haskell calls the "side effects." But for the most part, the risky code is now gone, replaced with a dispatch table that up front tells exactly what the code will do, and what results you will get back.
The replacement of 'if' statements with modern language constructs such as filters, maps, dispatch tables, routing tables, and factory functions that deliver polymorphic subclasses makes a more rich, better-documented, smaller and more powerful code base. Like my study of Haskell, this discipline has contributed to making me a better programmer. I recommend you try it, if only for practice.