• No results found

Industry Perspective: Making Inroads in Legacy Code

In document New Programmer's Survival Manual (Page 63-67)

When getting started in a legacy project, pick some very minor thing, make a very minor change, and observe the impact. It would be nice if this legacy code base had a comprehensive suite of tests, but it won’t. Worse, it may have been designed in such a way that testing it is virtually impossible.

Adding test cases is likely to be difficult. The code will be tangled and tightly coupled, and teasing apart even a little bit of it to put into test will only put the parts into test that are relatively trivial anyway. The truly hard stuff will be very resistant to being made testable.

This is the hardest part of the battle. You have to find a place to plant your flag of progress and write a test that sanely and clearly controls the behavior of that part of the system and defend it valiantly. Once you have made one inroad, find a direction to grow that and doggedly pursue it.

—Rich Rector, engineering manager, Spectra Logic

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

13. http://apr.apache.org/

Improve Legacy Code

49

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 com-mon for building new front ends to ancient mainframe systems.

These may not be the best solutions for creating a maintain-able 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, docu-ment your change in the check-in comdocu-ments 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,14initially released in 1995, or FreeBSD,15initially released in 1993. As of this writing, both are actively developed.

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

14. http://projects.apache.org/projects/http_server.html 15. http://www.freebsd.org/

Improve Legacy Code

51

• 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,16which 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 some-thing 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?

16. http://apr.apache.org/

Tip 8

In document New Programmer's Survival Manual (Page 63-67)