Refactor or rewrite?

We hit a crossroads with every aging project: to refactor or to rewrite?

Refactoring means diving into that spaghetti code and cleaning it up, bit by bit. It’s about making the codebase more efficient and readable without changing its external behavior. Think of it as giving your app a fresh coat of paint and fixing the plumbing.

On the flip side, rewriting is starting from scratch. It’s saying goodbye to the old mess but risking the unknown. You’re building from the ground up, with the chance to use the latest tech and best practices. Sounds great, but it’s a big gamble. Time, resources, and the potential to introduce new bugs are real concerns.

We should refactor!

Refactoring, at its core, is about improving and optimizing without starting over.

You dive into the code, untangle the mess, and enhance performance, all while keeping the engine running. The beauty here is continuity; your app stays live, users remain happy, and your team tweaks without tearing down years of work. But, the flipside? It can be a slow, meticulous process. Imagine trying to fix the plumbing while the water’s still running. You’re limited by existing structures, and sometimes, a patch here and a tweak there just don’t cut it. Plus, the deeper you go, the more likely you are to uncover hidden issues that extend timelines and budgets.

We should rewrite!

Rewriting, on the other hand, offers a clean slate. This approach frees you from the constraints of legacy code, allowing the adoption of new technologies, architectures, and practices. It’s a chance to reimagine the app, making it more scalable, maintainable, and aligned with current and future needs. The downside? Risk. Rewrites demand significant resources and time, during which your team isn’t pushing new features or directly adding value to the existing product. There’s also the “Second-System Effect,” where the ambition to make everything perfect leads to complexity and bloat, prolonging the project further.

We should sit down and cry!

Then there’s the issue of knowledge. Refactoring keeps you in familiar territory; you’re working with the devil you know. Your team has a deep understanding of the existing codebase, which can make pinpointing and addressing issues more straightforward. However, this familiarity can also breed contempt, leading to complacency and missed opportunities for improvement. In contrast, a rewrite brings everyone back to square one. There’s a learning curve, not just with new technologies but also in understanding how to replicate existing functionality in a better way. This fresh start can invigorate the team but also strain resources as developers climb the learning curve.

We should keep our product running!

User impact is another critical consideration. With refactoring, the changes are often under the hood, meaning less disruption for your users. It’s possible to incrementally improve the app, keeping it functional and available. But with every change, there’s a risk of introducing new bugs into a stable product, potentially breaking something. Rewrites pose a different kind of risk to your audience: the wait. During a rewrite, your app’s evolution stalls. If not managed carefully, this can lead to user attrition as your app falls behind competitors.

I’m a developer, what should I know about business impact?

Let’s talk about business impact. Refactoring can be more cost-effective in the short term, offering improvements without the hefty initial investment of a full rewrite. It allows for gradual investment and provides value at each step. Yet, this piecemeal approach can sometimes prolong the inevitable, leading to higher costs over time as more and more of the codebase demands attention.

Rewriting requires a significant upfront investment and a leap of faith, betting on the future efficiency and success of the new system. The potential for a high return is there—if the new system can deliver on its promises and revitalize the app for future growth.

Im’ a business guy, what should I know about tech aspects?

Refactoring means tweaking and improving the current system without starting from zero. It’s like routine maintenance on a car to keep it running smoothly. This approach minimizes disruptions and allows continuous delivery of new features, keeping users engaged and maintaining revenue flow. However, it’s not a magic fix; some issues may remain hidden, only surfacing later.

Rewriting, meanwhile, is building a new system from the ground up. It’s a chance to use the latest technology, potentially making the app faster, more secure, and easier to maintain. But, it’s a big project. Think of it as constructing a new building rather than renovating an old one. It takes more time and resources, and during this period, new features slow down, which might impact user satisfaction and revenue.

Strategic Decision-Making

In essence, it’s a trade-off. Refactoring allows for steady, incremental progress but may limit how much you can innovate. Rewriting offers a fresh start with more potential for innovation but comes with higher risks and costs. Understanding these trade-offs helps align tech decisions with business strategy.

Deciding between refactoring and rewriting is more than a technical challenge; it’s a strategic decision. It requires a careful evaluation of your app’s current state, its trajectory, and how either choice aligns with your long-term business goals. Refactoring might align better with a strategy focused on steady growth and incremental improvement. In contrast, a rewrite might be the way to go if your app needs a significant pivot or if you’re aiming for more modern, scalable solution. The key is to not only consider where your app stands today but where the market and technology will move in the coming years.

Risk Management

Both refactoring and rewriting come with their own sets of risks. Refactoring risks becoming a never-ending journey, where each improvement reveals new depths to be explored, potentially leading to ‘analysis paralysis’ or constant mid-course corrections without reaching a satisfying end. On the flip side, rewriting poses the risk of the unknown. New code means new bugs, and the time taken to reach market readiness can leave your app lagging behind. Managing these risks involves thorough planning, clear milestones, and continuous reassessment to ensure that your project remains on track and aligned with your objectives.

Balancing Act

Ultimately, whether to refactor or rewrite is a balancing act between innovation and stability, between immediate needs and future visions. It’s a decision that shouldn’t be made in isolation but as part of a broader discussion involving stakeholders from across the business. This includes weighing the technical debt against the opportunity cost of not innovating fast enough. Balancing these aspects with a clear eye on your app’s and business’s future will guide you toward the right choice, ensuring that your development efforts contribute to long-term success and sustainability.

The verdict.

So, what’s the verdict? It depends. If the app’s foundation is shaky and you’re constantly patching leaks, a rewrite might be in order. But if the core is solid, and you just need to modernize and clean up, then refactor. Both paths need a clear plan and understanding of the scope. Don’t dive in without considering the impact on your team and users. And remember, whether you’re refactoring or rewriting, the goal is the same: making your app better for those who use it.

Jarosław Michalik

Mobile dev consultant & Google Developer Expert in Kotlin

With over 8 years of experience in mobile development I help my clients untangle complexities of legacy Android projects.

Read also