Get Medieval On Your Code
I realize I'm dating myself paraphrasing 1994's "Pulp Fiction", but it really pays to get and stay hard-core with your project code. One easy way to turn up the heat is to enable all compiler warnings and tell the compiler to treat them as errors -- all of a sudden, those "minor" cleanup issues one never has time for now demand immediate attention. This actually save time in the long run, because once you go through the work of cleaning up all the existing warnings, any new problems can be quickly caught while the new code is being developed (rather than having to scramble after the product ships). Serious C developers have been doing this for years; the Solaris team, for example, bit the bullet maybe fifteen years ago and went "lint free", running the lint tool as part of its build and addressing all warnings it and the compiler reported, then requiring that all new code pass this same hurdle. Even though it was a major effort, that cleanup has paid major quality dividends ever since.In the past few years, Java has finally started to catch up with C on this front. Third-party static checkers like FindBugs and PMD are now freely available and are easily integrated into a build. In Java 5 the javac compiler added the -Xlint option with several types of checks, which were significantly expanded in Java 6. The Jikes compiler has a similar option called pedantic compilation (+P). All of these tools allow you to enable/disable different types of tests, and unless you strongly disagree with certain tests I recommend that you turn on all the warnings you can. Sometimes you need to suppress one or more warnings for a specific block of code. Java 5 introduced the SuppressWarnings annotation to enable you to do this, but javac ignored it in that release; happily, it is now recognized in Java 5, update 6 (1.5_06). One big advantage of globally checking for a type of potential error and suppressing it in specific places is that the SuppressWarnings annotation serves as documentation that you really intended to do this questionable practice. For example, Jackpot's parser outputs a big switch statement for a rule set, which is optimized using case statement fall-through. Since fall-though can be a frequent source of bugs, Jackpot is tested with javac's fall-through checking and with a @SuppressWarnings("fallthrough") for this specific method -- that way if there are fall-through bugs elsewhere they will be flagged.
Turning warnings into build-stopping errors has also been enabled in Java 6 via javac's hidden -Werror flag (just like the C compiler's). Jikes has the +Z2 flag to do this, and recently it added a -Werror equivalent to be command-compatible with javac. For NetBeans projects, it is easy to set these flags by right-clicking on the project, selecting its properties, clicking on the Compiling panel and putting them in the "Additional Compiler Options" field. It can be a pain changing all of your Ant build files to do this, however. You can set this property globally, however, because NetBeans projects have a javac.compilerargs property hiding in the nbproject/build-impl.xml file we can use. To set this for all projects which have this property, add this line to $HOME/.antrc (which probably doesn't exist):
The Ant startup script reads this file and passes the ANT_ARGS property to Ant's main class. If your project wasn't created by the NetBeans IDE, you can still edit the build.xml file and add this property to the javac task references. Separate static checker tools can be integrated into your build as well. Ant tasks are available for both FindBugs and PMD. Both tools have a failOnError parameter which can be set true so the build stops if a warning is issued. Both of these tools support the SuppressWarnings annotation, too. Now, those of you who are really hard-core will point out there are many other ways you can stop coddling your build and make it cough up its bugs. You are right, and in future blog postings I'll investigate other ways to get medieval on your code.