Você deve refatorar ou reescrever seu código?

Should you refactor or rewrite your code?

Whatever the choice, resist the temptation to default.

Código de refatoração ou código de reescrita

Software development is a field that does not lack for debate. But if I had a hard time choosing the most heated one, it would be the “refactor or rewrite” contest. As a quick Google search can show, there are as many opinions as there are software developers, so reaching an understanding is something close to utopia.

However, software engineering teams are faced with this choice more often, so it's not uncommon for people to turn to these opinions for help. But because viewpoints are so varied, doing so ends up feeling like a leap of faith.

I (or anyone else) cannot provide a straight answer because there isn't one. As with many things in software development, it all depends on several factors that are specific to each situation. In other words, there are no general rules about whether you should refactor or rewrite your code – even when many experts or experienced developers claim that one or the other is the best course of action.

In my opinion, it is better to develop a critical mindset to approach any project that can be refactored or rewritten. Armed with it, you can evaluate any scenario you encounter in nature and define the best path forward. Read on to find out what things you need to keep in mind. But first, let's make sure we're on the same page.

Refactor and rewrite

Criterion Refactoring code Rewrite code
Main role Improve the design of existing code without changing its external behavior Replace existing code with a new version that provides the same functionality
Key tasks Code cleaning, optimization, removing redundancy, improving readability Starting from scratch, designing, coding and testing
Required skills Understanding of the code base, good knowledge of the programming language, refactoring techniques Strong knowledge of programming language, software design principles
Time Consumption Generally less time-consuming, done incrementally More time consuming, entire codebase needs to be rewritten
Risk Lower risk as changes are small and incremental Greater risk, new code may introduce new bugs
Cost Generally minor as it does not require a complete rewrite Larger as it requires complete redevelopment
Existing errors Can help identify and fix some existing bugs Existing bugs can be eliminated, but new ones can be introduced
Understanding the code Increases developers' understanding of the codebase It can improve or decrease understanding depending on the complexity of the code
Impact on functionality Does not add new features, focuses on improving existing code Can add new features and improvements along with rewriting existing code
Test Requires testing, but generally less extensive due to small incremental changes Requires full testing of all functionality
Best for Codebases that need minor improvements or have maintenance issues Codebases that are difficult to maintain, understand, or poorly structured
Result Better code quality, maintainability, and potentially better performance New codebase, potentially with better structure, performance and new features

One of the most common problems you'll find with articles addressing this debate is that their authors often don't clarify what they mean by refactoring and rewriting. Maybe it's because they believe the developers know what they're talking about. While this may be true (any developer knows about these practices, regardless of their experience), the problem is that there is no universal definition of them.

So, to avoid any confusion, I will tell you what I think of them. It may be different from your definition, and that's okay. I'm not trying to convince you to use these definitions. It is mainly to clarify what I will talk about when I refer to both later.

I'm more of the Martin Fowler school when it comes to restructuring . This means that whenever I talk about refactoring, I'm referring to changing the design of something without impacting its behavior. It's about touching up the code to increase its quality while the software remains the same. So the result looks the same, but offers better performance, security, integrates better with newer technologies and is more scalable, among other things.

A rewrite, on the other hand, is scratching out all the existing code and starting from scratch to get to the same place (or even a better place). This means understanding the software as it is and recreating it through new code. We could say this is the “nuclear option”, in that we get rid of what we have to provide a better alternative.

In general, developers love to rewrite things. There are several reasons for this: it's easier to start from scratch, you don't have to worry about things breaking because you're tweaking specific parts of the code, you can create a better product – you can even write better documentation for it while you're rewriting it! However, believing that rewriting is superior because of these things means willfully ignoring other crucial aspects that accompany the decision to rewrite in the first place.

Let's see some of them.

Besides rewriting the siren song

All the reasons I mentioned above are the first things that come to mind when software engineers are faced with old, poorly performing software. It all ends the same way – engineers wanting to rewrite to start from scratch. However, developers are rarely the only ones to decide the fate of software. In fact, some considerations are often more significant when deciding which path to take.

Of these, business boosters are at the top of the list. A rewrite (especially of complex software) can be a time-consuming task that can end up costing a lot of money without any real advantage from a business perspective. Perhaps rewriting the software takes up too many resources that prevent the team from focusing on more valuable tasks. Maybe the rewritten software doesn't have enough ROI to justify the rewrite in the first place. As such, rewrites can often go against business objectives, one of the main reasons they are rejected.

This brings us to the risks associated with rewriting. Perhaps rewriting the entire software may have an impact on the business, but in the time it takes to complete, it allows the competition to bring a similar product to market faster. There may be new competitors in the market once you complete the rewrite. Or perhaps the money you invest in the rewrite prevents you from investing in a more strategic asset (whether technological or not).

Finally, there are certain aspects directly related to the software itself. Maybe the software you want to rewrite is not easy to maintain, but it is resilient, offers a lot of security, and has excellent performance. If you're not completely sure you can replicate all of this, rewriting it could end up backfiring. You may end up with more easily maintained software that isn't as resilient, secure, or performs worse than what you had before.

Presenting these considerations doesn't mean that rewriting is a bad option (I'm trying to avoid extremes at all costs). Instead, they provide the necessary information to be taken into account when making a decision. Thus, they help paint a more realistic picture of what the rewrite might mean.

Designing a critical approach

Since rewriting is what most software engineers consider when they need to improve an existing system, it's essential to start there. Considering business drivers and associated risks can be a great way to decide whether a rewrite is right for you. In simple terms, you need to determine whether rewriting is a viable option for you before considering the technical aspects of it all.

However, there is a tricky thing about doing this. You may be considering a rewrite or refactoring because you have a lot of technical debt or your software is nearly obsolete. In this scenario, both options are risky. If you stay the same simply because things work, you run the risk that your software won't last long, will be unmaintainable in the near future, or won't be scalable. If you rewrite it, you may not get the same features.

This means that there is no risk-free option – consider yours and be aware of them, but do not base your decision solely on the risks (or lack thereof), simply because there is no scenario in which you will be free of them. .

So the best way to look at this, in my opinion, is this:

  • Consider the business implications of either option. What are its potential consequences?
  • Analyze and assess the risks. One of the options may be riskier than the other, but not necessarily. Do you understand what it means to follow one path or another?
  • Describe the reasons why you want to refactor or rewrite. What are you trying to accomplish?
  • Identify how far your current software is from these goals. Make it as detailed as possible.
  • Set a clear path that takes you from where you are to where you want to be. Is it even possible? Perhaps there are incompatibilities with new technologies or there are no ways to transform outdated software into modern hardware.
  • Split the two processes by following this path. What is involved in code refactoring? And what are those included in a rewrite? This is a key part of the assessment, so don't try to express the process in how long you think both processes will take. Instead, try to think about the tasks and their complexities, as this will allow you to better compare the two options.
  • Compare the paths in front of you. You may find that although refactoring may require more steps, these steps are easier than the fewer steps included in the rewrite. Or perhaps it becomes clear that refactoring is an insurmountable effort due to the many tasks it entails.
  • With a clearer view of both paths, reevaluate your business drivers and risks. Once you take all of these considerations into account, you will be better prepared to make a final decision.

The refactoring versus rewriting debate is sterile when it comes to daily operations, as it often strays into theoretical terrain. As no two projects are the same, it is vital to go over these practical steps to better approach the subject and determine whether one road is better.

One final recommendation from me. Even if you find that one approach provides better results for your projects, resist the temptation to default to that option, as you may come across a specific project that could benefit from the other approach. It may seem tiring to do this analysis every time you work with old code, but I guarantee it's the only way to get the best results for your projects.

Source: BairesDev

Back to blog

Leave a comment

Please note, comments need to be approved before they are published.