Do You Write Legacy Code?

by Ville Laurikari on Wednesday, September 8, 2010

In his foreword to Working Effectively with Legacy Code by Michael C. Feathers, Robert C. Martin says:

Legacy code. The phrase strikes disgust in the hearts of programmers. It conjures images of slogging through a murky swamp of tangled undergrowth with leaches beneath and stinging flies above. It conjures odors of murk, slime, stagnancy, and offal. Although our first joy of programming may have been intense, the misery of dealing with legacy code is often sufficient to extinguish that flame.

Dilbert.com

Besides serving as inspiration for poetic descriptions of wetlands and humorous sequences of drawings, legacy code is also something you don’t want in your Emacs. But how can you prevent it from getting there? At what point does code turn from “perfectly good” or at least “I guess it’s OK” into “legacy crap”? We need to define what “legacy code” is.

Many people will characterize legacy code as simply old, but that’s not a very practical definition. Good code doesn’t turn into legacy code on a rainy Tuesday afternoon at 2:17pm. A better definition gives us some clues on how to prevent code from becoming legacy code. You can’t stop time.

Perhaps legacy code is a feeling. It’s the feeling that the code is too hard to approach, risky to change, and difficult to understand. This makes for a slightly better definition, because it suggests some things to avoid (don’t write crappy code, duh!). However, basing a definition like this on feelings is a bit… scary.

In the book, Feathers gives a very simple definition:

To me, legacy code is simply code without tests.

This is a pretty good definition. Tests make the code simpler to approach, less risky to modify, and easier to understand. Tests protect against the very things that make legacy code legacy.

With this definition, we arrive at a shocking realization: someone in your team could be writing legacy code right now.

Do you write legacy code?

Related posts:

  1. Why Write Code When You Can Remove Some?

If you liked this, click here to receive new posts in a reader.
You should also follow me on Twitter here.

4 Tweets

Leave a Comment

{ 14 comments… read them below or add one }

Susanna Kaukinen September 8, 2010 at 15:52

I have the book and it won’t help you much unless you’re using a language like Java. For older (legacy ;-)) languages it’s rather useless, because almost all advice is based on the assumption that you’re using an object oriented language.

Ville Laurikari September 8, 2010 at 16:47

Yeah, the book is very much about object oriented languages. There is a chapter in the book discussing procedural languages. You can use the linker and preprocessor to do some things. Feathers recommends moving legacy C code towards C++.

Arttu September 8, 2010 at 18:42

In the middle of your post I was thinking the point of missing tests, maybe because of I’m currently reading Growing Object Oriented Software, Guided by Tests. Good post. I don’t have much experience with legacy code(yet) but I remember I once ran into a very long method with a javadoc comment “This one is a tricky bastard”. That day at work wasn’t one of the best.

Peter Hickman September 8, 2010 at 18:45

Legacy code is code written in a different style. I wouldn’t call myself an OO programmer but I have used it for so long now I have real difficulty handling procedural programming. Even if I wrote the code myself.

I used to understand it but I can no longer get into the groove, therefore it is difficult.

It is the same with testing, testing these days assumes a coding style that was uncommon in the past so testing the code in the modern style hurts. Can you remember how you tested your COBOL programs written in the late 70s or your VAX Basic programs in the 80s?

Legacy == ‘old fashioned way of doing things’

Aleksey September 8, 2010 at 19:18

So, if someone’ll write tests for some ancient spahgetti code — will that code suddenly become “non-legacy”? Sorry, but I doubt so.

Susanna Kaukinen September 8, 2010 at 19:52

Some of the legacy code that I’ve seen has the exact opposite thinking as OO. You don’t do things once for one object, but rather you do all same kinds of things at once, in “stages”.

Let’s assume that you had objects that opened a file in constructor and closed that file in destructor. If you had a lot of objects, they would all take care of their own files in a contained way.

The “stages” thinking would have you first open all files, then do all the things for the files you want and then you would close all files. It’s like having three stages or phases of initialization, manipulation and clean-up. But it’s not on the object level, it’s on the global.

It is possible to group things differently than in OO, but I might want to add that doing so can make an OO programmer have quite a few WTF:s per line. The lack of encapsulation can sometimes make figuring out all the interactions needlessly difficult.

Then again, there may very well be problem areas where one or the other approach fits better. Personally I’m also more comfortable w/the OO approach, but wouldn’t go as far to say it’s the silver bullet. Great programmers can probably understand and exploit both ways of thinking.

As a side-note, I think the best thing I got out of the book w/o having really read it was the idea that testability should always be a design requirement for a system. I think that is a fundamental idea that one overlooks at her own peril.

Ville Laurikari September 8, 2010 at 21:58

@Susanna, I’ve used the something resembling the “stages” pattern mostly as a strategy to parallelize my code. Each stage can run in a separate thread/process, and data flows through the stages. The code was fully OO, though, so not really what you meant.

Testability (on all levels) should definitely be a design requirement from the get-go. Doing it afterwards can be a nightmare.

Cees Timmerman November 24, 2011 at 18:07

“Legacy code is simply code without tests.”

Tests can be like redundant newbie comments such as “// Add 1 to a.”, but i do love that tests should ensure that functions can actually be used from different places and don’t have too many side effects.

Michel Billard September 27, 2012 at 05:53

In my experience, legacy code is code that used to be normal, but was put into maintenance mode where fixes needed to be “quick-n-dirty”. There was not much time allotted to do a proper fix and with each such fix, the code became legacy code.

Hrish November 20, 2013 at 08:28

Off-topic, but why don’t you start updating this blog again?

Ville Laurikari December 5, 2013 at 09:18

I don’t have the time right now, or more accurately, I choose to spend my time on other things. Maybe some day.

{ 2 trackbacks }

Additional comments powered by BackType

Previous post: