Refactor or Rewrite: Things every programmer should consider
At some point you or your team will be faced with a difficult decision: to continue adding to an existing codebase, or rewrite the system from scratch in a new project. As developers, our first choice will almost always be to build a new system from the ground up, but that’s not always the best choice for every situation. Regardless of which decision you make, both paths include significant risks, and there are important things to consider before making a decision.
Here are a few things to consider when deciding on a refactor vs a rewrite:
Understand the type of application you’re building
Customer facing vs internal only application
Your team’s capabilities
Familiarity with languages
Familiarity with frameworks
Future hiring plans
Team’s appetite for risk
Willing to take risks and deal with issues as they arise
Not willing to risk any downtime or production issues
Whether you like it or not, you are probably not the only decision maker. Make sure you consult with all the stakeholders, including your manager, product managers, and teammates before making a decision. The decision making process will probably span weeks, or sometimes months if the system is sufficiently complex. At the very least, you should put together a design document that outlines your research and offers pros and cons about the tradeoffs your team will need to make for each option.
Let’s look at each option in greater detail.
Incremental refactoring is when you choose to make changes to a legacy system gradually over a period of time. This allows you to plan out schema migrations and is generally used when you want to keep a system running, but still improve it over time.
Changes can happen over time. You can shift your focus and come back at a later time if needed.
Improvements can be isolated to individual parts of the system in order to limit risk.
It’s always an option.
Can be done to any codebase.
Need to work within the constraints of the current system (i.e. tech debt).
May be difficult to fix underlying architectural issues.
Sometimes difficult and complex to swap out legacy code in a production system
Usually requires automated tests in order to ensure core functionality doesn’t break.
The large rewrite happens when you build a new system from the ground up to replace an existing legacy system. This allows you to start fresh with a blank canvas, which is enticing because you can use new languages, frameworks, infrastructure, and design patterns that you may not be able to use during incremental refactoring.
Enabled foundational changes to the architecture of a system.
Introduces new capabilities thanks to new technologies or design decisions.
Reduces the need to work around technical debt.
Provides the ability to introduce new coding standards with a clean codebase.
Always takes longer than anticipated.
Eats up resources for other projects like new feature development.
Not guaranteed to solve all problems that plagued the old system.
May introduce new problems that the old system didn’t have.
Complex migration period as you transition away from the old system.
Still need to maintain the legacy system.
Hopefully this gives you a better idea of the tradeoffs you need to take into consideration when deciding whether to refactor a legacy system or rewrite a system from the ground up. Both decisions carry their own risks and there is no silver bullet when it comes to these kinds of choices. Make sure you discuss all of these details with your team before deciding one way or another.