Thoughts on Legacy Code


The last few weeks, I’ve been giving some thought to the issue of legacy code. I was prompted to start thinking about it after stumbling across a wonderful company called Corgibytes, which is a consulting company that other companies can hire to help modernize, maintain, and clean up their existing code bases. Apart from having easily the best company mascot out there (which is the office Corgi), the company is an excellent representation of how to think about and address legacy code.

An article from firstround.com, gives a perfect summary of Corgibytes’ perspective on the issue:

“The most popular definition of legacy code comes from Michael Feathers, author of the aptly titled Working Effectively with Legacy Code: It’s code without test coverage. That’s better than what most people assume — that the term only applies only to really old, archaic systems. But neither definition goes far enough, according to Goulet [co-founder of Corgibytes]. ‘Legacy code has nothing to do with the age of the software. A two year-old app can already be in a legacy state,’ she says. ‘It’s all about how difficult that software is to improve.

This means code that isn’t written cleanly, that lacks explanation, that contains zero artifacts of your ideas and decision-making processes. A unit test is one type of artifact, but so is any documentation of the rationale and reasoning used to create that code. If there’s no way to tell what the developer was thinking when you go to improve it — that’s legacy code.”

The point here is that if you don’t have artifacts about the rationale in a piece of code, it’s already legacy code. If you don’t understand what you’re writing, you’re introducing immediate legacy code. There needs to be insight into your rationale; otherwise, it’s already black box code and therefore should be considered immediate legacy code. In other words, it’s not sufficient to just gives lip service to maintainability by writing flimsy and esoteric unit tests, you need to actual understand your codebase and codify that understanding in the form of documentation that can be referenced later when you need to improve upon your past designs.


Thinking about legacy code brings up immediate memories of the last company I worked for. I was on a newly created team within a larger organization. The team I was on was literally brand new. I was one of five in-house engineers, three of which were Senior Devs pulled from elsewhere in the organization and two of which were newer Junior Devs, including myself. We were led by a engineering manager, who had also joined the team about a month after I joined.

Joining a team like this at its infancy seems like a great opportunity to start fresh, to start things off on a good foot. The problem was, however, that we didn’t inherit a clean slate. We inherited projects that were created by a mishmash of internal developers from other teams and contractors from outside of our company. To make matters worse, the company I worked for had a really high turnover rate, and the vast majority of the developers who worked on the projects we inherited were no longer employed at the company. The same was true of the contractors who had worked on the project. Their contracts had either ended or they were located in some other part of the world and didn’t have schedules that aligned with ours.

So, when we inherited these projects, we didn’t have anyone to talk to about the rationale behind their code. These developers left us very minimal documentation about what did what. We didn’t know who did what or why they did it in the first place. It was, by all measures, a nightmare scenario for a development team.

To add insult to injury, as we were groping around in the dark with these inherited codebases, the company was simultaneously making efforts to hire agile consultants to somehow instill better agile practices within our teams. We had meeting after meeting with these consultants where they tried to teach us how to be more agile, communicate more effectively, and work better as a team. On random days, these consultants even popped into our daily standup meetings or organizational level meetings. It seemed like they were becoming more and more ubiquitous throughout the company as a whole.

These consultants spoke in platitudes and made vague statements. They never asked specific questions about our particular team scenario or made any specific recommendations. They just kept spouting the “joys of agility.” But, the real irony in all this was that, while this was happening, no one within the organization actually made any attempts to communicate why these consultants were here or what they were actually supposed to be achieving. And, no one addressed our lack of information about what the hell our codebases actually did.

It was frustrating at the time to watch this all go down at my company, but now I can appreciate the lessons being learned from observing all this. For one, I learned that the company I worked for had completely missed the real problem within the tech organization. What we really needed instead of fancy consultants was simply some clarity on what our tech did. We needed better documentation and needed to address the “legacy state of our code.” The company was focused on trying to improve everything, but we couldn’t improve what we first didn’t understand. We paid lip service to improving processes and implementing newer technologies within our codebases, but we had no way of actually making that happen because we didn’t first address our legacy code.

Moral of the story, paying attention to legacy code leads to better results than paying attention to fancy consultants.

References:

https://review.firstround.com/forget-technical-debt-heres-how-to-build-technical-wealth

Print Friendly, PDF & Email

Leave a Reply

Your email address will not be published. Required fields are marked *