Main | April 2004 »

March 29, 2004

A Polyglot in the making

I've realized that I've been sadly neglecting my range of development languages over the last couple of years. Sure, I've picked up a hint of Python here, a whiff of PL/SQL there, but since I last had to professionally develop in a language apart from Java (2001), I haven't really considered myself even partially fluent in any language I've looked at since university.

With this in mind, and spawned on by a great piece of tell-it-as-it-is stuff from the Pragmatic Programmer boys, I've decided to take the most recent piece of Java code I've been tinkering with and port it to several other languages that I'd like to learn...

The target application is a small utility called DocIndex. It's raison d'etre is fairly simple: from a nominated directory location, trawl through all the subdirectories looking for potential HTML documentation. When such a directory is found, store it's location and generate a simple HTML index page containing all the found directories as the result.

What do I use this for? Basically, I've accumulated a ton of HTML documentation relating to the various applications and (more frequently) languages, libraries and frameworks I've downloaded over the years. And I've been somewhat lax in keeping bookmarks to all this documentation. This tool can be pointed at my hard drive and a couple of minutes later can give me a list of every directory it thinks contains some form of HTML documentation.

The rules it uses for this process are straightforward and somewhat arbitary. A directory is considered to be containing documentation if:

DocIndex uses this set of rules to generate links to all the documentation on my hard drive in a couple of minutes and present them in a usable, albeit not very visually appealing, manner.

The application consists is about 200 Java SLOC (not including tests) and the structure appears in the diagram below:

org_corvine_docindex.gif

Although I have a small list of additional tasks for the current codebase (e.g., threading, further customization, addition of UI, etc.), I'm going to branch the codebase now to begin re-implementing in other languages. So far, I'm targetting the following:

I've chosen languages which have a zero dollar cost to use and are sufficiently different to keep me on my toes all of the time. For the same reasons, I've not considered C or C++ implementations.

Wherever possible, I'll try to use the full features of each language, but lack of experience will probably prevent me from an optimal solution in many cases. Still, I'm hoping to gain a fairly good understanding of each language. In addition to this, I'd like to present some findings on the relative suitability of each language for the task at hand.

Posted by Andy Marks at 02:09 PM | Comments (1)

March 28, 2004

Eclipse M8: Milestone or inchpebble?

I've been a fairly avid Eclipse bleeding edger for quite some time now, so I latched upon the chance to try M8 over the weekend. Some 80Mb of download later, I was ready to go. Although I haven't had quite the negative reaction to this version as my compadre Jon, I do have a couple of comments to make.

I should qualify all that follows by admitting I'm only an Eclipse user out of business hours. Professionally, I use IntelliJ and have bound most of the Eclipse actions to their IntelliJ keyboard shortcut equivalents to minimize context switching between applications. My general opinion is that IntelliJ is a smoother product overall, but Eclipse has made great leaps forward recently and there really isn't much between them.

Bottomline: I like Eclipse enough to not purchase a copy of IntelliJ for home use and not feel like I'm hamstringing myself unnecessarily.

So on with the review...

First off, I must admit I really like the no fuss/no muss approach the Eclipse crew take to installation: basically, you unzip the installation file to wherever you need it and execute the application file to get going.

Wow! Unlike most of the other Ms in the 3.0 family, when you start M8 for the first time, you really notice that "the times they are a-changin'". I was immediately impressed by the workspace configuration dialog that appeared as I always changed the default location (somewhere in the installed application directory) whenever starting a new project as I didn't like keeping my project source in the same directory as my applications. I dare say there was/is a configuration option somewhere to override this default, but I'd always been too lazy to go looking for it.

Secondly, M8 now initially starts by showing a revamped main help screen containing links to, amongst other things, the What's New items. As there's no point staying up-to-date unless you understand and attempt to use the new functionality, this was my first click. Bizarrely this link is non functional, which is a real shame. Details of the new stuff can be found here instead.

The other thing that is immediately apparent from the get go is the new L&F adopted by M8. I am somewhat aesthetically ignorant, but it looks awfully OS-X Aqua-ish to me... but so does anything that uses lots of sans seriffed fonts and blue. Either way, I like the new Eclipse look. YMMV.

Some interesting new generic features to note:

But for me, the value in Eclipse is as a Java IDE and in that respect, these changes caught my eye:

Note: I've only skimmed over some of the M8 goodies. I'd suggest you go to the New Features link above and see what might be of interest to you in particular. For instance, there are a whole swag of changes to the Debugging Perspective for those people who find themselves in spending a lot of time in that neighbourhood.

As with all Eclipse 3.0 updates I've experienced so far, the software itself seems virtually bulletproof. I've never had Eclipse crash on me (something I cannot say for IntelliJ), so there is little/no risk that updating to M8 is going to leave you with an unstable IDE.

Overall, I'm liking the new features in M8, although I'd also love to see some extra refactorings built in, or a standard JSP editor rather than having to rely on plugins for what seems like such a common requirement. Also, I get the feeling M8 is a little sluggish compared to M7. It's possible the new functionality plus the new L&F is contributing to this.

Posted by Andy Marks at 08:38 PM | Comments (1)

March 22, 2004

Fighting with Local Maxima (aka Domo Arigato, Mr Robocode-o)

Many moons ago, I had run a little refactoring competition on a Friday afternoon to give my development team a bit of a heads-up on an aspect of the codebase that they hadn't seen before, and also to try and focus them on the importance of the "refactor" phase of the "red/green/refactor" TDD cycle.

The format of the competition was:

  1. A time-boxed pair-programming session (60 minutes) to refactor the class in question
  2. Determination of the winner by using Checkstyle's Cyclomatic Complexity check to determine the greatest change to the initial complexity (which had a CC level of 15!)

To my great surprise, everyone had a great time and requested similar exercises on a semi-regular basis. With this in mind, I ran a second team-building exercise this Friday just gone. This time the focus was ... robocode.

Robocode is a way cool little game engine that simulates battles between programmable tanks written in Java.

It's very easy to start from scratch and build a simple robot that can be placed into the arena to do bloody battle with other such bots. We had three pairs writing bots (namely, PCBot, MightyBot and JoshieBot) over 4 stages (between 15 and 30 minutes for each stage) with all bots being shared between competitors at the end of each stage. Using this approach, each team got a chance to evolve their bots from stage to stage, with the winner of the final stage to be declared the overall victor.

As independent BattleMiester, my role was to collect the modified bots at the end of each stage and run 10-round battles to see how the individual bots fared. Not surprisingly, each stages' bots were considerable improvements on the ones from the previous stages and the results were somewhat surprising:

Although some thought it unfair that the final round counted for everything, I was quite happy that the evolutionary approach had given the rank underdogs a chance to claim victory. I dare say another round might have seen MightyBot return to the throne, but JoshieBot made it's run when it counted. Interestingly, although JoshieBot only won a single battle (out of 30) prior to the final stage, it was almost never the first to die. Unfortunately for poor JoshieBot, it wasn't the last to die either.

The end result was that the team had a challenging and enjoyably geeky way to finish out the week (thankfullly - I haven't had any repercussions from management regarding the obviously non work-related Friday afternoon). For some of the team, it was their first experience in programming in a highly threaded environment, which took some time to come to grips with. The look of delight on the teams' faces when they first saw their bots appear in the arena and begin to do "battle" (even if their battle stategy consisted solely of spinning in a tight circle and not firing - a la JoshieBot from stage #1) was priceless. I'm hoping some of them glimpsed the beauty of the decoupling of the Robocode rendering subsystem from the bot's implementation.

Footnote: a curious MightyBot author made the humbling discovery over the weekend that all of the competition bots would have been creamed by any of the basic supplied bots that ship with Robocode. This is an indication of how the strategies evolved to match the environment: the bots were only competing against each other (hence the slightly obscure statistical reference in the title), and each stage made modifications to counter the winning strategy from the previous stage. None of the teams took an "outside the square" approach and made a revolutionary change in tactics, which might have tipped the balance of power in their favour... or not.

As they say in the classics: "in the land of the blind, the one-eyed man is king!"

p.s. I ummed and aahhed about distributing the supplied sample bots with the version of robocode I gave to the pairs. In the end, I chose not to as I wanted all the competing bots to be 100% their designs and not a "here's one someone else prepared earlier" with a different name. Using this approach, all the pairs quickly had to come to grips with the event model and API required to develop bots.

Posted by Andy Marks at 07:35 PM | Comments (0)

March 20, 2004

Review: XPlanner

As someone who has spent quite a bit of time performing the role of Iteration Manager (IM) in an Agile development team, I'm quite keen to try anything that purports to make the tedious nature of this role more lightweight. For that reason, my team is currently trialing XPlanner for an iteration to see how it stacks up against our current Excel spreadsheet-based time recording system.

XPlanner is an open source, Web-based tool for helping the planning, recording and tracking of an Agile project.

For context, here's what we currently do in Excel, along with approximate costs in time:

  1. Each day, the developers submit their hours to the IM (5 minutes/developer/day).

    Note: this usually happens the following morning for the previous day.

  2. The IM updates the spreadsheet appropriately (the spreadsheet maintains card and iteration totals) (30 minutes/day)

  3. Each day, the IM transfers a summary view of the iteration's status to our BVC (30 minutes/day)

  4. Each day, the IM sends a brief (email) status report to our off site customer. This is basically a list of work in progress cards, a list of completed cards, plus a warning flag should new cards been needed for the iteration. (15 minutes/day)

  5. Prior to each iteration's close meeting, the IM creates a few simple summaries of our actual data (i.e., cards completed, estimates versus actuals, non-project time, project non-development time, etc) and pops these into a Powerpoint presentation (60 minutes / iteration)

  6. The IM resets the spreadsheet for the next iteration (30 minutes / iteration)

Total effort / iteration (assuming 6 developers and 10 day iteration) : 21.5 hours

So to make XPlanner a viable alternative, it needs to support these tasks with less total effort than our current approach.

Installation

XPlanner is a doddle to install, requiring merely the presence of a servlet engine and RDBMS. I managed to get XPlanner, Tomcat and MySQL installed/configured on a new box in 30 minutes using the simple installation instructions. Basically, you just need to configure an appropriate datasource (a MySQL one comes pre-configured), build the WAR (using the supplled Ant task) and drop it into the deployment directory for your servlet container.

Note: to perform the installation, you'll also need a modern JVM (i.e., 1.4.1 or greater) plus a compatible version of Ant.

From there, just browse to http://<machinename>:<servlet container port>/xplanner and you should be laughing.

Setup

Once installed, it's simply a matter of creating an initial project and iteration and a bunch of user logins and Bob's your mother's brother.

A couple of initial points to note from this data initialization step:

Usage

Once the project and iteration have been created, it's down to the daily grind of adding new cards/tasks, estimating the work and updating the hours against these items.

At this point, it became clear to us that there wasn't any documentation on how to actually "use" XPlanner, and although it's bleedingly obvious the majority of the time, it did take us a little while to work out how actual hours were recorded (i.e., if you assign hours to a task for a pair, then that amount of hours appear in both the individual developers' timesheets, and the same amount is recorded against the task). As we usually record estimates already factored out to include pair time, this confused us for a while until we realized what was happening.

A few more shortcomings were revealed during the early stages of data entry:

Reporting

As you might expect, XPlanner maintains quite a nice set of Web-based charts and tables showing various views of the progress through the iteration. Individual developer timesheets are maintained - nice for removing the guesswork if you have to double enter your time against a corporate timesheeting system (or two :-)). Paired versus non-paired time can be tracked, as well as estimates versus actuals. Project versus iteration velocity is tracked, although I'm not really sure how this is done at the moment. I think we'll have a better idea of how useful these metrics are in the Iteration Close meeting.

Conclusion

I've noticed two positives that have arisen from our usage of XPlanner to date:

  1. Developers are entering their hours several times each day instead of the morning after. Although this is undoubtedly costing more time, the actuals are more likely to be accurate.

  2. Being forced to break cards into tasks has generally resulted in considerably smaller overall estimates than those given during the Iteration Kickoff Meeting. So far, these estimates have proven more accurate as well. This is a good thing.

I'll post again with the final analysis of our evaluation, but at this point I don't think we're saving enough time to warrant living with the shortcomings of XPlanner. If you have no mechanism for tracking in place at the moment, XPlanner might be useful, but the flexibility Excel currently gives us is exceeding the extra features offered by XPlanner to date.

Posted by Andy Marks at 07:05 AM | Comments (1)

March 16, 2004

Review: JUnit In Action

This review is one I wrote for my company's internal newsletter, but as I haven't signed any exclusivity deals with them, I thought I'd release it to the unwashed masses, so to spreak.

JUnit in Action is written primarily by Vincent Massol - the creator of the Cactus server-side testing framework and a contributor to both the Maven and Mock Objects projects. Not surprisingly then, the book does spend the majority of it's post-introductory chapters using these tools in the context of testing a hypothetical J2EE application. It's worth stating up front that other JUnit descendents like HttpUnit and HtmlUnit only rate a passing mention and no examples of their use are included.

I came to purchase this book after having read early versions of the chapters covering mock and stub objects several months ago. I was most impressed with these chapters and brought the book expecting more of the same quality. Whilst I wasn't disappointed with the rest of the book, I do believe that these chapters are still the most compelling and are not exceeded
by anything else in the book.

As typical of the range of "In Action" books, each chapter is thick with code examples and whilst I find this technique disrupts the flow of the text somewhat, it makes the 330+ pages a fairly quick read. The author's style is both straightforward and easily understood, making the book amenable to reading short sections at a time.

The first section of the book introduces vanilla JUnit, the philosophy behind unit testing in general and briefly mentions TDD - although more as an alternative than a mandate. This entire section (117 pages) could be skipped by anyone with any experience in JUnit unless the final chapter on integrating JUnit with Ant, Maven and Eclipse is of interest.

The second section is the highlight of the book in my opinion as it begins with the stubs and mock objects chapters mentioned earlier in this review. In addition, the Inversion of Control pattern is introduced along with some great testing philosophy including a section on test code being a "first order client" of application code that completely changed the way I viewed test design up to that point. I strongly recommend anyone who hasn't read the PDF versions of Chapter 6 (Stubs) and Chapter 7 (Mock Objects) to do so if they're in anyway unfamiliar with these topics. Finally, Cactus is introduced as a general framework for unit testing server side components and as a precursor to the next section.

The final section is dedicated to approaches to testing a typical J2EE application's components. Various techniques for testing JSPs, servlets, EJBs (session beans, entity beans and message beans) and database access code are presented using Cactus or basic JUnit and often in combination with mock object frameworks (Mock Objects and DynaMock). Along with the pragmatic "how-to" nature of this section, there are liberal inclusions of "Unit testing best practice" sidebars (throughout the book) to isolate/highlight the salient points of the current section. Whilst many of these items are bleedingly obvious, either from the accompanying text or past experience, it is an effective technique nonetheless. A collection of these annotations itself would form a useful list for any Java developer.

Across the entire book, the author's knowledge in the server-side Java testing realm is obvious and further highlighted by the many good points on test design and philosophy he intersperses with the practical examples. This information is probably the most valuable and would be very handy for people starting to put together a unit testing strategy for a new project or looking to refactor an existing application's test suite.

In conclusion, I would recommend this book for a developer first coming to Java unit testing but there is probably too much of an overview perspective to the book (understandable, given the ambitious scope covered) to make it a mandatory item for an experienced Agile developer. If you're still interested, sample Chapters 6 and 7 to see whether the level of information is right for you.

More information (including TOC and other sample chapters) can be found at http://www.manning.com/massol/.

Posted by Andy Marks at 07:11 AM | Comments (0)

March 15, 2004

A Pattern By Any Other Name Would Still Sell As Well

My current bedside table book is entitled "The Manager Pool: Patterns for Radical Leadership" and I started reading it principally because of the "patterns" reference. The book is basically a large collection of software development team management tips, each one considered a pattern and grouped into general categories: Psychological and Retentive, Behavioral and Explusive, Strategic, Tactical, Environmental. Each pattern is described simply in about 2-3 pages and is linked to other patterns where appropriate.

However, I don't intend this to become a book review - I have another point to make:

Upon reading the first couple of pages of this book I was horrified at the fast and loose interpretation of the word "pattern" used by the author. There was none of the usual decomposition of the so-called patterns into standard sections, as I was so used to from GoF, PoEAA and the like. Instead, each pattern simply had an opening statement, followed by a lengthy narrative, a short conclusion and then cross references to other patterns.

And then it dawned on me (or so I thought) - the author was appropriating the term pattern to attract a larger readership lulled by the siren call of one of the most popular memes in software development at the moment. How cunning!

However, my occupation of the high ground of moral outrage was short lived. Soon came the dawning of the second age...

It took me a while to realize that I'd been acting under the misapprehension that something wasn't a true "pattern" unless it fitted the GoF stylesheet and could be documented in respect to its background, implementation, where to use it, etc. I'd forgotten that a pattern is nothing more than a "thing" that is commonly encountered or used in a particular field.

Furthermore, patterns are (obviously) not unique to software development. They may/may not be considered best practice in a particular domain, but are usually of sufficient quality (AntiPatterns notwithstanding) that their documentation can greatly assist people in identifying common situations amenable to the patterns and applying them appropriately.

Hence, the topics covered in this book are truly patterns - irrespective of the format of their documentation. I was thusly humbled.

"And the book itself?", I hear you ask: As with most pattern type publications, everything is very much common sense (well, duh!). I usually find these books better used as reference items than texts read cover-to-cover.

Posted by Andy Marks at 07:17 AM | Comments (1)

March 14, 2004

RE assertions in JUnit

Whilst busily TDDing the other day, I found myself writing a lot of test code like:

assertTrue(foo.endsWith("bar"));

where foo and bar are both of type String.

My tests didn't care how the start of foo looked, only the end so I didn't want to make them too brittle by using assertEquals.

And here's the rub...

I really like assertEquals. The thing which raises this method above the rest of JUnit's is that a failure of one of these calls results in an instantly useful error message along the lines of "Expected 'foo' but got 'bar'". All you get when an assertTrue fails is a most unhelpful AssertionFailedError.

So, to allow me to maintain my fidelity to assertEquals whilst still keeping my tests fairly clear and loose, I came up with:

    public void assertLike(String expected, String actual) throws AssertionFailedError {
        Pattern pattern = Pattern.compile(expected, Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(actual);
        try {
            assertTrue(matcher.find());
        } catch (AssertionFailedError e) {
            throw new ComparisonFailure("RE comparison failed - ", expected, actual);
        }
    }

In short, I'm using the inbuilt JDK RE classes to provide "fuzzy" matching in assertion checks and, if a check fails, emulating an assertEquals failure to present the error in the format I like. The method can be invoked as follows:

assertLike(".bar", foo);

Using RE matching in assertion easily leads to a far richer set of string assertion methods (wrapping assertLike) along the lines of:

However, I'll leave this stuff as an exercise for the reader.

p.s. Eclipse does a really nice job of present these errors in it's JUnit plugin. I'll post a screenshot as soon as I work out how to post images to this blog.

Posted by Andy Marks at 07:24 PM | Comments (2)

It's Alive!

That's right - li'l old me has joined the ranks of the blog-infected. Not quite sure what this means for the rest of y'all, but from what I've seen, I think everything I now think is suddenly vitally important for everyone to read :-)

Thanks heaps to Jon Eaves for the pointers on Moveable Type and even more heaps to the fabulously easy installation and instructions from the MT people themselves - I tend to emulate the perfect fool when installing anything that doesn't come with a Wizard, but I managed to get this up and running in around 30 minutes, so kudos to everyone behind MT!

Posted by Andy Marks at 05:20 PM | Comments (0)