Wednesday, February 28, 2007

Gettin' Groovy

My client site uses an Object-Oriented DB. For months now, the only way to "see" the data was either a wretched DB "inspector" from the vendor or to debug the extensive server application.

I had been experimenting with Groovy a bit and decided to give it a try. In a rare flash of tactical insight (particularly step 1), I did the following:

  • The server apps are started via Ant. I hacked the Ant XML file so that it wrote the classpath variable to the console. The line was enormous but, in theory, would contain almost everything I needed.
  • I set the classpath in a "bat" file along with the Groovy jar, and set-up a windows cmd shell.
  • I started to cut-n-paste some of the DB config code into a Groovy script.
  • There was definitely a learning curve (mostly classpath/import issues), but before long, I was reading and writing directly to the OODB, using precisely the same Java classes that our app uses. Each example script was about 30 lines long.
'Twas a pure moment of Code to Joy. Beethoven was playing throughout my cube.... True, it wouldn't have been that much different to do in straight Java, but (a) there's just something "inviting" about the scripting philosophy and (b) tellingly, no one had done it for months (re: Java).

Final score: Groovy 1 OODB 0

Monday, February 26, 2007

Word to the Wise

I once received great advice about being hooked on a computer game: if you want to get away from it, and regain motivation to hack, then try and develop the game.

Around the holidays, I was playing way too much online poker at home. So I indulgently uninstalled the damn thing and started playing around with some ideas/puzzles from the game. Currently, I'm starting a modest poker simulation in Groovy. It is just as fun as the time-waster, and yet infinitely more productive.

Admittedly, if you are hooked on Guitar Hero or Final Fantasy XVII, then it is going to be a tall order. But puzzle games such as Sudoku make great inspiration for learning a new language.

Quotable #1

During a recent lecture on Eclipse:

The IDE that I hate is whichever one I'm currently using. The IDE that I love is whichever one I used previously.
-- Anon

Wednesday, February 21, 2007

The Stopwatch Idiom

A favorite tool of mine is the "Stopwatch". It is a simple, all-purpose timer. The timer starts in the constructor and stops in the log() method.

For example:


public ObjectInfo exampleMethod() {
final String whoAmI = "exampleMethod ";

ObjectInfo result = null;

Stopwatch stopwatch = new Stopwatch();

result = someRemoteService.getInfo();

logger.info( stopwatch.log(whoAmI) ) ;

return result;
}

Output to log:

21-Feb-2007-21:30.05 exampleMethod completed in 0.234 seconds

This tool is easy to write, and can be used (a) temporarily, for pinpointing performance problems or (b) general logging, especially on client-server boundaries. If the whoAmI variable is used intelligently, then a simple grep of the log file can yield muchos infos. Clearly, one can learn how long a method took, but one can also gather stats on how many times a method was called. It is almost guaranteed that this tool will surprise you with new information.

Some thoughts:
  • Note that this trick works best when there is a single-point of return in the method. Much, much more to come on this one.
  • The keen reader will certainly ask: what about aspects?! To me the answer is, as usual, the KISS principle. There is certainly a time and place for the space-age gadgetry of aspects, but not here. To me it is just painful to take a simple idea like this and go overkill with something like aspects.
  • However, I do think that using something like Spring to set a "threshold" value on the Stopwatch is very useful. i.e. The stopwatch log() method would take the logging stream as a parameter, but not perform the log unless the time taken was greater than the given threshold (e.g. 1 second).

Sunday, February 11, 2007

Universal Issues

There are 3 axes of music: melody, harmony, and rhythm. These elements exist in most musical works, and those that don't have a particular aspect, say, melody, can be characterized as such.

This idea has inspired me, for several years now, to think of "universal issues" of a software project. That is: issues that apply to every project, even if the manifestation is absent.

An easy one is "architecture", but I think that is well-documented. Here are some others, in my experience. If you are just starting a new project, you would do well to consider these early. If the your project lead (or business manager) doesn't consider these, then, um, things are gonna get interesting. (I'm assuming you don't need a full explanation of each individual issue -- if you don't know one, hit Wikipedia).

  • Installation & Versioning. Who is the target audience for the software? How will it be packaged? What does an upgrade look like? See the quote below.
  • Licensing. How do we enforce that only our customers use the software? How does it fit in with the larger business model of the project?
  • Logging. Problems happen. And someone has to troubleshoot them. (Thankfully for Java developers, this issue is vastly simplified by log4j and friends).
  • I18n. This one is huge: there are lot of languages and cultures. Obviously Java helps tremendously here, but only if the infrastructure is actually used.
  • Performance & Scale. This one and i18n are probably the biggest "come-back-to-bite-your-glutes" issues. It is extremely important to state the goals upfront because marketing will let them creep if you aren't careful. Even if it seems obvious, assert that "the sole locale will be US/English and 95% of the web-site hits will be under 2 seconds with a max concurrent load of 100 users". If everyone agrees, then great, but my guess is that it will precipitate a rowdy discussion (which is the point -- you want this worked out upfront).
Any other universal issues, in your experience?

ps. Here is a stunning quote that applies to versioning (and more):

All code is terminal. It lives under a death sentence. Data is immortal.

--Ken Downs, NY PHP user's group, 10/24/06 (as attributed by Cafe Con Leche)

Chasing Interoperability

This is off-topic but, I think, of interest to our kind (geeks).

Quoteth:

The conference had taken place in Berlin, and the nations in attendance agreed in principle that every station or ship should be able to communicate with every other, regardless of whose company manufactured the equipment. They agreed also that companies must exchange the technical specs necessary to make such communication possible.
What year was this conference? It was circa 1903 and pertained to wireless communication. From the outstanding popular history book, Thunderstruck, one part Marconi bio and one part murder mystery.

Sunday, February 4, 2007

Dining at the TDD Buffet

I recently started a gig with a new client site. In the last 18 months, they have brought in a consultant to move to Extreme Programming (XP) and Test-Driven Development (TDD). Prior to this assignment, I liked some of the items on the TDD menu, but only those which seemed reasonable. I've since realized that "reasonable" equated to "known" and "comfortable".

Before (long before my arrival):

  • They used the waterfall method. Every 6-8 months or so, people were asked for time-estimates on titanic swaths of functionality.
  • People were sequestered away in the Dilbertian cubes, emerging on occasion for a weekly ponderous, nebulous meeting.
  • The build took 4 hours!
  • They had tests that blurred unit-testing and integration-testing. They were slow and difficult to write.
Now:
  • Work is done in 2-week iterations. Though there is a large-scale sense of direction, work is estimated in much smaller units (i.e. what can be completed in this iteration?)
  • There is a war-room: a large conference room that often has 8-10 people in it. Often times, the people are paired up. Iterations are planned in this room as well. It is extremely social and highly reminiscent of a "computer lab" from university.
  • The build takes 10 minutes. There are a ton of unit-tests (via JUnit) and some integration tests.
  • The team culture absolutely encourages that developers write tests first.
My main concerns going into this were:

Can I concentrate in a war-room?

Surprisingly: yes. It has to be noted that its inhabitants are pleasant, kind-hearted professionals, and that it is not a stressful "boiler room". It's a big lab. That said, the war-room has been fantastic, especially for newbies like me, as the company's domain is highly technical (medical devices). The main upside is that people can learn about the product and others' work, just from osmosis and yet still concentrate on their own work. It is also highly efficient: one can just call out "hey, is the build breaking for y'all?" or "does anyone remember where the XYZ config property is set?".

The war-room requires significant infrastructure. This group uses new-age Wise terminals (hello 1980s!) to remote-desktop back to someone's computer in the cube. For this to work, they have a standardized IDE environment. One must use Eclipse version 3.x.y. In this way, it doesn't matter whose machine is used as the workstation.

Another key thing is that people are free to return to their cubes if they so desire. That is critical, and I certainly do that at times. Interestingly, I sometimes feel "lonely" after being in my cube for too long. Perhaps geeks are social after all?

A final thought: it is very hard for people to email/surf in a war-room. Peer-pressure is a powerful thing.

Can I really pair-up with someone?

Another surprise: yes. Again, I am lucky to be working with 2 people who are bright, articulate, and kind. This might not work if that weren't true, but for my situation, it has worked brilliantly. My main partner, Kevin, and I share roughly the same level of ability and experience, except that he has been on the project for 2+ years.

My first 2 weeks was spent as co-pilot, watching him work as he thought out-loud. This was infinitely more productive than sitting in a cube, alone, sifting through the code and checking the time to see if it was lunch-time yet. Over time, the roles gradually shifted. Now, after only 3 months, we switch back and forth effortlessly.

Just as the war-room is not mandatory, neither is pairing: anyone can "throw a pair-exception" and state that they need alone time. No harm, no foul. That's critical as well -- especially since there are those days when one of us is irritable or that the common mental thread is just not there.

Write the tests first? Really? Come on....

Everyone thinks that test-first sounds good. When you are sitting in a large group at a Java conference, it's an easy sell. It's modern and fashionable. However, when you actually are working on a project and want to impress a new client site with your productivity, it is extremely difficult to write a test first. Especially if there are no existing tests for the old functionality. Often, the "real" code is right there in the editor and the new changes are seductively beckoning you to come up to the room. It's perfectly obvious what we need to do! Just edit this method and....

Gah. Thankfully, when working as pairs, one of the pair will act as the angelic conscience who says "tsk tsk"and waves a finger at the wayward, lustful programmer. Though grudgingly, the tests are written.

And it works. This is not news, but writing tests with JUnit is fun. That damn green bar is just like getting a row of limes on some kind of Turing Slot Machine. It is an electrochemical buzz, broadcasting to our dopamine receptors. But it also changes the mindset for developing the "real" software. The game turns into this for the pair:
  • Who can come up with the next "interesting" test that exercises the old functionality? (e.g. what if a string parameter is empty? what if something is null?)
  • Once the test-suite is complete for the old code, what are some new tests for the new functionality? Again, there is an unspoken, fun competition to see who can get the next "meaty" test.
  • As the new tests are written, the "real" code is written. Because of the priority inversion (i.e. test first), what was once so seductive can actually seem a bit dreary! Let's keep thinking of tests so that I can see that pretty green bar.
  • Recently, we use a code-coverage tool, Emma, to check on the coverage of the tests. Even more green bars! Bliss.
When combining all of these aspects, I have never seen such high productivity with such a low defect-rate. This really works.

The moral of the story: most of us sample items from the TDD cafeteria, but only the things with which we feel comfortable. With serious expenditure on infrastructure and the dev process, my client site has really offered a full-blown buffet. Having tried some of the more exotic, challenging things on the menu, I gotta say: I'm a believer.

The Gist

Q: I don't know a lot about music or Beethoven. What are you talking about?

A: In a nutshell, there are a ton of tools and ideas to use when writing software, from simple Bash scripts to multi-threaded, aspect-oriented "flux capacitor" design patterns. They all have their place. It is our burden, as software composers, to use them properly. When an idea hits that sweet-spot between utility and elegance, that's Code to Joy.

The "rub" is that there isn't necessarily a right answer as to where that sweet-spot is.... There is an aesthetic debate on top of the engineering considerations. And that's fun stuff.

I fully concede that this site is experimental -- it may or may not take the musical analogy very far. It may well be a positive alternative to the "What The Heck" sites that post unbelievably bad code -- the idea is to talk about composing good software.