🎵 The song for this post is Scatman, by Scatman John.
In 2014, I built two Android apps for a 5-person startup in about two and a half months. In part because of lessons learned from the iOS app, I was able to architect it such that it had some features iOS didn't. When the CEO asked the CTO if it was possible to port some of the features back into iOS, the CTO said:
The iOS app has a fair bit of legacy code that makes this extremely challenging.
The iOS app was 6 months old. 🤔
I've mentioned my belief that most startups move to microservices due to cultural factors more than tech ones; I think a similar thing happens with the phrase "legacy code." It gets brought up as if merely stating the phrase communicates challenges usefully. Like the phrase "tech debt," I see it most often used with non-tech stakeholders, who can only challenge the assessment in metaphors.
When I hear "legacy code," I actually hear "this feels hard" or "I don't want to work on this." Lets go over some of the reasons this might be true.
"I didn't write this code"
Let's start directly in the deep water: many engineers hate working on existing code they have little context for, and will reach for reasons to avoid it. In the typical case, I don't think this happens consciously; it's like buying more groceries if shopping while hungry. Most people don't read code recreationally, and figuring out how a system works requires a different set of skills than building one out. Additionally, there's a sentimental factor: when looking at your own code, you know all the decisions leading to its current state, and are personally proud of the working product in front of you. You don't have that context with someone else's code.
I assume good faith, so I model this as engineers using the conscious brain to construct and rationalize narratives to get what they subconsciously want. Sadly, this is extremely challenging to address directly: by definition of "subconscious," the engineer isn't aware of what is motivating them, and has to confront that their rationalizations may simply be their lizard brain saying "but I don't wanna."1
If you're an engineer: Remember to challenge yourself and ask how much of your decision to label something as "legacy" or "awful code" is based on your lack of understanding of it. This is true beyond code: ignorance is a common cause of fear. And as with all fear or pain, ask yourself why it's present. You'll probably unearth learnings (about yourself, about your team/company culture, about the project) that will pay back in spades.
If you're a manager: You'll mostly be hearing true things said to you, and you have the challenging job of determining whether they're really unbreakable roadblocks, or whether they're rationalizations of your report largely not wanting to work on it. Be open to the possibility that it is the former: maybe there are extremely solid technical reasons not to work on the old project. If the latter, gently-but-persistently challenge the points brought up. And as always, remember to emphasize, repeatedly, that this isn't a question of the engineer's competence; you're mostly trying to find a solution with the biggest wins for both them and the org.
"I'm not confident the org will recognize the impact"
Legacy systems, by definition, are already running and providing enough value to justify their existence. While everyone intellectually understands the importance of keeping a system running, it doesn't feel as satisfying, for employees or stakeholders, as being responsible for the Hot New Thing. That new revenue stream, that UI redesign, that architecture rewrite: all of them are easier to pin hopes and dreams to than what's old and known. This is human: we're terrible at valuing maintenance and infrastructure.
For managers: Demonstrate, over and over, that you value infrastructure and maintenance as highly as new initiatives. Do as much as possible to sweeten the gig of working on something that is already running.
For engineers: As with always, whatever you work on: recognize the value of your work and ensure your employer does the same. If you feel like infrastructure and maintenance are undervalued, make a case for yourself. I don't mean this to be adversarial! Most managers, being human, need nudges and reminders. Assume good faith when you bring it up, but do bring it up.
"I'm not confident the org will support me"
Slightly a combination of the previous two, but: working on legacy systems is hard! Engineers have to wade through complex systems that often lack documentation, tests, specs, or monitoring ("it works because it works"),2 and their managers have few yardsticks to measure or determine impact.
Additionally, non-engineering management tends to have a skewed view of engineering maintenance, where they expect someone to go in and fix it like a plumber repairing a leak: a sufficiently smart engineer can find the bug, patch it, and the component will work as normal. In reality, they have to learn the system, build fixtures to determine and subsequently work around its existing behavior, architect and (re)implement the solution, then gradually remove the fixtures, documenting the whole process. It's more akin to a jockey doing surgery on a racehorse as it's running a race.
So many engineers (rightfully!) fear that they won't get the time, space, autonomy, and error budget to do the job effectively. They fear management will get cold feet partway through and cancel the project.
For both engineers and managers, be clear that this is a marathon, not a sprint. Most working relationships require more communication than is typically comfortable, and legacy code projects require more than that. Be prepared to challenge each other and stand up for each other for many months to come.
It's just code
Despite the old truism, successful rewrites of old codebases are possible. And there's a playbook or two for working with Legacy Systems. Whether you're the engineer in charge or their manager, recognize that with diligence and significant investment, getting what you need from an old codebase is very possible.
Ruby from 10 years ago is just as readable in your editor or terminal as Ruby today. If everyone involved can keep a marathon mentality, there's no reason projects on legacy systems shouldn't work.
1. ^ My favorite examples of subconscious wants driving conscious discussion is when two engineers fight over which tool or language to use for a task. They'll both say true facts back and forth at each other but really it's about how they feel. So if the choice is "should we build the Frobulator in Go or Java?", you'll hear
"Java has the whole JVM ecosystem of libraries!"
"Go enables soft real-time with thread-local garbage collection!"
"All things considered though, it is so much easier to hire Java developers."
"Go's quick compile times enable fast iterations!"
when what they're really saying is something closer to
"I want to write in Java because I like it better."
"I'm bored with Java and wanna learn some Go."
"I want to feel like the more senior engineer."
"No I want to feel like the more senior engineer!"
2. ^ New code lacks docs/tests/specs/monitoring too, but the engineer either wrote that code, or being new, it's so small and does so little that it's pretty easy to comprehend.
Thanks for the read! Disagreed? Violent agreement!? Feel free to drop me a line at , or leave a comment below! I'd love to hear from you 😄