Dead time: code, compile, test

When developers were writing C, C++ or Java code in the old days, we used to say that the software development process was a seemingly endless cycle of (1) coding, (2) compiling the code, (3) testing the code. Ideally, you want to spend most of your time coding and testing rather than performing mundane tasks that a computer ought to be doing.

So I always have to scratch my head when I hear people make criticisms about the development cycle when using Java because of the associated time they spend compiling code. I feel somewhat odd writing this post, because this material seems completely obvious to me, but apparently there are others in the world who have different experiences. Timothy O’Brien discusses some of them in his article on onjava.com.

I say this because my experience is totally different. And I think it has to do with the way I have my dev environment set up. I thought I’d take a few minutes to describe what I’m doing in case it’s useful to anybody. First off, I’m using Eclipse. Eclipse is super. It compiles my code as I write it and gives me good refactoring capabilities, syntax checking and other goodness. I have the FindBugs plugin installed to get a bunch of extra checks available to me as I’m writing my code. This particular plugin has helped me code in a very defensive manner, especially in cases where I have complex execution paths. When dealing with a traditional MVC architecture, this combination works fine for the Model components since I can also take advantage of the one-click access to fire off a bunch of junit tests. So, basically, I’m just coding and testing. I’m certainly not compiling code myself.

I also use Jetty and JettyLauncher plugin. This is a pretty important point, because they basically inherit the classpath from my Eclipse project. The result is that I don’t to build .war files when I’m developing. When dealing with the Java-based Controllers for my application, this is a real time-saver. Write code, bounce servlet container and test it. Now, it only takes Jetty a second or two to start up, which is definitely a pain in the neck. I’d love to get some fancier classloaders in there for development purposes to help me avoid this cost. But it’s pretty close to what I actually want.

Not all my Controllers are written in Java, though. I’m also using Apache Cocoon for parts of my application, specifically the AJAX endpoints, and I’m writing those Controllers in JavaScript using Cocoon’s Flow API. Those are interpreted, so I’m coding in a scripting language at that point. Development overhead is reduced somewhat since I don’t have to bounce the container after each change to get the classloaders to pick them up, but I’m also giving up some of the static checks that a compiled language can give me. But this works pretty well, so I’m fairly satisfied with that as well.

The one thing that I would really like is a servlet container that runs JSPs in an interpreted mode for development purposes in order to reduce the cost associated with compiling the JSP into bytecode. There’s definitely some room for improvement here. If anybody knows of a better way to handle JSP changes in a transparent manner, I’d love to know about it.

I want to go back to Timothy’s article on onjava.com, specifically to this statement:

In a scripting language, you can make a change to your code and run it immediately.

I’ve worked with Perl for about 10 years and I’ve coded Perl full-time at several jobs, so I feel qualified to respond to this. He is indeed correct, but my experience in coding Perl actually was more like this:

Write some code:
$ emacs program.pl

Do some syntax checking:
$ perl -c program.pl

Fix syntax errors:
$ emacs program.pl

Do some syntax checking:
$ perl -c program.pl

Run code (finally!):
$perl program.pl

While it’s true in many cases that you can simply edit your code and run it immediately, I found it very useful to run some syntax checks as I was coding. Ideally, I would have found a way to avoid the ‘perl -c’ step, but in some cases, you don’t want to run things immediately if there’s going to be a failure of some sort. An example of this would be a situation where a bash script performs some actions, kicks off a perl script and then the bash script finishes its job. If the perl code is going to fail due to a syntax problem, you’re not going to gain a lot by running it, especially if you then have to reset some preconditions so that the calling shell script will run properly again.

So the analog with Java code doesn’t hold any water for me, because I hardly ever kick off javac myself. Do you? I can’t see the point in this. If you do, it’s likely because your development environment could use some optimization or you are over-relying on Ant for build-time activites that you might be able to make into configuration options that are read at runtime.

Timothy’s notion of “dead time” is so correct, though. You must aggressively address any dead times in your development process, because you will quickly spend huge amounts of aggregated time dealing with them. One project I worked on required our team to use the development tools selected by our client. We each had powerful dual-processor Intel workstations but we were saddled by an unbelieveably bad IDE by an Infinitely Big Manufacturer of various computer products (I won’t name them:). It quickly became apparent that the software chosen by our client was complete junk, but there was no way to change it for various political reasons. We calculated that our developers were spending 40% of their time fighting with the IDE and the poor integration with the client’s source control system. Unfortunately, since getting rid of the software wasn’t an option, we all had to literally work twice as many hours to get the same amount of work done. (Some developers started using sane tools and resorted to copying and pasting their code into the IDE that the client selected so they could check it into the versioning system. No kidding.)

But I really doubt if the amount of dead time imposed by using a compiled language is as high as some people claim. Real productivity benefits are derived from other things like frameworks, architecture and a streamlined development environment.