Java Development w/The Eclipse IDE: Five Underused Features

Conditional Breakpoints

Have you ever wanted to suspend execution only under a certain circumstance while debugging, such as every hundredth loop iteration? You can. Set your breakpoint, right-click it, select “Properties”, check “Enable Condition” and enter a condition in normal Java code that will be evaluated every time the breakpoint is hit to determine whether or not to suspend the JVM.

Remote Debugging

Sometimes things work on everybody’s box.. except Bob’s. You’ve watched him produce the issue and have tried to reproduce it on your development machine, but it just ain’t happenin’ for anybody but him. It’s time for a remote debugging session. Start up the JVM on Bob’s box like so..

java -Xdebug -Xrunjdwp:transport=dt_socket,address=8000,suspend=n,server=y
-jar YourApplication.jar

Within Eclipse IDE on your development machine, select Run -> Debug… and create a new “Remote Java Application” configuration. Select the project that contains the source code, enter Bob’s boxes hostname (or IP address) and the port his JVM is listening on (8000 in this case). Click the “Debug” button to close the dialog and your “Debug” view should now show a new session, connected to Bob’s JVM, and the threads of your application just as if you were debugging it locally. You can set breakpoints and use all the other features described in this article, or impress your mom by starting another instance of your application locally and step through both Bob’s and your own JVM instance simultaneously, side-by-side!

Dynamic Variable & Code Replacement

If you’re debugging a tricky piece of SQL in a servlet that isn’t working right, it’s tempting to abide by the typical write, compile, deploy, run, debug, repeat cycle every time you need to tweak the String. This is tedious and time consuming. Instead, set a breakpoint someplace after the String is defined but before it is used. When you hit it, right-click the variable in the “Variables” view and select “Change Value…”. You can figure it out from there. (Note: This doesn’t seem to work for “final” variables, and so-so with statically declared things.)

If you modify and save a class while you have a debugging connection established, Eclipse will try its best to update the code on the remote JVM without having to restart it. This doesn’t always work (especially if there are stack frames using the changed code), but you’ll be notified if the remote JVM could not be updated. This is especially useful when testing a complex algorithm in a situation that is a pain in the arse to set up.

Custom Code Templates

Typing “fore[autocomplete]” in a block in Java code will add a “foreach” code template that you can fill in using the TAB key. These are customizable, and you can even add your own. For example, I prefix all generated local variable and Iterator declarations with the “final” keyword, and have added my own custom templates for inserting my most frequently used Java 5 annotations. Go to Window -> Preferences… -> Java -> Editor -> Template and have some fun.

Refactoring Actions

All of the refactoring features of Ecilpse IDE are worth learning. I can’t think of one that isn’t. Once you have a method defined and used, there isn’t much reason to manually modify the declaration. “Move”, “Change Method Signature…”, “Pull Up…”, “Push Down…” etc. give you basic, commonly used tools, and actions such as “Extract Interface…”, “User Supertype Where Possible…” etc. provide support for larger jobs. Understanding what all these do helps relieve some of the pain felt when refactoring heavily used, public APIs, and helps keep you focused on the bigger picture by taking care of the details.

If A Unit Test Fails In The Woods, Does It Make A Sound?

No, it doesn’t. Unit tests that execute a large amount of code but fail to make assertions along the way give you a false sense of confidence in the code. They pass when they should fail. These problems, formally known as type 2 errors, are a huge liability for a development team because the tests are believed to be verifying the intended behavior of the software, but are really doing nothing in a really lengthy way.

For a new person maintaining the code under test, the problems worsen. The new maintainer will not understand what the code is supposed to be doing: what it’s currently written to do or what is implied by the possibly out-dated and incomplete unit tests. Good luck finding API documentation if the unit tests suck, and have fun with those future API changes when you must attend to the “unit tests” that need to be updated to successfully add no value to the project, just as they were originally written. No thanks.

Units test exist to prove that software is behaving as intended, not simply “mock” user actions. This means being particular about states of things during a process, and doing mean negative testing by passing nil into that function that clearly requires a non-nil value. The rule of thumb is this: if, for whatever reason, you cannot write, fix, or otherwise finish work for a correct and complete unit test, assert false. You have not proven the software works correctly, so it doesn’t work. Period.

Square Foot Garden Beds

I built a couple of square foot garden beds this weekend. The frame is made of redwood 2x2s, and the sides are redwoord planks normally used for fenching. The bottom of the bed is a thick sheet of plywood with holes drilled through it for drainage. The diagonal supporting pieces connecting the load bearing trusses with the vertical posts helps support the weight of the beds contents.

2x6 Garden Bed

Ant Rant

I’ve come to loath ant.

XML is great for a lot of things, but is simply painful for expressing control flow. Now don’t get me wrong, it’s still easier to work with than make; you can use any XML editor or a web-browser to validate the well-formedness of an ant build file. It’s just that programmatic thought isn’t elegantly represented by a tree structure full of angle brackets. Trees are simplifications computer scientists use to fit information into limited structures that can be easily parsed and manipulated, however, as a user of the system I don’t give a flying flock that it uses a standard SAX parser. I do care about defining basic control-flow operations in a natural way, and not having to create artificial work-arounds to cater to the structure of the tree. Elegance, however, is the least of ants problems. It lacks a fundamental development capability that is missing from other build systems such as make and jam, and even long-established shells such as bash: debuggability.

Here’s the deal, plain and simple: if you’re writing a development tool, you must provide some mechanism for easy debugging. “Hello, world!” does not require troubleshooting. Every other real-world “script” does. If you’re automating a build process for a large application, it will have bugs, and when you do get them squashed the system will soon be inadequate and require modification. Now, when I say “debuggability”, I’m not talking about scattered echo/print elements throughout the code or color-coded syntax. I’m talking about stepping through the script line by line and examining the inputs and outputs of every step in the process, just like you would with any C++ or Java program,

The last item in today’s rant is support for basic data structures. Variable passing is pukingly awkard in ant, and calling other targets sometimes requires firing up another ant process. Umm.. riiiiight. “If today is Saturday turn debugging support on, run all known unit tests and send a status report to all team members” is not an unrealistic use of these systems. Debugging this should not be such a chore.

Preston Joins The 21st Century

After an eternity of posting my thoughts, project information and other digital potpourri in a scatter manner across the wire, I’ve finally begun putting the pieces for my personal website. Apparently this is now a requirement for Software Engineers to age past 25, so I have some serious catching up to do. Hooray me.