Writing
Oct 20, 2024Engineering8 min

Code Cleanup, Product Glow-Up: Why Refactoring Matters

Refactoring rarely gets the spotlight of a new release, but it is the invisible force behind sustainable product success.

Open in Medium

Refactoring: The Unpraised Hero of Product Growth

It is in the best interest of product managers and engineers alike to constantly ship new features, boost user engagement, and stay ahead of the competitors. After all, nothing excites customers (both internal and external) more than a new and exciting release. It’s the kind of thing that captures the spotlight from the perspective of your users. However, beneath all this sparkle, there’s a quieter, less glamorous task that too often gets pushed aside: refactoring.

While it doesn’t come with the same fanfare as a new product launch, refactoring plays a critical role in the long-term health and growth of your software. In fact, it’s the invisible force behind sustainable product success.

Having navigated both startup and corporate environments across North America and Europe, and being on both sides of the table, transitioning from software engineering into product management, I’ve seen how crucial it is to maintain a clean and healthy codebase. The state of your codebase directly impacts your ability to scale, pivot, and adapt your product to new challenges. Whether you’re deep in the code as an engineer, or juggling timelines and priorities as a product manager, a well-maintained codebase is a powerful enabler of sustainable growth.

Refactoring is often viewed as a “necessary evil” amongst software engineers, but this mindset underestimates its importance strategically. It’s much more than a code cleanup. It’s about ensuring that your product can continue to evolve gracefully. It’s a key factor in future-proofing your codebase, keeping it adaptable and resilient in an industry where change is constant.

What is Refactoring, Really?

Refactoring can be thought of like a home renovation… You’re not necessarily adding an extra room or changing the layout of the house; instead, you are ensuring that the plumbing doesn’t have leaks, the wiring will not create short circuits, and the rotten beams behind the walls are replaced with sturdy new ones. Thus, you are ultimately strengthening the foundation of the house, to be sure that it remains safe and functional for years to come. Similarly, in software development, refactoring means restructuring existing code to improve its internal structure and maintainability, without changing any of its external behaviour.

In simpler terms, refactoring is about making the code easier to read, more efficient, and simpler to maintain. It reduces complexity, removes redundancies, and eliminates outdated logic: bringing order to chaos. While it doesn’t add new features, it sets the stage for faster, more reliable development of new features to come. When your code sparks joy instead of bugs for the engineering team, they can continue focusing on building new impactful features instead of wrestling with a mess of spaghetti legacy code.

The benefits aren’t just for the developers either. A cleaner codebase translates into an increase in development velocity, fewer bugs to spend time resolving, and a more seamless user experience, all of which can directly impact the success of your product.

Why Product Managers Should Also Care About Refactoring

As a product manager, it can be very easy to fall into the trap of thinking, “Why focus on refactoring when we have new features to prioritize, and OKRs to meet?” This is a fair question, especially if it is being asked by your product leaders… After all, from a strategic perspective, refactoring looks a lot like engineering effort and time that can be used towards shipping more impactful things that solve customer problems. But overlooking it can be quite dangerous in the long-run. The way I see it, it is all about being forward-thinking.

Without regular code maintenance, engineers can start to face problems. New features become harder to implement, bugs become trickier to pin-point & resolve, and each new release becomes riskier than the last in terms of product stability. Refactoring strengthens the foundation on which your product is built. It allows your product to grow and evolve without the constant fear that the entire scaffolding might collapse under its own weight.

In today’s tech landscape, we are constantly facing new challenges; some of which are shifting market trends, evolving customer needs, rapid advancement of AI, and unforeseen edge cases. Refactoring doesn’t have to just be about cleaning up the code; it can be about ensuring that your product is ductile enough to evolve with these changes. In a sector where flexibility is key, that adaptability is invaluable.

As a product manager, hearing out your engineering team’s cries for refactoring, and communicating its importance to senior leadership as well as non-technical stakeholders is in your best interest, because it is making a long-term investment in your product’s success.

The Cost of Delaying Refactoring

Refactoring isn’t something you should keep postponing. The longer you wait, the more daunting the task becomes. While it may seem to be inconsequential for the time being, it is bound to create LOTS of headache down the line if not addressed.

Every day that refactoring is delayed, the technical debt of your codebase grows. And similar to financial debt, it accumulates interest in the form of slower development, increased number of defects, and a frustrated engineering team. Over time, that frustration can spread to your customers, who experience buggy behavior or possibly even software that fails to meet business requirements completely. At this stage, when it truly becomes a high-priority problem for the product team, the code has already become unmanageable, and you’re left with fewer options and higher stakes.

Urgency is key when it comes to refactoring, to address the issues while they’re still manageable, rather than waiting until DEFCON 1. Trust me, I’ve been in that high-pressure situation when I was still a Software Engineer. My team had to refactor an entire codebase under very tight timelines because we hadn’t built a strong enough business case for refactoring earlier on. It led to a handful of sleepless nights, and it certainly was not fun. What’s worse, it caused our internal customer base to become quite unhappy until things got back in order again. What is most important here is that all of this could have been avoided with more advocacy from the product team. Knowing this now as a Product Manager (having lived it multiple times first-hand as an engineer), I try to act with more urgency and cooperation at the first mention of the term.

By making refactoring a regular part of your development process, you can prevent fighting these fires and ensure smoother sailing through the roadmap of your product. It is certainly a lot more sustainable for your team!

Continuous Refactoring: An Agile Approach

So then how do we prioritize refactoring without stalling feature development? The answer lies in Continuous Refactoring, an approach that integrates refactoring into your Agile workflow. Rather than waiting for a massive overhaul, you can strategically break refactoring tasks into smaller, more manageable pieces and address them incrementally.

This can be done in a variety of ways, two simple ones of which are:

1. By allocating effort within each user story / task (depending on your team’s practice) to address possible areas of improvement that you might notice while trying to meet the Definition of Done within that user story / task. If the refactoring effort is too large, then it gets placed in the backlog to be picked up later. By adopting this practice, you foster a continuous improvement work culture, and increase your chances of avoiding big refactoring efforts down the line.

2. By adopting “hardening” or “technical-debt” sprints, based on the Quality Improvement Paradigm (QIP). Instead of waiting for a dedicated cleanup, which is also often postponed in favour of feature development, you allocate one sprint in each development cycle for addressing technical debt, or in other words, quality improvement. By addressing minor issues early, you avoid the need for a costly rehaul later.

Continuous improvement allows you to mitigate the accruement of technical debt, preventing small issues from snowballing into bigger problems. This approach also provides more transparency and reassurance to stakeholders, who can see steady improvement rather than spontaneously being face to face with a massive refactor that is planned to take up engineering efforts for the next quarter.

This incremental approach fosters confidence in your development team as well, as their day-to-day operations remains undisrupted. By integrating refactoring into your Agile processes, you ensure that your product remains nimble, no matter how complex it becomes.

A Strategic Priority for Product Managers

Sometimes, despite the best efforts of engineers, continuous improvement does not save the fate of a codebase from needing a complete overhaul. As soon as this gets raised by the tech lead, it should become a strategic product priority.

One of the biggest misconceptions about refactoring is that it’s solely an “engineering problem.” In reality though, product managers can find that it can very quickly become a product problem as well. Once the quality of the released features starts to plummet, and time-to-market starts to increase, it is already too late to bounce back from quietly. As product managers, it’s essential to advocate for refactoring just as much as the engineers. It should be a requirement to ensure that the product roadmap allocates time for this crucial task. By aligning with engineering leads and communicating the business value of refactoring to stakeholders, you can elevate it from a back-burner task to a strategic priority.

Without this advocacy, refactoring often gets deprioritized in favour of more visible or immediate wins. But in my experience, this short-term mindset has always led to long-term pain. A well-maintained codebase doesn’t just reward engineers, it leads to faster development, less maintenance, and a more scalable product, all of which ultimately benefit the bottom line.

Reframing Technical Debt: From Debt to Opportunity

Finally, the term “technical debt” is often associated with an overall negative sentiment. It can be seen as an anchor dragging a project down, something to avoid at all costs. But what if we reframed it?

Instead of viewing technical debt as a burden, we should see it as an opportunity for optimization and innovation. Every piece of debt you address is a chance to streamline processes, improve performance, and create a more resilient codebase. When you frame it this way, technical debt becomes an investment in your product.

This reframing is crucial especially when explaining refactoring to non-technical stakeholders. To avoid certain preconceptions, we can refrain from using the term “debt”, and instead explain the situation as a method of improvement (buzzwords such as cycle time or error rates do tend to help your cause). This way, doesn’t it suddenly become an appealing investment?

By shifting the narrative from burden to opportunity, you make a compelling case for why the team should prioritize refactoring.

Make Refactoring a Part of Your Product DNA

Refactoring isn’t just about cleaning up code, it’s a strategic investment in the longevity of your product. It strengthens the foundation on which your codebase is built, allowing it to scale and pivot without fear.

For any product to thrive in a rapidly evolving tech landscape, a well-maintained codebase is essential. By making refactoring a continuous practice, you ensure that your product is able to grow in a sustainable way, and ready to meet whatever challenges the future (or your eager customers) might throw at you!