Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

anti-if campaign

I recently ran against a very interesting site that expresses a very interesting idea — the anti-if campaign. You can see this here at www.antiifcampaign.com. I have to agree that complex nested IF statements are an absolute pain in the rear. I am currently on a project that up until very recently had some crazy nested IFs that scrolled to the right for quite a ways. We cured our issues in two ways - we used Windows Workflow Foundation to address routing (or workflow) concerns. And we are in the process of implementing all of our business rules utilizing ILOG Rules for .NET (recently purchased by IBM!!). This for the most part has cured our nested IF pains...but I find myself wondering how many people cure their pains in the manner that the good folks at the AntiIfCampaign suggest (see an example here) by creating numerous amounts of abstract classes to represent a given scenario that was originally covered by the nested IF. I wonder if another way to address the removal of this complexity might also be in using an IoC container such as StructureMap to move in and out of different bits of functionality. Either way...

Question: Given a scenario where I have a nested complex IF or SWITCH statement that is used to evaluate a given type of thing (say evaluating an Enum) to determine how I want to handle the processing of that thing by enum type - what are some ways to do the same form of processing without using the IF or SWITCH hierarchical structure?

public enum WidgetTypes
{
    Type1,
    Type2,
    Type3,
    Type4
}

...

WidgetTypes _myType = WidgetTypes.Type1;

...

switch(_myType)
{
    case WidgetTypes.Type1:
        //do something
        break;

    case WidgetTypes.Type2:
        //do something
        break;

    //etc...
}
like image 407
Andrew Siemer Avatar asked Jul 22 '09 19:07

Andrew Siemer


4 Answers

The problem is not the 'if' statement, it is the programmers who write bad code.

EDIT: Also, as others have pointed out, you should be using polymorphism (if available) when you are using if statements to check the type of an object, but if statements in and of themselves are very useful and fundamental constructs.

like image 77
Ed S. Avatar answered Oct 22 '22 19:10

Ed S.


In Java it's easy to use enums as polymorphic anti-if agents.

public class AntiIf {
    public enum WidgetTypes {
    Type1 {
        public void doSomething() {
        //...
        }},
    Type2 {
        public void doSomething() {
        //...
        }},
    Type3 {
        public void doSomething() {
        //...
        }},
    Type4 {
        public void doSomething() {
        //...
        }};

    public abstract void doSomething();
    }

    WidgetTypes _myType; // set by someone to one of the types.

    public void someFunction() {
    //...
    _myType.doSomething();
    //...
    }
}
like image 41
Robert C. Martin Avatar answered Oct 22 '22 20:10

Robert C. Martin


Being anti-if is silly.

Sometimes replacing a conditional via polymorphism is the right thing to do, but in those cases it wasn't the if statement that was the true problem. The real problem was working with abstract types in non-abstract ways, i.e., failing to think at level of abstraction of the base class.

Other times it is possible to replace a conditional via polymorphism, but doing so would be a bad idea. The logic that leads you to treat one type different from another may belong in the algorithm itself, not the individual classes. Moving that logic to the classes may cause the classes' code to be overly aware of the context in which they are used.

But most often, an if statement has nothing to do with polymorphism at all. Getting rid of if statements is the wrong goal here.

Being anti-if is silly.

like image 22
Darryl Avatar answered Oct 22 '22 21:10

Darryl


Switch statements can often be replaced by polymorphism:

abstract class WidgetBase {
  public abstract void DoSomething();
}

class Widget1 : WidgetBase {
  public override void DoSomething() {
    // Do something ...
  }
}

class Widget2 : WidgetBase {
  public override void DoSomething() {
    // Do something ...
  }
}

...

Widget widget = new Widget1(); // Use a factory pattern instead.
widget.DoSomething();
like image 15
Martin Liversage Avatar answered Oct 22 '22 20:10

Martin Liversage