Status for Waverley’s Ukraine Office: READ HERE

Code Rewriting: When and Why

Hi, nice to meet you! My name’s Elena Sharovar and I am a Lead Node.JS Developer at Waverley Software. In this article, I’d like to discuss a situation in the software development process when the software engineers believe or insist that the time has come to rewrite the code on the project, but it’s not easy to explain “why” to the customer. As a result, the customer is not eager to start the code rewrite process. 

This article is about finding mutual understanding between the decision-makers and the development team. Developers say that the existing code “needs improvement”, but the customer “doesn’t get it.” Software engineers are now nodding in understanding:  “How familiar!” while their clients are opening their eyes wide. But the question remains: how to reach a win-win solution?

Upon conducting a comprehensive code review and a thorough analysis of your project, you may come to any decision – to rewrite the code, to do it partially, or to keep the code as it is. I hope my detailed analysis will help you make that decision wisely and in a well-considered manner, successfully getting your idea through to all the stakeholders.  

For starters, let’s consider the driving factors.

What Code Rewriting Means for Developers

The question that bothers customers the most is why do programmers want to rewrite the project code?

First and foremost, because we want to do our job well. Unfortunately, “well” sometimes implicates different quality standards for different people. For example, a developer might want to rewrite code if they took over a legacy system, and the people who used to work on it had their own opinion of what’s “well”. Sometimes, legacy code is not written well because a preceding software development team got a product prototype created in a rush, with one goal – to meet the deadline, and with no attention to quality and maintainability. 

Secondly, when we work, we need to keep information in memory. And it’s much easier to remember and understand well-structured code than to memorize random files and functions.

good code vs messy code

Third, we need to understand the consequences of our actions. When one has to change something they don’t understand, it starts getting stressful. Nobody wants to work under stressful conditions when developing, testing, deploying, do they?

What do Experts Say?

Software engineers want to rewrite code in a large portion of cases. This is a result of our natural desire to do our job better. Here’s what Joel Spolsky, a creator of Stack Overflow, wrote 20 years ago:

The reason that they [programmers] think the old code is a mess is because of a cardinal, fundamental law of programming: It’s harder to read code than to write it.

This is why code reuse is so hard. This is why everybody on your team has a different function they like to use for splitting strings into arrays of strings. They write their own function because it’s easier and more fun than figuring out how the old function works.”

Whenever new developers onboard a project, they find the existing code too complicated and want to rewrite it. “As a corollary of this axiom [that code is more easily written than read], you can ask almost any programmer today about the code they are working on. “It’s a big hairy mess,” they will tell you,” he says. 

The thing is, nobody wants to do the unpleasant part of the job, which is dealing with legacy code or onboarding a project. “Fixing bugs isn’t fun; going through the bug list isn’t fun; but rewriting everything from scratch is fun (because “this time it will be done right”, haha)…”, Jamie Zawinski writes

So, as you see, developers want to rewrite something fairly often. But one should be pragmatic and think twice before taking action. 

A Word on Engineering Ethics

When becoming a doctor, one takes the Hippocratic Oath. One of the things they promise with it, is the serving of the interests of patients first and foremost, as opposed to their own concerns. 

When becoming a programmer, we don’t take any oaths (not yet), but we do have our professional Code of Ethics put downin black and white, and one of its postulates is essentially the same: “Principle 2: Software engineers shall act in a manner that is in the best interests of their client and employer consistent with the public interest.

The bottom line is that pursuing personal interests instead of business goals is considered unethical. So, before asking for approval for rewriting the code, make sure you pursue the interests of the product and the customer, not your own.

Code Rewriting and the Customer

What any business owner should understand is, the more parties involved in a project, the more diversified their objectives are. First of all, let’s define the possible stakeholders participating in a project, their roles, and interests: 

  • Investors: they invest their financial assets into a project and expect a good Return on Investment (ROI).
  • Product Owner: this person is responsible for project management and sets priorities for the upcoming sprints, quarters, years. They communicate with both investors and developers. 
  • Users: these are people who (will) use your product and pay for it.
  • Developers: yes, they are also considered as stakeholders, and they should be satisfied with the product or code they create. 

This is how a computer program looks for all the stakeholders but for programmers:

how computer program works

And that’s it! The magic which happens inside the “black box” is known only to the software engineers. If an application works the way it should, everyone – the investors, the product owner, the users, and the customer – is happy. 

Where is the Conflict?

I’ve heard about a methodology of conflict-solving: in any conflict situation, ask the parties to put down their wishes and concerns on paper. This technique is very simple and effective. I’ve filled the table below as an example, and you can fill it out based on your situation:

stakeholders' wishes and concerns

A conflict usually appears at the intersection of one party’s wishes and the other party’s concerns. As a result, the parties cannot come to an agreement: the wishes of one stakeholder cause concerns for the others. To ensure your software development process is running efficiently, I recommend resolving such situations.It’s worth mentioning that when the software development is done through an outsourcing company, the investors’ concerns may include the fear of being tricked into paying for additional development and resources. A way to cope with this concern is requesting an independent code review and audit done by a third party, whom the investors can trust, or a non-profit organization.

Where do the Interests Overlap?

In addition to functional characteristics, any software application has the non-functional ones. Here they are:

  • Response time (performance)
  • Absence of bugs (reliability, usability)
  • Availability
  • Resilience (to failures)
  • Extendability
  • Maintainability
  • Mean time to repair
  • Development and maintenance cost
  • Testability
  • Auditability and availability for debugging

The first four characteristics are crucial for end-users because the end-users will definitely notice and complain if these characteristics are faulty. 

The other six characteristics – starting from extendability – do not affect user experience directly, but they’re crucial for the product owner and developers. They support the quality of the previous four. Also, these six characteristics significantly affect the speed of development of the new features. 

All this brings us to the fact that the non-functional characteristics are the touchpoint for programmers, users, product owners, and customers. So, when requesting approval for code rewriting or refactoring the main project elements, programmers should explain which particular non-functional characteristics they want to improve.

For example, if the project code is way too complicated and messed up, then maintainability, development time, and testability are likely to be poor. If a project uses old libraries and frameworks, the chances are that extendability is limited. If the old system’s architecture was not adapted for a big volume of requests, you could be expecting problems with scalability and performance. If developers spend half of their workdays looking for the source of old and new bugs, auditability and traceability definitely need improvement. 

Also, it is important to apply the strategy of preventive risk management and think of issues that are likely to emerge in the near future.

Considering the Reasons to Rewrite Code

Note: saying “rewrite” here I mean rewriting the code from scratch or starting a major refactoring project touching a large portion of the code.

Here are some good reasons to rewrite your project code:

  • You can’t add new features without a complete rewrite of the existing source code. 
  • Onboarding new developers on a project gets too complicated and takes more than two months.
  • You find it hard to set Continuous Integration or Deployment.
  • Simple bug fixes take up way too much time or you can identify a “code smell” that might be hinting at deeper system issues than it seems at first glance
  • A platform hosting your application terminated maintenance.
  • You are planning to increase the number of users, and the old system won’t handle it.
  • The software interface got outdated and you need a modern one.
  • In the process of delivery, the development team has evolved a deeper understanding of the product’s business domain and can suggest a better implementation through a more efficient model.

And here are examples of bad reasons to rewrite:

  • The existing code is written using Promises, but you want to use the async/await pattern.
  • There’s framework N, but a friend of yours told you that framework Y is trending now.
  • You want to put a couple of new technologies on your CV.
  • You don’t like working with the code written by someone else.
  • The code is working but you don’t understand how. 

Here are some other good and bad reasons for rewriting the code.

Some common pitfalls or code rewriting:

  • Rewriting the code always takes up more time than expected (based on global stats, mentioned in the McConnel’s book “Software Estimation: Demystifying the Black Art”,  software development projects typically get underrated by 30% or more).
  • Mere rewriting brings little value to the end users.
  • You risk “leaving behind” or “losing” part of the existing software functionality if the complete documentation on the preceding system is missing.
  • You are likely to produce new bugs or the same ones your predecessors did.
  • While rewriting the code from scratch you will have to maintain both the old system and new version of the application. 

Should we not rewrite the code if it works?

This is a faulty assumption. The principle “if it ain’t broke, don’t fix it” doesn’t work here. The book «Object-Oriented Reengineering Patterns» mentions that if a system works well, but you can neither maintain nor scale it, it is broken. 

Basecamp, for example, has released three versions of their product – Basecamp, Basecamp 2 and Basecamp 3. They never killed or made major changes to the old version, they just released a new system every time. 

Something similar happened to the AngularJS framework – when they decided to rewrite it, they issued a completely new Angular framework, thus reducing the risk of breaking what had been working well.

Microsoft rewrote their Visual Studio IDE and released it as VSCode, which many of you are using now, I would assume. Google rewrote its Inbox, but kept it working along with the new Gmail. 

So, this is one of the possible options – you can release a new version of your product instead of doing a complete rewrite of the legacy code which actually works.

Refactoring Existing Code or Rewriting Code From Scratch?

Of course, we cannot do without the “refactor vs rewrite” question here.  When doing a complete rewrite, you start the project over from scratch and use the existing code, without changing it, only for reading. Meanwhile, refactoring means restructuring of code. When refactoring, you gradually modify the existing code until you come to a new and better version of it. 

A good question I actually can’t answer is, is it possible to achieve the same result by refactoring the code as by rewriting from scratch? In my opinion, the answer is yes but in some cases, rewriting from scratch is more efficient than code refactoring. Or, it seems to be faster… 

Objectively speaking, code refactoring is considered a safer measure because:

  • Code refactoring is done in short iterations – small changes are easier to plan, test, and release.
  • With rewriting from scratch, there’s a risk that if you stop the process only halfway through, you get into a situation when the new system is not ready yet while the old system stays without updates  – a no-go with money already spent. Less risk is a benefit of refactoring here. 

We Decided to Rewrite. What’s Next?

So, as a software development professional, you feel that the system your team is working on needs code rewrite. This is what I suggest as the optimal next steps in this case.

1. Present a Plan

Have you ever done a home renovation? Do you remember what were your key points of interest then? The cost, the time required, and the quality. Same things here – to make your client say ‘yes’, provide the information about the cost, the time needed, and the quality of whatever you’re planning. 

Cost and Timing

Cost and Timing are tightly interconnected. To provide an estimate as precisely as possible, you need to have an action plan. To create a plan, you must clearly visualise what results you want to achieve:

  • Charts and diagrams of the end result.
  • Comments or a Design Document explaining the benefits of the new architecture.
  • Work stages and an estimate (optimistic, pessimistic, and realistic prognosis).
  • Potential associated risks (for example, if a key team player leaves)
  • How you are going to test the result and who will be responsible for that; a complete testing checklist
  • Estimates including efforts needed to set deployment, data transfer, and user migration

Having this plan at your disposal, you can start talking to stakeholders about rewriting the code.

Quality

Typically, your professional reputation is your quality warrant. If you screwed it once, how can you make sure everything will be fine next time? Winning the stakeholders’ trust is your pass to taking such a risky initiative as rewriting the code on a project. If you get vetoed, it’s likely that the customer is not aware of the value it may bring, they don’t feel it’s worth it, or don’t trust you. C’est la vie. 

2. Provide Calculations

Some people have more trust in solid numbers and statistics than intangible assertions or predictions. But they want to develop a maintainable system, anyway. If your Product Owner is this type, the best way is to present calculations comparing the cost of rewriting and maintenance of the new code, and the cost of a maintenance team for the old version.

effort and cost diagram

The cost of rewriting the code is the easiest to calculate: it is directly related to the time (man-hours) needed to rewrite and roll out the new version. 

The cost of product maintenance has more components: development time spent on new features, time spent on bug fixes, onboarding of new team members, deployment, as well as expenses on resources able to maintain and understand the system’s complexity (Senior vs Junior Developers). 

If rewriting decreases the variables mentioned above – it lowers the system maintenance costs. Also, code rewriting pays off well in cases when you expect a significant increase in users and the old system is not likely to handle it. 

3. Choose the Right Time

Suppose you provided feasible arguments and developed an elaborate plan supporting the need for code rewriting, but the Product Owner still has a decent excuse – “It’s not the right time now.” 

Naturally. Since a project roadmap is planned for months in advance, introducing major changes to it is close to impossible. Also, you are likely to be out of the picture in terms of the project’s financial situation – whether it’s on the verge and struggling to survive or maybe it just got a C Round investment and is rapidly growing. Of course, getting time and resources for starting any refactoring project would be easier in the second-case scenario. 

A good solution would be to be patient and find out the PO’s opinion on when will be the best time to implement your plan. As long as you have a dialogue, you might decide to rewrite at least some parts of the project, for example. For this, try to define the most problematic parts of the system based on bug-report history and user complaints. 

What do my Colleagues Say?

Eugene Bogatyriov, VP of Engineering

What’s crucial is evaluation: you need to provide your project’s ROI evaluation of code rewriting/refactoring. ROI is the time needed for the investment in rewriting the code to pay off. If it’s going to take no more than 12-18 months, the client will gladly agree. I recommend providing your evaluation to each of the stakeholders individually, one at a time, bottom-up hierarchically. There’s an unwritten rule that says that any software product needs a complete rewrite from scratch at least once per decade. This is because technologies tend to get out of date. I had a case of this kind in my experience: it took 3 years and 80 people to rewrite, from scratch, a desktop legacy system for the web.

Nadiia Labyk, Lead .Net Developer

I once worked on a big software project handled solely by one engineer at the time, without any control from the outside. After this engineer suddenly left, instantly, everybody was confused on how to maintain the product. It took about a month for the new engineer to work out the old code – everything was messed up and complicated. We saw a complete code rewrite as the best way to make it a maintainable system. After we got the green light from our customer and agreed on the timing and budget, it took us five to six months to rewrite the code from scratch. The result was beyond expectations: the system became much easier to maintain and we solved severe performance issues.”

Aleksander Subota, Senior JavaScript Developer

I think the “to rewrite or not to rewrite” question is the most pressing for lengthy projects or products having fundamental flaws in architecture (due to developers’ lack of experience or haste, for example). I had such a case in my career – a Cordova-based mobile app with jQuery and Yahoo UI front end that my team took over. It was a nightmare of any software engineer: we could barely implement new features and bug fixes since application modules were tightly bound. The last nail in the coffin was a critical screen scroll bug whose fix in one place caused the same issue in another place due to a conflict between the two libraries that were used. The team suggested rewriting the app as the most effective solution. Having learned the estimates, the PO didn’t really like the idea, but we insisted and started the work at our own risk. It took three months and numerous complaints from the PO about the timeline, but the end result was worth it. We ended up with a stable and predictable UI, we could much more easily introduce new features and maintain the system, the app functioned for 2 more years, and, most importantly, the PO was happy!

Conclusion

In conclusion, I will provide for you this checklist to use whenever you have the feeling of rewriting the code  on your project, be it a web, desktop, or mobile development case, or any other:

  • Make sure you can provide some worthy reasons to rewrite it.
  • Find where your and other stakeholders’ interests overlap.
  • Define the stakeholders’ biggest fears and ways to mitigate them.
  • Prepare a detailed description of the expected result: charts, diagrams, design document.
  • Be ready to explain why code refactoring practices cannot bring the same result.
  • Prepare optimistic, realistic, and pessimistic estimates.
  • Compare the expenses and benefits you will have in the end.
  • Find the best time.
  • Make sure you gain the trust of the decision makers.
  • Try doing the work in stages, starting with the most problematic parts. 

Useful Links

Article​​ Things you never should do by Joel Spolsky

Book Object-Oriented Reengineering Patterns

Wiki-article on rewriting from scratch