The words "legacy code" strike fear into the hearts of developers everywhere.
Behind that fear, legacy code means it's slow to understand existing behavior, slow to fix bugs, slow to develop features, and slow to gather confidence that I haven't broken some seemingly unrelated thing.
And I hate slow. Slow means risky. Slow means expensive. Slow means trust-eroding.
For a business, though, which do you think is more painful: projects that have been operating in production for years, or greenfield projects that have yet to prove their value in the marketplace? Not every business has the same answer here, which is fine, but I think it's interesting to consider what I can do to avoid or at least reduce these kinds of negative responses for codebases that have proven valuable over time.
For the purposes of this discussion, legacy code is code that you inherit from somebody else. If the codebase is large, or it's been a while since you looked at it, that "somebody else" might even be yourself from the past.
Acknowledging our feelings, and the difficulties that legacy code presents, allows and motivates us to make improvements that enable progress. Ask yourself these questions, and answer as honestly as possible. Notice when you're censoring yourself or answering based on what you think you should feel.
Inheriting a Legacy
How did you feel the last time you inherited a project where there was already code in place?
Do you know why the previous developers made the decisions they made?
Did you run the tests? How did it make you feel when they passed (or failed)?
What did you think when you found a bug? Whose fault was it?
How long did it take you to fully understand the most important concepts in the system? How could you speed that up?
How long did the original developers think this code would live? Were they right?
Do the abstractions help you add features more easily than if everything was concrete?
When you see a TODO or FIXME, who's responsible for making it TODONE or FIXED? Is it you? How does that make you feel?
Leaving a Legacy
How do you feel about the code you've written on the project you're working on right now?
Do you communicate the reasoning for the changes you're making, in your code and commits?
When you make a change, how do you gain confidence that things haven't broken?
Are there any known bugs? Who is responsible for fixing them?
How long should it take someone to fully understand the most important concepts in the system? How could you trim that time down?
How long do you think this code will live?
Where you have abstractions, are they paying off?
How will you leave the project when you're done? Will you feel proud of your work? What if you left the project today? Are you proud now?
Empathy and improvement
Now it's time to reflect on your responses.
Did you value the same things in the legacy code you inherited and the code that you wrote? Most of us have a different set of values for things we do vs. the things others do.
We have an opportunity to learn from our own experiences about what we value in legacy code.
When we inherit a gnarly piece of legacy code, it's helpful for our headspace to remember that a human being wrote that code.
Being empathetic and looking for positive aspects of the code (along with negative ones) can go a long way toward improving our own positive feelings. Recalling the fundamental attribution error can be helpful if you have a hard time with this: what circumstances contributed to the code being the way it is?
Think of empathy in legacy code as building a sort of team camaraderie across time and space.
What will your legacy be?
We can make dealing with legacy code easier on ourselves and others by incorporating that learning into our daily work.
We all have a hand in creating legacy code. If we can act in our daily development work the way we hoped the original authors of our legacy code acted, we can make the legacy code experience better for future maintainers.
So let's leave a great legacy for the future, with every commit we make.