Recently, I’ve been tasked with adding features to a product and codebase that I did not write. This of course happens all the time; if the code is at all useful, it will be extended and evolved by an increasing number of authors. There’s nothing inherently wrong in working in someone else’s domain.
That said, the existing code is a bit hairy, fairly complicated, doesn’t fit quite right, and requires an understanding of multiple systems to even begin to know where to make additional changes. Much of it can be classified as technical debt, despite the youthfulness of the codebase itself.
Given this setup, it’s fairly easy for me to rage against the pieces I have to work with. Indeed, I’ve gotten up from my desk multiple times, frustrated at my lack of progress and the amount of work it takes to set up a clean development environment and massage the model objects into a usable state. I’m as guilty as any other engineer in underestimating the depth of debt that needs to paid back, or at least worked around.
But whining about the problem doesn’t help. Instead, I’ve been trying to stay empathic, and tell myself that
This code was written to a product spec in another time.
Which is to say, don’t start with the mentality of blaming the previous engineers and project managers. Instead of assuming that they maliciously threw debt over the wall, I want to give them the benefit of the doubt. Yes, some things may be hacked together, but they were trying to hit a tight deadline. The product was likely never meant to accommodate all these additional features I’m tasked with building. The target audience and user have changed in the meanwhile.
In fact, had the product requirements not evolved over time, there would be no need to actually modify the software. The real reason why software develops is that the things it tries to model – reality – also shifts over time. Our software, at any single point in time, is just a reflection of our imperfect understanding of how things really work.