Stop Waiting For Green Fields

July 5, 2012

There’s a skill that I’ve rarely seen among recent college grads walking into enterprise codebases, and that’s maintaining legacy code. It must be shocking to expect to walk off campus and on to a green field project, only to be met with a “where the hell did these 1.5 million lines of code come from?” sentiment. I’ve observed three particularly difficult challenges that less-experienced engineers face when working with legacy codebases: rapid understanding, adapting design, and finally, implementing bug-free modifications.

Rapid understanding seems intuitive, but is actually quite difficult. Even with a masterful understanding of whatever language(s) the codebase happens to be written in — and not to downplay this, that helps tremendously — it can still be extremely difficult to actually understand what some lines of code are accomplishing in an unfamiliar domain. Almost always what ends up being most difficult to understand were the intentions behind the code. Of course, you had an initial requirement to make a change that lead you to explore this part of the code to begin with, and you likely came up with an idea of how you thought existing functionality would work, and what type of change you needed to make. After rapidly understanding the code that’s actually there, you’ll likely find that you made some incorrect assumptions. Now it’s time to adapt your design to fit within the constraints of the code that’s actually there. Alternatively, you could try to adapt the existing code to facilitate your optimal design, but this can be difficult in codebases that aren’t cooperative.

Finally, the actual implementation can seem easy, until it’s caveated with “bug-free”. An all-too-common post-mortem of code changes in legacy systems is counting the ways it broke pre-existing functionality, sometimes in the most obscure, non-obvious ways. Unfortunately, I’m not aware of an awesome, immediate fix to this problem. It usually requires invasive testing of legacy components, and potentially risky refactors — reducing the risk of which can be exceedingly difficult. However, as for the code you’ll be writing, test-driven development and pair programming are essential to bug-free modifications. We’ll talk more about reducing the risk of legacy refactors next.


John is a serial conversationalist who spends entirely too much time engulfed in problem domains he knows nothing about and has no earthly business trying to learn. He can occasionally be found at your local coffee shop writing algorithms and trying to think deep thoughts.