Tuesday, September 23, 2008

Building with Ant and Friends

This past week, we have been learning about the build tool Ant, and the quality assurance tools Checkstyle, PMD, FindBugs, and JUnit. We practiced using these tools on a sample implementation of the stack data structure. We were given Ant build files with targets to run Checkstyle, PMD, FindBugs, and JUnit tests on the sample stack project. Our goal was to fix the problems identified by these tests and successfully build the project with Ant, without any errors/warnings.

Running Targets

I was able to install all of the tools without any problems. I did encounter some minor problems when running some of the targets. For example, if I edited the source code and forgot to recompile before running the JUnit target, I would get "Bad version number in .class file" errors. This is because JUnit is a non-static tool--it works by actually running the code--so of course the modified code needs to be recompiled first. The problem did not arise with the other tools because they are static analysis tools: they work by examining the code (source code, or compiled bytecode in the case of FindBugs) without actually running it. Another minor hiccup was that FindBugs would show an error message complaining that it could not find the plugin directory. Perhaps this is an installation issue, but since I didn't install any plugins, and since FindBugs still worked just fine, I ignored this message.

Fixing Errors

Identifying and fixing the errors took a bit more work. JUnit identified an error at the "Testing stack top of three" assertion in TestStack; the top of the stack should be "three", but the test was getting "one". It took me a moment to realize that the problem was not in TestStack, but in the Stack.top method, which I then easily fixed. PMD gave an error about an empty catch block in TestStack that was a bit trickier to resolve. My first impulse was to add an assert false statement in the catch block. While this would technically resolve the error, it seemed like it was "cheating"; since assert statements are turned off by default, the program would still behave as if the catch block were empty. I then noticed the hint in the Javadoc comments: "Should use JUnit 4 exception annotation!" I found the JUnit API and this page helpful in learning about exception testing using annotations. I was then able to remove the try and catch blocks altogether, replacing them with an annotation that declares than an exception is expected.

My corrected implementation of the stack project is available here.

Parting Thoughts

There were some "errors" that I didn't quite understand. For example, PMD suggests that collections are declared using the interface type (e.g., List<T>) rather than the implementation type (e.g., ArrayList<T>). I don't understand the reasoning behind this. In some situations, PMD suggests returning a value directly rather than storing it into a local variable and then returning the variable. While I understand that the local variable is unnecessary, I also think that in some cases giving the return value a name makes it clearer what the method is returning.

I understand that Ant is great: it is configurable, extensible, and it allows for an automated, consistent build process. However, it is hard for me to appreciate how powerful and useful it really is, as I have not yet worked with it in a sufficiently complex project.

No comments: