Thursday, May 13, 2004

Conversation Is Not Understanding Either!

I have been as guilty as the next geek of rationalising my distaste at the tedium of documentation. Many of my agile friends and colleagues are fond of saying that 'Documentation is Not Understanding' when promoting the 'people over process' bit of the Agile Manifesto. Now while I do indeed hold this truth to be self-evident, a few recent experiences find me not so dismissive of the value of documentation as once I was.

Circumstances led me to leave my role in a nice fun agile project for a few months. When I returned, I struggled to get back up to speed for a couple of weeks - these agile folks will just go and change things while you're not looking :) When trying to reconstruct my mental model of the project, I found the pieces I had to put together out of conversations with analysts, customers and developers didn't always fit together snugly, and I found myself needing some sort of point of reference that was indeed shared understanding to work forward from. Anyway, I haven't really worked out what this means, but I have to conclude that while documentation is not understanding, neither is conversation. Another assumption bites the dust!



Monday, April 12, 2004

The Need for Speed

At the Melbourne eXtreme Programming Enthusiasts Group the other night we had a big rantorama about TDD. One of the points in my presentation was that Kent had said that unit tests had to be fast, and he cited one project in which there were 4,000 tests that ran in about 20 minutes. A few guys from my team were there and guffawed out loud. Our current project (4 months old) has 1,300 unit tests that run in about 10 seconds, so they weren't impressed with Kent's numbers at all. Even allowing for Moore's law over a few years, we'd run about 4,000 tests in 30 seconds, which two speed-doublings ago would take 2 minutes. That's still an order of magnitude faster...so what's the deal?

This led to lots of enthusiastic debate about what the hell a unit test actually is. For what it's worth, here's my simplistic test categorization model:

1. A unit test is a test that requires only the class under test and its immediate dependencies (or mocks thereof). This means no deployment, no packaging, nothing. That's why they're fast.

2. A functional test is a test you can't run until the app is packaged and deployed in some way. So you "in-container unit test" fans aren't doing unit tests by this model. I'm hard on this stuff because anything requiring deployment puts you in a different order of magnitude speed wise; this doesn't mean these tests aren't valuable, just that I don't count them as _unit_ tests, even if they only test a single unit of functionality.

3. An integration test is a test of your external dependencies, not necessarily requiring your app to be deployed at all, but requiring your external dependencies to be available. This is where databases come in, or other services provided by EJB's or anything else. These tests are also usually way too slow for me to want too many of them, and I want to isolate them from my app as much as possible. This means a separate test harness for the external stuff and leave my app just unit testing against the assumptions proven by the integration test suite.

The point is that I want to push unit tests as far as I can because they just provide so much more performance than the other types of tests. That's the only reason. I want as few of the others as possible because I spend enough of my life waiting for computers to get done with stuff as it is. Yes, you _can_ unit test custom tags to within an inch of 100% coverage!

So what's everyone else getting speed-wise???



Saturday, March 20, 2004

Become what you despise

A lot of agile/TDD/XP folks like me enjoy flouting a very public disdain for "whiteboard architects" and their ilk. These are the ones who haven't written a line of code in ten years or more, serve out voluntary life sentences in financial institutions and impose design decisions from on high while ignoring development teams entirely. They never ask for feedback on their architecture from anyone who sits beneath them on the org chart, as what feedback of value could a lowly code-cutter have? They are far too busy seeking feedback from those _above_ them on the org chart to make sure their career ambitions are on track, and that's a full time job.

So how happy was I when Jon broke his arm and I was pulled off my nice little agile dev lead role and into a six week whiteboard wonderland? Hmmm. In a nutshell, this gig involves designing a technical solution to coordinate half a dozen systems on four different platforms written in four different languages, integrating .NET with J2EE, a rules engine, messaging systems, mainframe yuk galore, blah, blah, snore.  The system will be used by thousands of people every day and carry billions of dollars of business every year  Textbook whitebook architect turf. Oh, and you've got three weeks to get your head around it and come up with a solution and another couple of weeks to write it up and get it approved by the Big Guys Upstairs. No coding for you!  Well, it's been an interesting and enlightening experience - always a good thing. I hope I haven't become what I despise, but perhaps I despise them a little less by understanding them a little more.

Lesson: Same shit, different abstraction

So why is it that we who prefer to spend our time at the implementation coalface smirk at the whiteboard architects? I have noticed during this brief out-of-body experience that one reason is the same as why we smirk at some of our less-than-breathtaking code-cutting colleagues. They can't design to save themselves. Just as many developers solve the wrong problem and can't distinguish between an implementation abstraction and a design abstraction (Dude, don't call it a SQLDataSource if it's role is a DomainStore!), it seems the same mistakes happen at the higher level of abstraction where enterprise architects play. Some of them seem compelled to define the implementations of the solution to the problem instead of just defining the problem, assigning responsibilities to well-nhamed abstractions (SOA, anyone?) and admitting that in the time available they don't have a hope in hell of telling a development team how they should actually build the thing. I can forgive them their transgressions against developers because it's not just them. We do it too. And so do business people. How often have you been given a so called 'requirement' that is not a statement of a problem at all but a statement of a dumbass solution? It has surprised me how well design concepts I'm used to using at the class/interface/component level map to the system/service level.

On this gig I've met one particularly outstanding guy who's an enterprise architect on a parallel project, and I just know he would be a kickass code cutter as well; he must just prefer to get paid properly. So take heart, you too might get lucky and find a whiteboard architect whose pictures deserve to make it off the drawing board!

 



Sunday, March 7, 2004

Getting into the Swing of TDD

Just came off a tough late night/early morning pairing session with Simon Harris. We're working on a Swing app that will let you wander around the duplication in your code base by reading a Simian log file and referring to the original code tree. We're also trying an experiment where we use TDD and blog the experience so that we can publish the gory details of the construction of the app, on the presumption that anyone cares, of course...:P

Last night's session will make for interesting reading, mainly because we're both pretty clueless about Swing. In keeping with Jon Eaves ideas on spiking and TDD, we mucked around for a while trying to figure out how to use the java.awt.Robot to drive our panels, but we got there in the end. What we are trying to explore is how far we can push TDD, and I, for one, am so sick of web apps that this seemed like a cool idea.

I don't know enough about Swing to understand why a lot of folks seem to hate it these days, but it's always appealed to me as having the potential to facilitate real unit testing. By this I mean that a UI area composed of multiple JPanels should be able to have independently designed and tested each of those panels before assembling the UI and running functional tests over it.

The theory goes something like this:

  • you don't have to write tests for one line delegation methods in my book. So if the UI was a veneer so thin over a fully tested set of non-Swing stuff, I'm happy to just glue the UI onto the layer below with trivial delegation. This is the interesting part - how thin can the UI layer be? So thin that no testing is required?
  • you use a Mediator to coordinate the interaction between panels (which you of course make an interface so you can easymock it for testing), and each panel implements a Colleague interface (again facilitates testing). This means that although there is 2-way comms between the mediator and the colleagues, either end of this pipe can be mocked, allowing testing of each bit independently.
  • you then assemble your UI like any other swing UI and the bits play nice.

We had previously gotten our mediator TDD-ed into existence and were happy with it. We then came to creating the JPanel that contains a list of files that share some duplicated code. This panel was also TDD-ed into existence but with all its behaviour in non-Swing methods. All good. Then it came time to (we thought) just add the JList and off we go. Turns out the amount of code required, with event listeners and a private inner ListModel class left us facing the dreaded NullPointerException at run time. If there is a more glaring signal that your code is crap, I don't know it.

So we came to the conclusion that we would have to actually unit test the UI with events somehow, you know, mouse and keyboard stuff. Yuk. We mucked around for a while trying to figure out how to do this while keeping the test 'headless', but failed dismally. In the end we came to grips with the pixel coordinate stuff required by Robot and plonked our little panel into a JFrame of its own in the unit test and just displayed it and started the Robot clicking on stuff.

So the upshot was that a single panel pops up on the screen and dances about a bit being unit tested against a mock Mediator that catches and verifies the panel's interactions with the rest of the dialog that isn't even there yet. Long story, I know, but I thought it was kinda fun and my blog's been a bit quiet lately.



Wednesday, February 11, 2004

Just what the world needs

Just what the world needs - another ThoughtWorker bleating on about test-driven development. Sheesh!