Thursday, March 6, 2014

Good use of Closures - Execute around pattern

Not long ago, in a blog post, I explained what Closure were in Groovy.  This blog post will explain one good example of using them.  I recently found myself having to write the same exception handling logic for a bunch of back-end Controller APIs which were serving AJAX requests.  It was like this
class ApiRugbyPlayerController {
    JSON getPlayerStats() {
        try {
            ...
            // invoke business service method to get player stats
        } catch (ServiceException serviceException) {
            // don't care too much about this. 
            // log and move on
            ...           
        } catch (SessionException sessionException) {
            // clear out session cookies
            ...
            // send 403 to client 
            ...
        } catch (Exception ex) {
            throw new ApiException(ex)
        }
    }

    JSON updatePlayerStats() {
        try {
            ...
            // invoke business service method to update player stats
        } catch (ServiceException serviceException) {
            // don't care too much about this. 
            // log and move on
            ...           
        } catch (SessionException sessionException) {
            // clear out session cookies
            ...
            // send 403 to client 
            ...
        } catch (Exception ex) {
            throw new ApiException(ex)
        }
    }

    JSON queryPlayerStats(){
        try {
            ...
            // invoke business service method to query player stats
        } catch (ServiceException serviceException) {
            // don't care too much about this. 
            // log and move on
            ...           
        } catch (SessionException sessionException) {
            // clear out session cookies
            ...
            // send 403 to client 
            ...
        } catch (Exception ex) {
            throw new ApiException(ex)
        }
    }
}
As can be seen, there is some code duplication going on here. In the spirit of DRY (don't repeat yourself), it is better to only define this exception handling logic once and then re-use it. So I defined the following utility method, which implements the exception handling pattern and takes a closure which is executes the exception handling for.
    private JSON withExceptionHandling(Closure c) {
        try {
            ...
            c.call();
        } catch (ServiceException serviceException) {
            // don't care too much about this. 
            // log and move on
            ...           
        } catch (SessionException sessionException) {
            // clear out session cookies
            ...
            // send 403 to client 
            ...
        } catch (Exception ex) {
            throw new ApiException(ex)
        }
    }
We can make a code block a closure in Groovy by surrounding it with {}. This means I can make the logic inside my Controller methods into Closures and pass them to my utility method. And when I pass it to my utility method I don't even need to pass it inside a () as Groovy doesn't make you. So that means, I can take out all the common exception handling, remove the code bloat and my Controller API's are much cleaner.
class ApiRugbyPlayerController {
    JSON getPlayerStats() {
        withExceptionHandling {
            ...
            // invoke business service method to get player stats
        } 
    }

    JSON updatePlayerStats() {
        withExceptionHandling {
            ...
            // invoke business service method to update player stats
        } 
    }

    JSON queryPlayerStats(){
        withExceptionHandling {
            ...
            // invoke business service method to query player stats
        } 
    }

    private JSON withExceptionHandling(Closure c) {
        try {
            ...
            c.call();
        } catch (ServiceException serviceException) {
            // don't care too much about this. 
            // log and move on
            ...           
        } catch (SessionException sessionException) {
            // clear out session cookies
            ...
            // send 403 to client 
            ...
        } catch (Exception ex) {
            throw new ApiException(ex)
        }
    }
}
So there we go. We have adhered to DRY principles, avoided code bloat and have a dedicated place for our exception handling confident that it being implemented consistently. This example of Groovy closure is a little but like a second order invocation in JavaScript. If we wanted to do something like in Java, it would just involve a lot more code. We could use something like the template method pattern. You would have more decoupling, but you have a lot more code. Or you could make all your AJAX APIs enter a common method (like a Front Controller) and put your common exception handling there. Again, possible but just more code. Until the next time, take care of yourselves.

No comments:

Post a Comment