When Refactoring Is Better Than Rewriting

In my last post, I posited that too many organizations choose to rewrite an application or component rather than invest in making it better. My belief is that this decision gets made because making the existing system “work” (whatever this means in context) is too hard. My concern is that the next time you write it, it’s also going to be hard. It might not be hard in the same way - you may have moved “the hard”. Regardless, you may not ever get to done.

I’ve gotten feedback from some colleagues that this might be too harsh a characterization. In fact there are systems that are so bad, the smart investmest is to throw them away and start over. These systems, however, are a bit different. These systems have likely accumulated tremendous amounts of technical debt. There is a subtle, but crucial difference between these two conditions. Most (all?) software systems have some amount of technical debt. It’s how much that governs whether you should throw it away. Consider the chart below.

'A silly made up chart'

This chart is completely contrived, and not fashioned from any real data. It’s primarily built from experience. As Martin Fowler states in the aforementioned article on Technical Debt, it’s difficult, if not impossible to measure. That said, most teams will have a sense of how much technical debt they have. The “amount” will generally be estimated by how difficult it is to make changes to the system. A system that is incredibly difficult to change will have high technical debt, and one that is fairly easy will have lower technical debt. This is not a hard-and-fast rule, but will generally work.

Back to the chart. Suppose we have two systems that are both 80% complete (another contrived number, but it will work for this example). The system represented by the blue line has accumulated massive amounts of technical debt. We can assume that changing this system to get to 100% complete will take a long time (and in fact, might be impossible). On the other hand, the “green” system has accumulated moderate amounts of technical debt. It’s a safe bet that changing this system will be a bit more straightforward.

Referring to my last article one more time, regardless of how much technical debt exists, finishing any system will be difficult. The work that’s required is simply hard. However, if the technical debt is not excessive, you’re better off doing the hard work.

An Example When Not To Rewrite

I can think of several examples where I’ve seen companies go down the rewrite path and subsequently regret it. Confidentiality prevents me from being too specific, but one example in particular is fresh in my mind. This particular company had a very high volume web platform, with multiple customers white-labeling. The platform had grown over a number of years. Rather than figuring out how to make it an extensible product, it became a jumble of code, where each customer’s customizations were sitting along side every other customer’s. This led to having multi-1000 line source files, with one code branch after another (if customer x, if customer y, if customer z, etc). The company had large growth plans, and wanted to add many more customers. Additionally, they wanted to make changes easier. When considering how to fix the situation, there were two factions.

The first faction suggested some targeted refactorings. This team’s reasons: the existing system was already scaling VERY well, and with the volumes they had, trying new technology was fairly risky. They also felt that the product itself, while having some issues, was not fundamentally flawed, and just needed some investment.

The second faction wanted to either buy a replacement product (or acquire a competitor) or rewrite it. Their position was that if the team could have made the changes, they would have already. By pulling in something new, they could solve the problems from the ground up.

The second faction won. It was not a pure rewrite. The company wound up acquiring the software assets of a competitor, and then needed to change it and customize it so it would do what the original platform did (and hopefully far more). The project was challenged from the beginning. The asset was in a new technology, and the company needed to train its employees. Additionally, the employees knew what the existing platform did, how it worked, how to change it, how to test it, etc. The new platform was different, and so the team lost a great deal of time figuring all of that out. Finally, it turns out that the new platform didn’t have all the features it needed to, in fact it had far less than the original platform, and had serious scaling issues.

As far as I know, it was a significant financial investment simply to buy the assets. I’m no longer associated with this company, but it was a 3+ year project to get it live, based on original estimates of 1 year or less. I’m not sure it was ever completed.

A Rewrite

This particular company had a Windows desktop application with a significant user base. It was very feature-rich, and while its user interface left something to be desired, it met its customer’s needs. It was written in .Net, C#, using WinForms. Several members of the team felt that the technology had aged to the point where it was no longer practical to update it. Additionally, it was a start up, and the code had acquired a great deal of cruft. Changing it was scary, and the company only had one developer that was fully trusted to make changes.

They engaged in a full rewrite of the software, using the latest and greatest .Net technologies, including WPF and XAML. They architected it properly, used good practices, although they could have written more unit tests. The initial project launch was unfortunately not very successful. The prior system, while it had aged, was complete. Customers were happy with it, it was fast, it was reliable. The new system had some performance issues, was not functionally equivalent, and was unstable at first.

It took several months of focused and intense work to get this product to done, and it was very, very hard. Rewriting the original version was the right choice, but getting to done a second time was difficult. The organizational memory of how long it took to get the original product to done had faded. No one remembered that the prior version took years to get stable. By the way, the company’s customers also didn’t have that memory. They had an expectation of function and quality that was badly missed in the new product.

In Summary

Even when it’s the right choice, a full rewrite is hard. When it’s the wrong choice, it’s generally very wrong. I’d recommend taking the time to analyze the technical debt in your system. If possible, get hard metrics, maybe by using a tool like Sonar.

A full rewrite implies a big bang launch to production, heavy investment, high risk, and potential disruption to customers. If it needs to be done, so be it. But if it can be avoided, perhaps it should be.


© 2024. All rights reserved.