Ask programmers and managers, “What's legacy code?” and
you'll get different answers. Common answers include
“code that's hard to work with,” “code lacking automated
test coverage,” “someone else's code,” and “I know it
when I see it.”
However they define legacy code, everybody agrees that
they don't like it. It makes system maintenance harder,
more specialized, and slower. Programming around legacy
code is scary, because you don't know what you break and
you don't know how much to retest. It invalidates
estimates for new development. Such code might well be an
asset to your organization, but it weighs ever more on
the liability side of the ledger.
Now let's say you adopt Agile principles. You allow
changes to the requirements. The time from making a
change request to deploying it is shorter than it used to be. Team members
allow themselves to work on any part of the codebase.
Are you comfortable with this approach? If you believe
that solid code can only result from experts working from
thought-out specs and designs, this agile approach might
look like a disaster waiting to happen.
Sure enough, that's exactly what happens in many Agile shops,
but they don't notice the disaster happening because it's
in slow motion. Some folks mistakenly equate Agile with
no design and no long-term thinking. Others would like to
do design, but say that short iterations force them to forgo it. Project schedules are always tight and
“aggressive”, so there's never time to go back and
improve matters. All those folks still produce legacy
code, only faster.
Some Agile teams counter this tendency by still doing
architecture and design the old way: before any code is
written. They have to know most of the system's contents
ahead of time, and they account for everything.
Invariably, this approach stifles change and protracts
schedules, causing even more rushing at the end.
Agile teams have one overarching purpose: deliver
customer value. That purpose has a secondary clause: “do
so while setting up for delivering value in the next
round.” In other words, they produce code now that does
not compromise their future ability to produce more code.
This does not mean making the code so generic it can
handle every eventuality; it does mean making it simple
and pliable so it can be adapted at low cost.
This is where the approach of doing architecture and
design ahead of time breaks down. It might solve this
project's needs (while stifling change and protracting
schedules), but it doesn't help the team to set up for
the next project.
Empirical proof of this is everywhere. If you've ever
“re-architected” a system (that's usually around version
3 or 4), or worked on a system that included two or three
frameworks that have the same purpose, you'd know
first-hand that early designs couldn't accurately tell
So, what's the solution? How to avoid producing instant
The answer is to integrate an appropriate technical
discipline. Just like the project management side of
Agile, technical Agility is built around evolution and
small, safe steps. Specifically:
- When you're working on a small iteration story, write
simple, minimal code. Make sure its design sits well with
existing architecture, or even furthers it. That's TDD
(test-driven development) with continuous refactoring.
- When you need to keep developing but the design “gets
stuck” (doesn't readily support the next addition), adapt
the design before proceeding. That's known as
- Break down your work into small steps. And then break
them down into even smaller steps, so you're not tempted
to do Big Design.
- Automated low-level tests are your friends. Have plenty
of friends (even if some are being difficult), and take
good care of them.
- Get quick feedback from your code, team, users, tests,
and environment. Don't sit on that feedback; apply it
forthwith, including making required design improvements.
- If you find yourself producing instant legacy code —
cryptic, spaghetti, don't-touch-it, the kind you won't
understand next month — STOP. Step away from that code!
Think carefully, and correct it NOW. Don't wait to pay
for its shortcomings when you can least afford to.
These technical disciplines imply that you're not just
developing every day; you're investing in your code
every day. That's how you curtail legacy and prevent your
asset — your code — from turning into a liability.
September 2014 update: If some of your team members could benefit from learning how exactly to do all that, Gil is available for mentoring and coaching. As well, there is still room in his Agile Engineering practical course in Boston.
Information and registration for the workshop.
Copyright © 2011-2016, 3P Vantage, Inc. All rights reserved.