A blog about software development and other software related matters

Blog Archive

Thursday, November 13, 2008

Objectifying conditionals

Im sure that any programmer has come across a code snippet which included a long list of nested conditionals, like follows:


public class NaiveImpl {
public void process(final String option) {// mapping a type code to behaviour
if (option.equals("first")) {
// first option ..
} else if (option.equals("second")) {
// second option code ..
}//.. a ton load of other conditionals
}
}

Basically conditionals map between state (option) and behavior (a legacy which is carried from the procedural programming days), multiple conditionals are problematic:

  • They include multiple navigation paths in single condensed code sections.

  • They have a large number of inter dependencies between them (makes changes hard).

  • They are not objects (statements in Java, we cant access them in runtime, they are not "first class citizens").



One of my favorite ways of handling type code to behavior mapping without the resort to conditionals is binding Enum values to behavior:


public class CleanImpl {

private interface Handler {
void handle();
}
private static Handler firstOptionHandler = new Handler() {
public void handle() {
// first option code
}
};
private static Handler secondOptionHandler = new Handler() {
public void handle() {
// first option code
}
};

private enum Option {

First("first", firstOptionHandler),
Second("second", secondOptionHandler);// more options to come ..
private final String name;
private final Handler handler;

private Option(final String name, final Handler handler) {
this.name = name;
this.handler = handler;
}

private static Option fromString(final String optionString) {
for (Option option : values()) {
if (option.name.equals(optionString)) {
return option;
}
}
throw new RuntimeException("no matching option found");
}
}

public void process(final String option){
Option.fromString(option).handler.handle();
}
}

This code seem to be more verbose at first glance but its more than reasonable to split the handler interface and implementations into separate files (all in one file enables minimal visibility of members and getter-less code), its easy to see how all the above downsides are answered:

  • No multiple navigation paths in single condensed code section (each handler is seperated).

  • No inter dependencies between different options handling.

  • All round objects.


Hopefully will see more usage of similar patterns and enjoy an if-less world!

No comments: