I’m using the term “legacy code” quite a lot, what do I mean by it? I like most the R. C. Martin’s description in his foreword to the Michael Feathers’ book Working Effectively with Legacy Code:
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.
M. Feathers himself first repeates a common definition:
Legacy code is code that we’ve gotten from someone else.
He then acknowledges that in programmer’s mind the term legacy code means much more, something that has nothing to do with who wrote it:
If you are at all like me, you think of tangled, unintelligible structure, code that you have to change but don’t really understand. You think of sleepless nights trying to add in features that should be easy to add, and you think of demoralization, the sense that everyone on the team is so sick of a code base that it seems beyond care, the sort of code that you just wish would die. Part of you feels bad for even thinking about making it better. It seems unworthy of your efforts.
In summary, legacy code is “used as a slang term for difficult-to-change code that we don’t understand.” But M. Feathers somes up with a different definition he’s arrived to over the years:
To me, legacy code is simply code without tests.
He justifies his definition by explaining:
Code without tests is bad code. It doesn’t matter how well written it is; it doesn’t matter how pretty or object-oriented or well-encapsulated it is. With tests, we can change the behavior of our code quickly and verifiably. Without them, we really don’t know if our code is getting better or worse.
I pretty much agree with all the descriptions and definitions. We could expand them a lot, talk about dependencies, insufficient abstractions etc., but I think that though not very scientific, the descriptions express very well what we mean by legacy code and Mike provides us with a very simple and easily verifiable definition.