A few Adaptavisticons attended the annual Java developer conference, Devoxx, in Belgium in November 2009. I highly recommend this conference to anyone involved with Java or the various JVM focused languages out there - the presentations are top notch with high content value. There was consensus amongst our delegation that Robert Martin's talk on 'Filling the Professional Gap' was the highlight of the week. Bob spoke, in his own superlative style, about how developers need to undertake what they do in a professional manner. Most of what Robert spoke about was common sense, but he certainly struck a chord - most notably in a jibe at untested code. He stated that the argument is over - Test Driven Development works and is necessary.
Wild Macros
Confluence, the enterprise wiki, provides a very powerful mechanism for integrating custom functionality into the heart of the system via plugin extensions. One plugin option is to provide custom macros - simple code that can be added to wiki content to add functionality, formatting or integration with other elements or systems. The macro is a powerful tool for enhancing content in a simple manner for the end user. And there are many macros out there!
However, I have always found the process of writing the code behind macros to be quite difficult to fit with the test driven paradigm.
The main entry point to a macro is via the execute method:
public String execute(Map macroParams, String body, RenderContext renderContext) throws MacroException
In the past, I have succumbed to some kind of blindness when writing macro code. Most of my macros have consisted of a large number of operations all contained within the execute method, with the final operation of extracting the required data and adding it to a VelocityContext for rendering in the appropriate template. This led to complicated code with many different execution paths based on the complexity of the macro. Having failed to write the code in a test first manner, the prospect of compiling tests for the bloated execute method was not altogether welcome and the code would most likely go untested.
Do One Thing
Having discussed the issue with my learned colleague, Jonathan Mort, he also agreed that the problem seems to stem from the execute method signature. The method accepts a number of parameters, which can be a code-smell in itself. This method could be refactored with the addition of helper methods in the BaseMacro class. For example, quite often the renderContext is only required in order to determine where the macro is being used. This could be better facilitated with a method that can determine the case for us, freeing the developer from adding this code into the macro. The body could be retrieved from a simple getBody() method.
On my current project, we realised that there was still no reason not to follow the guidelines as set out in Robert Martin's book Clean Code, as he states a rule about functions:
| Do One Thing Functions should do one thing. They should do it well. They should do it only. |
This led us to deconstruct how we can coded the execute method, extracting suitable functions that enabled us to write discrete tests. The code became easier to read - with the intentions behind it more easily understood.
The nature of the macro still makes it difficult to test, but I think this small step has helped enormously.
In all, I have found Clean Code to be full of these small, common sense rules that, when applied to our craft, help simplify and clarify our daily tasks.


Comments (1)
Jan 18, 2010
Dan Hardiker says:
It should be noted that macro instances are thread-unsafe singletons, which is w...It should be noted that macro instances are thread-unsafe singletons, which is why all state is passed in to what can effectively be a static method.
Perhaps this is a case for Macro v3, with a better architecture?