Stories about Software


So, You’ve Inherited a Legacy Codebase

Editorial Note: I originally wrote this post for the SubMain blog.  You can check out the original here, at their site.  While you’re there, have a look around at some of the other posts and sign up for the feed.

During my younger days, I worked for a company that made a habit of strategic acquisition.  They didn’t participate in Time Warner style mergers, but periodically they would purchase a smaller competitor or a related product.  And on more than one occasion, I inherited the lead role for the assimilating software from one of these organizations.  Lucky me, right?

If I think in terms of how to describe this to someone, a plumbing analogy comes to mind.  Over the years, I have learned enough about plumbing to handle most tasks myself.  And this has exposed me to the irony of discovering a small leak in a fitting plugged by grit or debris.  I find this ironic because two wrongs make a right.  A dirty, leaky fitting reaches sub-optimal equilibrium and you spring a leak when you clean it.

Legacy codebases have this issue as well.  You inherit some acquired codebase, fix a tiny bug, and suddenly the defect flood gates open.  And then you realize the perilousness of your situation.

While you might not have come by it in the same way that I did, I imagine you can relate.  At some point or another, just about every developer has been thrust into supporting some creaky codebase.  How should you handle this?

Read More


Learning a Healthy Fear of Legacy Code

Editorial Note: I originally wrote this post for the SmartBear blog.  Check out the original here, at their site.  While you’re at it, have a look around at some of the other authors posting there as well.

The life of a developer would be pretty much nothing but rainbows and unicorns if all we did was add new code to code bases. Imagine a world without maintenance programming, debugging, and scratching your head while squinting at confusing, existing code. It’d be pretty nice, right?

Unicorn with Rainbow

Sadly, we don’t live in that world. The result is that most of our efforts in software development involve a blend of new and old code. We write some new code, stuff it into some existing code, and then try to figure out how the two things will behave together in production. Consequently, both writing and reviewing code necessarily involve a kind of constant, subconscious risk management. “Hmm… should we really touch this code?”

There’s rarely a set of explicit heuristics that guide this decision; it tends to be a matter of feel. It’d be nice if there were a way to be a bit more deliberate about it.

Understanding Legacy Code

“Legacy code” is a rather nebulous term.  Even the wikipedia entry offers multiple, possible meanings.

  • Code that relates to a no-longer supported hardware or software dependency.
  • Code inherited from someone else.
  • Code that’s part of an older version of the software.
  • Code that isn’t covered by automated unit tests.

When I think about what pops into my head when someone says, “legacy code,” none of these things would surprise me.  I could imagine any or all of them being true.  But for me, legacy code really translates to, “code you’re afraid to touch.”

Read More


Dealing with Legacy Code for Developers: Managing your Manager

Editorial note: I originally wrote this post for the NDepend blog.  Click here to check out the original, on their site.  While you’re there, take a look around at the other posts and the offering.

Here’s a campfire horror story of legacy code that probably sounds at least somewhat familiar.

One day, your manager strolls by casually, sipping a cup of coffee, and drops a grenade in your lap.  “Do you think we can add an extra field to the customer information form?”  Sure, it may sound innocuous to an outsider, but you know better.

The customer information form is supported by something written almost a decade ago, by a developer long departed.  Getting that data out of the database and onto the form prominently features a 60,000 line class called DataRepositoryManagerHelper and it also makes use of a gigantic XML file with odd spacing and no schema.  Trying to add a field to that form casts you as Odysseus, navigating between Scylla and Charybdis.  In fact, you’re pretty sure that author of the legacy code made it necessary for the assigned developer to cut off and sacrifice a finger to get it working.


Aware of all of this, you look at your manager with a mix of incredulity and horror, telling her that you’ll need at least 6 weeks to do this.  Already swirling around your mind is the dilemma between refactoring strategically where you can and running exhaustive manual testing for every character of the source code and XML that you change.  It’s now her turn to look incredulous and she says, “I’m just asking for a new field one one form.”  You’ve told her before about this, and she’s clearly forgotten.  You’re frustrated, but can you really blame her?  After all, it does sound a little crazy.

The Nature of Legacy Code

I’ve talked in the past about legacy code as code that developers are afraid to touch (which I correlate closely with Michael Feathers’ definition as “code without tests”).  If you accept this definition as axiomatic, there’s a critical implication here: legacy code creates a disconnect between the developers and everyone else.

As “everyone else” you see a form that needs a conceptually simple tweak.  As a developer, you see a mythological monster that threatens to rip your digits from your body; you see something that inspires fear.  And, while the bodily fear I’m referring to is an exaggeration, the visceral fear of unknown and lack of understanding is not.  Management is asking you to do something it thinks of as simple, and your head is flooded with an overwhelming number of possibilities as to how this could all go quite wrong.  And, worst of all, it’s really hard to explain this without it sounding as though you’re making excuses, being lazy, or being melodramatic.

If you want to understand how to manage expectations around the legacy code in your codebase, understanding this expectation mismatch is critical.  From that starting point, let’s look at some things you can do to make your life easier.

Read More


A Manager’s Guide to Legacy Code

Editorial Note: I originally wrote this post for the NDepend blog.  Go check out the original here, at their site.  If you like posts about static analysis, code quality, and architecture, head on over and check it out.

If you have a sadistic streak and manage a team of software developers, it’s probably high entertainment to dredge up some old, dusty piece of software and then to task them with maintaining it.  If, on the other hand, you’re a normal human being and you’re asking this because it’s necessary for your business, you brace yourself.  After all, this is legacy software, and the reaction of the team is likely to be quite predictable.

Alright, let’s take a look at this thing.  Oh, man, look at that right there.  A global variable.  And — oh my god — there are dozens of these things.  Who even wrote this?  And, look at this over here.  That’s the kind of idiotic, backward code that we used to have to write 20 years and 6 language versions ago when this code was current.  But even when it was current, this code was horrible.  This was obviously written by a trained ape.

When you’re a developer, the only thing worse and more contemptible than the uninformed code you wrote years ago, is the code that someone else wrote years ago.  Not only is it alien to you in makeup and reasoning, this legacy code also features patterns that have gone out of date or even been forgotten.


But lest you, as a manager, assume that this is simply a matter of developers being prima donnas, consider that an encounter with legacy code bother developers precisely because it renders them less effective.  They’re professionals, wanting to do good work, and the lead balloon you’ve dropped in their lap is an impediment to that.

Read More


Why You Should Do Periodic Reviews of Legacy Code

Editorial Note: I originally wrote this post for the SmartBear blog.  Go take a look at the original here, at their site.  If you like posts about collaboration, code review, and other topics, take a look around while you’re there.

Legacy code is sort of like your house’s storage crawlspace.  It tends to be a repository for things that mattered to you in days past or on special occasions.  The code sits there, largely unnoticed, until such time as an odd change or a production bug causes you to dig it up, dust it off, and revisit it.  Barring extraordinary circumstances, it tends to sit, largely forgotten, and possibly rotting or getting riddled with moth holes.

By and large, this considered an acceptable and even desirable state of affairs in our industry.  A lot of folks that manage software development efforts and hold the purse strings think of software construction the way they think of building construction.  Once you’ve built a house, it’s done.  Why would you go back and revisit it unless there was some kind of problem that had cropped up?  The problem with this well-intentioned, bottom-line thinking is that building software isn’t much like building houses.

When you build software, you stack the new atop the old and everything comes along for the ride.  Sure, there may be the occasional new module that stands all by itself or plugs in with the rest, but that’s the exception.  The new code interacts with the old stuff, calling into it, relying on it, and running beside it in production.  If housing construction worked this way, a short circuit in the house across the street might cause your shower to stop working.

The result is that, however well-intentioned someone encouraging you not to focus on legacy code might be, the edict is often misguided.  If the short circuit across the street meant you couldn’t shower, would you listen to someone who told you their wiring was none of your business?  Clearly, you wouldn’t go storming over there out of nowhere, remodeling that house, but you wouldn’t just ignore it either.


This is the approach required with legacy code in your code base.  The fact that someone typed it out years ago doesn’t mean that it doesn’t have a very real, current impact on your team every time you deploy your code.  Because of this, it behooves you to review it occasionally, when time permits.

Let’s examine some specifics as to why it makes sense to audit your legacy code from time to time.  Having your finger on the pulse of everything going into production is a compelling but abstract argument.  So, let’s get more concrete.

Read More