Only take the codebase where it already wants to go
I was once airdropped, by myself, into a 3-year-old mobile API that served millions of requests a month. That was old by this company’s standards; the senior coders in the company had moved on to more exciting arenas.
This was a pivotal moment for my career. I had massive respect for my co-workers and felt like a small fry compared to those who wrote the API. I felt that I was entrusted with something above my level as a coder.
It was a period of learning. I had many failed initiatives, like my attempts to reduce code redundancy, migrate to Rails API, and introduce protocol buffers. Some of these failed because I encountered resistance from the team; some failed because users themselves weren’t interested; some failed because it just wasn’t the right time yet.
I had an epiphany during this process of trial and error. I realized that codebases are, in a way, alive. Sounds crazy, huh?
If the files in a repository make up its body, then there’s also a hidden spirit, discernible in the patterns, conventions, history, opinions of the team, and the overall direction of the code. It speaks to you in subtle ways when you fix bugs, read old tickets and commits, extend and modify existing code, and interact with the team. It’s not something you can capture in documentation; you have to experience it over time.
Some think that, by rewriting the code itself, they can force the codebase to go where they want it to go. They don’t consider where the codebase wants to go. This is why so many refactors and rewrites are total disasters. The coders may have switched out the body for a new body, but the spirit is still there, fighting them.
When it did come time to write version 2 of the API, I had been doing this for about a few months shy of a year. I could see a new architecture immediately, informed by those past failures. There was still some disagreement among the team, but it was the smoothest rewrite I’ve ever seen.
Ever since then, I’ve had a secret rule I follow when refactoring: only take the codebase where the codebase already wants to go.