Tip 7Improve Legacy Code
White Belt[​​White Belt] Maintaining and improving legacy code is a day-one reality.

Your job would (seemingly) be a lot easier if you could simply take all the crappy old code floating around, trash it, and start over. But that’s not going to happen, so what do you do about it?

The typical Godzilla legacy code base looks something like this:

  • Functions spanning thousands of lines, with a near-infinite number of possible code paths.

  • Classes or modules with dependencies on twenty (or more) other classes.

  • A comment somewhere reads, “Don’t touch this or everything will break!”

  • Another comment reads, “Ask Bob before changing this code,” where Bob is a programmer who left the company a decade ago.

  • …and much, much more.

Sometimes when you need to fix a bug in code like this, the path of least resistance—just making the change without cleaning anything up—is the most prudent path. However, consider the maxim “If you find yourself in a hole, stop digging.” If this is code you’ll need to maintain for some time, it’s best to make things better as you go.

Finding Seams

The key problem with legacy cleanup is where to start. If everything depends on everything else, how can you separate a module to work on? Let’s say you’re working on a legacy Win32 application and you’re porting it to POSIX. The system APIs are a good place to start. Perhaps start with file I/O, looking for stuff like the following:

 
HANDLE hFile;
 
 
if​ (CreateFile(hFile, GENERIC_READ, 0, 0,
 
OPEN_EXISTING, 0, 0)) ==
 
INVALID_HANDLE_VALUE) {
 
// ...error handling...
 
}

Rather than replacing 100 calls to the Win32 API with 100 POSIX calls, take the opportunity to extract file I/O to its own module. (Or, use an existing cross-platform library like Apache Portable Runtime.[13]) Implement this module for both Win32 and POSIX, because this will allow you to verify the program’s behavior on both platforms.

The practice of extracting bits of functionality is sometimes called finding the seams since you’re looking for natural places you can pull the legacy code apart. Although there may not be many seams at first, it gets better as you go. Each newly built module is modular and well-tested, thereby giving you a bigger safety net when it’s time to pull at the next level of seams.

Transition to New Platforms and Languages

The computing world never stays still, and legacy systems sometimes need to migrate just to stay functional. Perhaps it’s just porting from some ancient versions of Windows to the current version; in a more ambitious project, it could be moving a system from PCs to the Web.

Where possible, contain migration risk by reusing parts of the old program. Here’s an example:

  • If the old program is written in a common language like C, many other programming languages have an option for interfacing with C code (Java Native Interface, Ruby extensions, and so on).

  • If the old program has a network or console interface, you could build a shim layer that interacts with that by screen-scraping. You may laugh, but this is very common for building new front ends to ancient mainframe systems.

These may not be the best solutions for creating a maintainable system, but they could possibly buy you time. Consider an alternative scenario: the company’s legacy system is on a version of Windows with a thousand known security flaws, everyone is panicked about getting the system migrated now, and they’re willing to cut every corner possible. Taking an intermediate step—and buying your team the time to do the job right—suddenly doesn’t sound so bad.

Bugs vs. Misfeatures

A common task for newbie programmers is bug patrol. Lucky you. When fixing bugs in legacy code, be careful to mentally separate bugs (clearly wrong behavior) from things that are simply strange. Fixing strangeness can bite you in ways you may not anticipate.

Let’s say you’re working on a web browser, and it crashes if it tries to generate a certain HTTP header field. That sounds like an obvious bug to fix. However, while fixing that bug, you also notice that the browser creates an HTTP header labeled “Referer,” which is misspelled. Do you fix it?

In this case, no. Lots of web servers depend on that misspelling—in fact, it dates back to RFC 1945, from the mid-90s. “Fixing” that header would break all kinds of stuff.

That’s not to say you shouldn’t try to fix strangeness. Just be conscious that the code might be strange for a reason. Ask your mentor or a senior programmer. At a minimum, document your change in the check-in comments so others can find it quickly, just in case that bug was a misfeature in disguise.

Further Reading

Most programming books focus on writing new code. You can’t blame the authors or the programmers buying the books; green-field programming is certainly a lot more fun. However, there are a couple books dedicated to “brown-field” programming.

Michael Feathers’ Working Effectively with Legacy Code [Fea04] is the definitive text on dealing with legacy code. If you’re working on a big legacy project, this is the book for you.

On a more tactical level, Martin Fowler’s Refactoring: Improving the Design of Existing Code [FBBO99] is helpful for anyone maintaining code over time.

Actions

Some open source projects have a long history, yet they haven’t devolved into the spaghetti mess of traditional legacy code. Consider the Apache HTTP Server,[14] initially released in 1995, or FreeBSD,[15] initially released in 1993. As of this writing, both are actively developed.

A hallmark of both projects is their clean code base. Assuming some knowledge of C, you can pick files at random and readily understand what the code is doing. So, along those lines:

  • Download source code for one of these projects, or view code using their online source browser.

  • Observe their adherence to a single coding style and how that makes it easy to skim through pages of source code.

  • Note how they’ve abstracted common patterns into separate libraries, for example the Apache Portable Runtime,[16] which makes the core code much easier to follow.

  • Consider: these projects may be old, yet unlike legacy projects, there’s little drive to replace them with something newer. How have they managed to keep up with the times?

  • Consider: do these projects use programming techniques or standards that you could adopt in your company?

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.84.112