Sunday, December 27, 2009

Replacing conditional logic

A conditional dispatcher is a conditional statement (such as a switch) that performs request routing and handling. For example:

public void doAction(String action) {
        if (action.equals(UPLOAD_FILE)) {
            System.out.println("uploading file");
        } else if (action.equals(SAVE_FILE)) {
            System.out.println("saving file");
        } else if (action.equals(DEL_FILE)) {
            System.out.println("deleting file");
        }
        //etc
 }



Another variation is to use "instanceof" and then do something depending on the type of the object.

The two most common reasons to refactor from a conditional dispatcher are the following:

  1. Not enough runtime flexibility: Clients that rely on the conditional dispatcher develop a need to dynamically configure it with new requests or handler logic. Yet the conditional dispatcher doesn't allow for such dynamic configurations because all of its routing and handling logic is hard-coded into a single conditional statement.
  2. A bloated body of code: Some conditional dispatchers become enormous as they evolve to handle new requests or as their handler logic becomes ever more complex with new responsibilities. Extracting the handler logic into different methods doesn't help enough because the class that contains the dispatcher and extracted handler methods is still too large to work with.

The Command pattern provides an excellent solution to such problems. To implement it, you simply place each piece of request-handling logic in a separate "command" class that has a common method, like execute() or run(), for executing its encapsulated handler logic. Once you have a family of such commands, you can use a collection to store and retrieve instances of them; add, remove, or change instances; and execute instances by invoking their execution methods.

...
public enum FileOps {UPLOAD_FILE, SAVE_FILE, DEL_FILE}

private Map handlers = new HashMap();

public CommandDriver() {
        createHandlers();
}

private void createHandlers() {
        handlers.put(FileOps.UPLOAD_FILE, new UploadHandler());
        handlers.put(FileOps.SAVE_FILE, new SaveHandler());
        handlers.put(FileOps.DEL_FILE, new DeleteHandler());
}

public void doAction(FileOps action) {
        Handler handler = handlers.get(action);
        handler.execute(null);
}
....

And the command defines the operation to execute and accepts a context object with the necessary data to do so:

public class UploadHandler implements Handler{
    public void execute(Map params) throws IOException {
        System.out.println("uploading file");
    }
}


Another alternative to replacing conditional logic is to use the Strategy pattern. This pattern has a particularly good synergy with IoC containers: it's the responsability of the container to inject the strategy to use. It is also easier to test using mocks and we can change the strategy at runtime.

public class StrategyDriver {

    private FileStrategy fileStrategy;

    public void setFileStrategy(FileStrategy fileStrategy) {
        this.fileStrategy = fileStrategy;
    }


    public void doAction(Map params) throws IOException {
       fileStrategy.handleFile(params);
    }

    public static void main(String[] args) throws IOException {
        new StrategyDriver().doAction(null);
    }
}

Friday, December 4, 2009

Redeployment pain



Did you know that the average turnaround time (for deploy/redeploy) of a typical web application is about 1 minute? This sums up to almost 1 month a year (of pure waste)!
That's a completely insane amount of waste.
And don't forget the effort/time that's necessary to pick up "where we left" when the application is running again after staring at the console for a small while.
So, how can put the redeployment torture to an end?



Deploy the application in exploded format

You can package view templates and other types of GUI resources and just hit "refresh" but it doesn't work for classes so it works partially.

OSGI modules

By dividing the application in smaller modules we can speed up the turnaround time. Less code has to be deployed but still we have to wait and there's a degradation cost.

Web framework class loaders

For example, Seam supports incremental redeployment of JavaBean components. That's pretty nice but it doesn't work for entity classes (plus several other limitations) so it works partially. I think Tapestry does something similar.

JVM Hotswap

Running an application in debug mode you can "reload" changed classes. Works OK as long as you only make changes in method bodies (no new methods, no new fields). On top of that it's too slow so it's not really a solution

JavaRebel

I attended a Devoxx presentation about this product and was impressed. :)

It installs as a JVM plugin (-javaagent) and works by monitoring the timestamp of class files. When it is updated (e.g. when a developer saves a class from the IDE) JavaRebel will reload the changes to class code and structure while preserving all existing class instances.

Check http://www.zeroturnaround.com/javarebel/

I've actually tried this and it works both for JavaBean components and entities. Cool! Of course ot also works for any Java SE application. Goodbye redeployment pain.

For example for JBoss all you have to do is add the following line to run.bat

set JAVA_OPTS=-noverify -javaagent:javarebel.jar %JAVA_OPTS%


And after copying the javarebel jar file to /bin you are ready to start your application and enjoy zero turnaround glory :)