Agile Java published!

I finally got my copy of Agile Java from the publisher on Tuesday, after some typical production delays. The way things worked out, some other fortunate consumer got to see it before I did! Ahh well. At least he was kind enough to email me some positive words on it.

I’ve spent months waiting for the book to ship. I wouldn’t have guessed that I’d relinquish the joy of opening the first copy from the publisher to my wife Kathy. But she was home when the FedEx guy dropped it off, and I gave her permission to go ahead and rip it open. I even let her open the boxes of additional copies sent by the publisher. Jaded? Maybe. Or maybe just detached and disbelieving. When I did open it, I was impressed with how much it looked like a real book, like something I couldn’t have possibly had anything to do with.

But I did, and now that it’s done I don’t even want to think about the countless hours I spent on it. Writing, coding, rewriting, editing, reworking, cleansing. A conservative estimate is perhaps 750 hours over the course of 18 months; maybe one hour per page.

And it’s still not complete. I’ve noticed a number of small problems that should be fixed and several sentences that I’d like to reword. I’m hoping to sell enough copies to warrant at least a second printing. Not so much for the money, but for the opportunity to make it an even better book.

As with code, technical writing is never perfect, and there’s always a way to improve on it. I hope I get the chance.

Trying too hard?

J2SE 5.0 includes a new for-each loop that works like its C# or Visual Basic counterpart. It provides a simple, consistent idiom for iterating across collections or arrays. The for-each loop is intended to replace the need for working with Iterator or Enumeration objects or for using classic for loops to iterate across a collection.

For example, you can code:

int[] list = { 1, 2, 3 };

for (int i: list)
   System.out.println(i);

or:

List list = new ArrayList();
list.add(1);
list.add(2);
list.add(3);

for (int i: list)
   System.out.println(i);

Both produce the same, expected output. The syntax is reasonably obvious. The cooler part is that you can create your own iterable classes, simply by implementing the new Java interface java.lang.Iterable.

Sometimes I like being an object weenie. Having done enough Smalltalk, I prefer an object-based solution over a procedural solution most of the time. Uninformed claims to the contrary, a pure object-based solution can be elegant, powerful, and easily maintainable. Certainly procedural and other paradigms have their place, but you wouldn’t throw OO concepts into a C program, so why clutter an OO program with C code?

So, what about replacing classic C-style for loops with an OO concept? The basic idea is that instead of coding something like:

for (int i = 0; i < 10; i++)
   ...

you code:

for (int i: new Sequence(0, 9))
   ...

Here is the Sequence class. Tests follow.

import java.util.Iterator;

public class Sequence implements Iterable {
   private int start;
   private int stop;
   private int increment = 1;

   public Sequence(int start, int stop) {
      this.start = start;
      this.stop = stop;
   }

   public Sequence(int start, int stop, int increment) {
      this(start, stop);
      this.increment = increment;
   }

   public Iterator iterator() {
      return new SequenceIterator();
   }

   private class SequenceIterator implements Iterator {
      private int count = start;
      public boolean hasNext() {
         return count <= stop;
      }
   
      public Integer next() {
         int result = count;
         count += increment;
         return result;
      }
      
      public void remove() {
         throw new UnsupportedOperationException();
      }
   }
}

SequenceTest:

import junit.framework.*;
import java.util.*;

public class SequenceTest extends TestCase {
   private List ints;
   
   protected void setUp() {
      ints = new ArrayList();
   }

   public void testSingleEntry() {
      verifySequence(new Sequence(0, 0), 0);
   }

   public void testTwoEntries() {
      verifySequence(new Sequence(1, 2), 1, 2);
   }
   
   public void testMultipleEntries() {
      verifySequence(new Sequence(5, 10), 5, 6, 7, 8, 9, 10);
   }

   public void testNegativeNumbers() {
      verifySequence(new Sequence(-2, 2), -2, -1, 0, 1, 2);
   }
   
   public void testIncrement() {
      verifySequence(new Sequence(0, 5, 2), 0, 2, 4);
   }

   public void testIncrementIncludesLimit() {
      verifySequence(new Sequence(0, 6, 2), 0, 2, 4, 6);
   }

   private void verifySequence(Sequence sequence, int... expectedValues) {
      for (int i: sequence)
         ints.add(i);
      assertEquals(expectedValues.length, ints.size());
      for (int i: expectedValues)
         assertTrue(ints.contains(i));
   }
}

Sometimes things like this seem like a really dumb idea. It has a few potential values beyond my object compulsiveness: you can pass the Sequence around easily; you could persist it if you had to. You could also extend its complexity without having to alter code that uses a sequence.

Not very earth-shattering, and perhaps I’m trying too hard to create something where it’s not needed. But let me know if you find this useful.

 

Comments:

Not at all overkill. In fact, as a means to really get my head around J2SE 5 (especially generics), I’ve been working on a collections library influenced by the ANSI Smalltalk collection protocols: http://sf.net/projects/jaggregate. I know this treads over “Essential Java Style” territory, but it’s been educational, and who knows, maybe it’ll catch on at some point. I’m writing benchmarks for ArrayList vs. OrderedCollection right now…will also pit HashSet vs. Set, HashMap vs. Dictionary, etc.

The closer we get to “everything is an object”, the better IMHO.

Pairing and Other Office Battles

A poster at JavaRanch complained about loss of worker productivity when his cubemate started pair programming. His work was suffering due to the amount of constant conversation. I dropped a subsequent posting, suggesting that perhaps his neighbors weren’t that good at pairing yet. Pairing done effectively requires only a small amount of verbal communication.

That aside, I’m reminded of other battles in shops. Lights vs. no lights, for example. Some cultures like to work in the relative dark and turn off the fluorescent lights. This can make it very difficult for some people, perhaps even emotionally. Others claim that fluorescent lights cause them similar distress, and they’re unable to work as effectively as possible.

The best we can do is learn to show some respect and consideration for others. This doesn’t mean, however, that we cater to everyone’s whims. I happen to work best shirtless (not a pretty sight) and with obnoxious music playing. I’ve found that I need some noise level, otherwise I’m unable to concentrate. (It’s probably a side-effect of my wife using a white noise device to sleep at night.) But my personal preferences aren’t going to fly in most places.

I’ve gotten to the point where I just don’t give a hoot. After doing this long enough, I’ve learned to adapt to wacky coding styles, ignorant management, fluorescent lights, unworkable processes, shirts, and silence or excessive noise. I’ve worked in a Coke room, an open room with 60 people (on 3+ projects), in a rickety shack of a building, in lots of horrid cube farms, in an office with a physically abusive coworker, and in an office with two heavy smokers (back when you could still smoke in the office). I still managed to always get the job done.

I note that my most successful projects were when I worked in a collaborative environment, i.e. not in isolated cubes or offices. The best efforts I’ve ever been on were with a bunch of developers circled around a group of monitors, pairing or no pairing and XP or no XP.

If something is particularly bothersome to me, I first find a way to change it. I’ve taken out fluorescent light bulbs, I’ve brought in Allen wrenches and dismantled cubes, I’ve put my headphones on, I’ve requested a different cube, I’ve talked to my coworkers and management. If I can’t change it, I learn to cope. If I can’t cope, I just leave. When the time comes that none of these is an option, it’s time to move to my second career.

Atom