Wednesday, March 17, 2010

The Anti-IF Campaign

When I first found Francesco Cirillo's Anti-IF Campaign I signed up almost instantly. Over the years I've learned that the if-statement is best used sparsely. Neither the campaign, nor I, strives to eliminate all if-statements but rather wants you to think twice before using them. Unfortunately I don't think the web site does a good job explaining why if is bad, so I'm going to make a try on my own.

Every if-statement creates another path through the code. That opens up for a lot of additional cases to test and hence harder to test. Harder to test means there will likely be more bugs. For example you need to add at least one Unit test for each if you add to your code. A nice technique for testing your code coverage is to comment out either the if or the content and see if any test fails. If it doesn’t the code is either unnecessary or not covered by your tests.

That being said code is a lot about different paths, and must be, so you can’t take away all if-statements. But consider your options!

There’s the redundant if:
if (flag) {
flag = false;
}
Just replace that with
flag = false;

There’s the horrible null check:
if (filter != null) {
filteredList = filter.Filter(list);
}
else {
filteredList = list;
}
Create a null object filter and always filter, like this.
  • If don’t have a interface for your filter already, create one.
interface IFilter {
Array Filter(Array list);
}
  • Make a implementation of that interface that just returns the argument.
class NullFilter : IFilter {
Array Filter(Array list) {
return list;
}
}
  • Where you used to decide not to set the filter field, create a NullFilter.
IFilter filter = new NullFilter();
  • Now remove the if and the else and just filter.
filteredList = filter.Filter(list);

Now lets round up with the case that Francesco lists on the Campaign site where you refactor your code to use strategy objects.

The Simplest Anti-IF Code (Anti-IF Campaign)

There's a lot of other cases, but I can't go through them all. I hope that you've learned that if should be avoided and that you will try to do so in the future.

I'll end this article with a Twitter quote from @garybernhardt.
Let's rename the "if" construct to "ponder" and impose a one-second busy wait per use. That'll teach those branchers! ;)