Refactoring to remove code duplication using the strategy pattern

The strategy pattern‘s main benefit is often stated as being that it provides the ability to essentially swap out parts of an algorithm’s behaviour at runtime. There is another use however that may be deemed overkill and that is simply to get rid of duplicate code.

Consider the following two methods, each with DO A STUFF and DO B STUFF as identical lines of code.

public void foo() {
  // do A stuff
  fooSpecificSection();
  // do B stuff
}
public void bar() {
  // do A stuff
  barSpecificSection();
  // do B stuff
}

How can we refactor the offending abomination to get rid of the duplication? There are a number of techniques, one way is simply to use simple control flow statements (switch, if) as suggested in the following excellent overview of the strategy pattern. So we would have the following for example.

enum Action {FOO, BAR}
public void fooBar(Action action) {
  // do A stuff
  switch(action) {
    case FOO:
      fooSpecificSection();
      break;
    case BAR:
      barSpecificSection();
      break;
    default:
      throw new IllegalArgumentException();
      break;
   }
   // do B stuff
}

As you can see from the above, depending on the number of lines of code in DO A STUFF and DO B STUFF we might not actually have reduced our total lines of code (TLOC) but we would almost certainly have made maintenance easier and less error-prone since our two cited sections of potentially intentionally identical code are no longer duplicated.

If we where to use the strategy pattern to get rid of the duplication in Java 7 we would end up defining a one method interface and an anonymous inner class as has been neatly illustrated here. In the simplest possible case our interface will effectively just be a function pointer, as is shown below.

interface Action {
  void execute();
}
private template(Action action) {
  // do A stuff
  action.execute();
  // do B stuff
}
public void foo() {
  template(new Action() {
    @Override
    public void execute() {
      fooSpecificSection();
    }});
}
public void bar() {
  template(new Action() {
    @Override
    public void execute() {
      barSpecificSection();
    }});
}

Arguably the solution shown directly above is more convoluted, however consider that the main reason for this is because of Java 7’s poor support for function pointers in the foo() and bar() methods.   This may no longer be an issue with Java 8 with the introduction of method references.

Berkeley DB Java Edition – Gotcha Log

This post is simply a log of Berkeley DB burns or gotchas written as rules to be remembered. The post will be updated as time goes by.

1. Don’t just change your enum constants willy-nilly and deploy

If you are in development mode, running your app on your local lightweight container, then this one is easy to forget. Its good to get into the habit of having a staging environment with Berkeley DB in write-to-disk mode, even on your local, so that you can occasionally get burnt by Exceptions such as this one and so remember it.

java.lang.IllegalArgumentException: Deletion and renaming of enum values is not supported: STANDARD

at com.sleepycat.persist.impl.EnumFormat.initValues(EnumFormat.java:93)