[ale] Wandering [further] into the OT tar pit

Joe Knapka jknapka at kneuro.net
Tue Mar 14 11:59:40 EST 2006


Mills, John M. wrote:

> We probably all have favorite 'war stories' about projects gone wrong. I
> keep telling myself, "Design first, code later" but I am too easily
> tempted to just start typing.

OK. Here's a war story about a project gone right. It may
sound like hyperbole, but it is not.

My employer had an old app that performed a particular task
related to administration of remote devices.  That app was
about 300K LOC (Java 1.2), had a bulky UML design model,
supported three different kinds of remote device (though
support for one of those was broken) and took about four
man-years to develop. I was not involved in that effort.

Last December, I decided to replace that app. I'd just read
"Extreme Programming Explained" (Beck) and "Better, Faster,
Lighter Java" (Tate & Gehtland), and I'd also been hanging
around on comp.lang.forth (which group has an almost
fanatical devotion to the concept of simplicity in
software).

While I was quite familiar with the domain, I did literally
*no* up-front planning. I sat down, wrote a unit test that
exercised an interface that I decided I needed, and then
wrote code until that all worked. Lather, rinse, repeat.
In two weeks, I got a good way down the re-implementation
road - far enough that by mid-January I had convinced
all the relevant folks that this thing was going to
be way better than the original app. By April I
and a couple of other developers had re-implemented all
the core functionality of the original app, *and* supported
5 varieties of remote device that weren't supported by the
old app -- and we did it in *45K LOC* (Java 1.5, this time,
which probably contributed somewhat to the reduction in
code volume -- but not *that* much).

The components we wrote were almost trivial, because
trivial code is a lot easier to unit-test. But they
turned out to be a lot more flexible then the code in
the original app, for a number of reasons. Mainly,
I think, it has to do with dependency management --
when you write test cases first, you end up building
components that can be easily tested, which implies
the absolute minimum of external dependencies. You
wire things together at a higher level (in this case,
within the UI code), but you can be dead certain that
the lower-level pieces *work*. And since they have
minimal dependencies, you can use them in ways you
hadn't originally anticipated. And since you have
automated tests in place, you can freely change things,
knowing that anything that breaks will be immediately
obvious. This strategy has worked fantastically well
for us.

I've also gone the route where I produced a comprehensive
design and then wrote code to implement it (for a different
product). That approach worked, but the design documents
were obsolete within about a week of starting the code, and
they never got maintained, because I never had time to do
it. And because I "knew" where I was going when I started
coding, I didn't think as much about testing and dependency
management. We're actually still using the result of that
development effort, but I'd throw it all away and do it
the "Extreme" way if I had the chance.

At this point, I'd much rather have clean code that people
can understand on its own merits. Software evolves in ways
we can't predict, so we may as well be prepared for it.
The code *is* the design.

Cheers,

-- JK




More information about the Ale mailing list