Have you ever started working at a new development job, or picked up someone else’s project, only to find that the existing codebase is an absolute mess? I know this has definitely happened to me a few times! As you look through the code and find blatant memory mismanagement issues, the same snippets of code pasted throughout the app, or just downright poorly-designed architecture, you might ask yourself, “Was the last guy an idiot? What was he thinking?”
The thing is, every piece of software is a mess. Developers usually start out with the right intentions, but inevitably on any medium- or large-sized project, the code is going to end up ugly and messy in some way. This happens for all sorts of reasons – requirements change, new features don’t fit into the original plans and architecture, teammates get lazy, or (often) management places heavy time restrictions on development.
When faced with these issues, those of us who take pride in our craft get a strong urge to scrap the existing code and rewrite the app from scratch. After all, we can do it better, right?
Well, maybe. Most of the time, I would suggest that the answer would be a strong, resounding “No!” But occasionally, you might find yourself in the predicament I found myself in with The Benefit X-Change: where it feels like your only real option is to start over and do the project right. Hopefully, through this example, I can make it easier to understand when to rewrite code and when to simply update it.
Why You Shouldn’t Rewrite Your App
The vast majority of the time, it’s not a great idea to start from scratch — and there are some very good reasons why that is the case!
1. It’s a HUGE Time Sink
Rewriting an app from scratch might take six to eight months – and that’s for a small- or medium-sized project! If you haven’t launched, that is six to eight months (or more) where the app is not in production and is not generating revenue. Even if you have, that’s still time that’s not being spent focusing on improving the app or growing the business.
Chances are that your app has an actual purpose, such as “making money.” Unless you’re just building something for fun, the primary goal is to get the product to market. The sooner you can finish your MVP (minimum viable product) and begin selling it, the better. Adding features or fixing bugs takes precedence over even refactoring existing code, nevertheless rewriting the whole codebase.
By going back and rewriting existing code, you’re pushing back your launch date. This also pushes back your time to freedom and wealth (or reaching whatever goals you have set for this project) and stretches out the time that you must live on your current salary or savings. Furthermore, it reduces your available opportunities – the sooner you launch, the sooner you can find out what the market thinks about your product. That’s where you want to get to – so you can focus on and capitalize on the good things you’ve done, and use the responses and advice you get from your customers to fix, remove, or redesign what they don’t like.
That’s why there’s so much talk about technical debt in the startup world — messy code that “works” but must be fixed later.
In some cases, putting off your launch date might actually cause your business to fail. It gives your competitors a chance to get a foothold on the market, and it gives your customers time to forget that you exist. Alternatively, the market might change or grow – and while you’re focusing on rebuilding the base of your application, you might not have the chance to pivot with it.
2. Existing Code Has Been Tested and Used
As Joel Spolsky wrote a while back, if your app has been in production for a while, chances are it has been tested in all sorts of ways that you couldn’t even imagine during the development phase. Customers have broken the app countless times, and support techs have patched it together and fixed the bugs. This produces a (relatively and acceptably) bug-free application. By rewriting the app from scratch, you’re going to introduce a lot of new bugs that don’t exist in the current iteration – many of which might even be bugs that existed before and have been fixed once already!
3. The Original Developer Probably Understood the Domain
Chances are, the original developer was around for a while before he began architecting the app, and he probably understood the problems it was supposed to solve quite well. Furthermore, even if you do understand the domain as well as him, you’re likely to fall into many of the same traps that the original developer did, simply because the problems might not have been apparent during the design stage.
Have you ever been working on an app, only to encounter a problem midway through where the most obvious solution does not fit well with your existing architecture? The best way to solve it would be to refactor much of the existing app to allow you to design this one feature right; however, that’s not always a reasonable plan of action, due to time/budget/other constraints. Rather, you might find yourself making a quick “hack” – the resulting code might be very messy, but it works well and allows you to move closer to your goal.
Even worse, you might encounter a bug, and due to emergent behavior, you don’t know why it’s happening. But by adding a simple print statement (or even a comment), the code might execute correctly! So you just add a quick comment (
/* magic, do not touch! */) and go about your business, promising yourself that you will return and fix the problem later!
These are all things that happen (often) during software development, and they happen to all of us. It’s foolish to expect that your app will be perfect when the existing code is not; chances are, it’ll end up with the same sort of issues!
Why I Rebuilt The Benefit X-Change
Despite all of my warnings above, I decided to rebuild The Benefit X-Change anyways because I believe that my scenario was different (don’t we all?). I wasn’t developing within an existing, working app that was already in production. I was working with an amalgam of one-off code snippets and third party apps, messily arranged in such a way that they worked very clunkily at best. It was a nightmare to develop new features, it was a nightmare for the app administrators, and it was a nightmare for our alpha customers to try and use.
In fact, I initially attempted to continue to build onto the existing app to make it better, knowing that rewriting the codebase is a huge no-no, but it finally got to a point where I broke down and couldn’t deal with it anymore. There were just too many glaring issues that could only be resolved by a nearly complete rewrite.
1. The Existing Code Was Not In Production
The Benefit X-Change had a couple of alpha customers, but it was not tested, and it was most definitely not “bug-free.” It was a much smaller app with only a few customers at the time. There was not very much time or manpower spent on actual development up to this point – instead, the app was really just a few existing plugins and third-party apps that were tied together using a central Joomla-based website. Much of the work that the app “did” was not really automated and had to be done by a person behind the scenes, which cut into the time we could spend to actually build upon or market the product.
What this mean was that a rewrite or a major change to existing functionality would have very little impact on anyone else – we didn’t have many customers and no one was reliant on any specific behavior the app was exhibiting at the time.
2. The App Was Barely Architected
There was no design effort to begin with. Nearly every feature in the app was a function of “oh, we need this feature? Let’s create a quick patch to add it in.” Eventually, this resulted in a mess of one-off plugins that were essentially self-contained apps themselves. Data was passed back and forth between plugins through the Joomla framework, and plugins did not reuse existing code or features – even when they existed side-by-side on the same page!
Now, Joomla and WordPress are great frameworks for simple websites that only need to have very generic functionality – blogs, membership sites, etc. However, once you start introducing complexity and customization, it begins to take a lot of extra time and effort to build even the simplest of features. It was even worse with the alpha version of The Benefit X-Change, where designing a new feature involved reinventing the wheel each time — each new plugin increased the complexity and the difficulty of adding new features exponentially.
To get from “alpha” to “production” with this app would have involved a major effort to refactor and re-architect the existing code to make it cleaner and more easily extensible. All of this would need to be done before we could even think of automating existing tasks or adding new features. Of course, refactoring may have taken less time than rebuilding from scratch, but it would have still taken several months to complete. And even then, we would still be developing the app on the Joomla framework.
3. I Was the Original Developer
While it was my father who originally set up the third-party apps and tied them together with a Joomla website, I was the one who was doing much of the customization, programming, and maintenance on a contract basis. This meant that I already understood the domain, the problems, and exactly what this app was supposed to do to solve them in detail. I had also encountered issues with the system already, and knew what to expect during the course of development.
Of course, there would likely be other issues that would arise, but they were likely to be problems that I had not encountered before. These problems would probably be the sort that would pop up regardless, whether I decided to refactor the existing codebase or rewrite from scratch.
Furthermore, much of the code could be reused. I had developed it originally, and so I would be able to understand it well enough to copy-and-paste it from the existing codebase into the new one, refactoring it along the way not only to fit in with the new framework, but also to make it reusable and extensible. In this way, rebuilding the app would not be truly starting over from scratch, but rather a sort of pseudo-rebuilding that involved mostly refactoring into a coherent architecture and porting frameworks. The tasks that would truly involve building from scratch would be framework-related rather than domain-related functionality, such as registration and authentication – features that most frameworks make very lightweight and easy to build.
This is actually the primary reason I rejected the idea of building the app using Ruby on Rails. The complex “web-app” functionality of The Benefit X-Change lends itself to a Rails-like architecture, so it seemed like the perfect tool for the job. However, I would not have been able to reuse PHP code in a Ruby app, which would have likely increased the time to launch even more. Instead, I opted for a Rails-esque PHP MVC framework, eventually settling on Laravel.
4. The Secondary Goal is Understandability
While the first goal might be to get the product to market quickly, the second goal is to be able to build support and business systems around the product to allow it to grow and be maintained beyond the scale of what I can do myself and allow me to focus on the entrepreneurial tasks rather than the technical ones. Once the app is in production, we will need to hire support personnel to fix bugs, and they will need to be able to understand the codebase well enough to do so. Developers will also need to be hired to add new features and update existing ones.
This will obviously require more than just “readable code.” I have plans to create extensive documentation and even screencasts to explain the functionality of the app and its codebase. However, those things are out of the scope of this article, and will likely be addressed in another blog post (probably when I get around to doing them).
What it does mean, however, is that the code must make sense. Fixing one feature should fix it for the entire app – support techs should not have to update the same code in multiple places very often. This means not only following DRY (don’t repeat yourself) principles, but also decoupling features and functions from each other. More importantly, the flow of the functionality throughout the app should be the same or similar for every function – there should be some sort of consistency, so that even if a developer can’t find documentation on a specific function or snippet of code, he should still be able to work within and around it, having reasonable expectations of what it is doing.
5. Removing Points of Failure
As I said, the existing app made use of plenty of third party apps and plugins, and some of these had costs associated with them. Of course, this isn’t necessarily an issue as long as revenue remains greater than expenses; however, this forced us to increase the membership price to cover the monthly fees associated with the apps, and we did lose a few sales. Since I wanted to rebuild the app anyways, it presented a great opportunity to remove these restrictions. By removing the dependencies on these third party apps, we could keep costs down and reduce our prices to find a sweet spot, while simultaneously increasing our margins. Additionally, maintenance and support would be easier with access to the code – some of the plugins and apps we were using were not even being actively maintained, which would lead to issues when bugs or broken functionality popped up.
While this one isn’t specifically a good argument for rebuilding the app, it was definitely a point of added value.
Rebuilding The App
Rewriting the Benefit X-Change from scratch using a developer-oriented framework like Laravel probably did take a bit longer than it would have to simply refactor the existing Joomla application. I had originally anticipated that it would take about six months to rewrite the application from scratch, and four or five months to refactor the existing codebase. It ended up taking about eight months, but those couple of months of extra effort were well worth it in the end, as the new version of The Benefit X-Change is orders of magnitude better than the alpha version – from the perspectives of both the developer and the user! It will probably save time in the long run, as well, since new features can be implemented far more easily and quickly while adhering to DRY principles.
In the end, I am very glad that I did this. Given the option, I would do it all over again the same way (possibly with some minor tweaks to the application’s architectural design, but hindsight is always better, right?). The net effect of redesigning the application from the ground up was that it is much easier to maintain and build upon, and the interface is much simpler and less clunky for the end-user. Plus, there’s the added bonus that I can have the emotional satisfaction of owning the work done (although this is by no means a good reason to actually do the work unless the extra work provides real value in some way).
Should You Rewrite From Scratch?
So, when presented with the problem of whether to rebuild an app from scratch, you should ask yourself:
- Does the existing app work well enough? Has it been used and tested? If so, rebuilding it probably won’t provide you much additional value, and may create headaches in the form of new bugs (or bugs that were previously fixed!)
- How big is the app? (alternatively: How long/how much work will it be to do this? Have a good, conservative estimate, and then double that!) For smaller projects, it might make sense to redesign and rebuild. Any medium or large project should not, however – especially if it’s been in use or in production for months or years! The larger a project is, the more effort it will take to rebuild – and that kind of time, money, and manpower can be put to better use growing your product or marketing it: both activities having a much more direct effect on your bottom line!
- What is your understanding of the domain? If the existing app was written by someone else, they probably encountered issues throughout development that you probably couldn’t even dream of right now – and those issues likely helped shape the architecture of the code. In fact, the codebase is probably messy because of those issues. If you were to rewrite the app as a newcomer, you’d probably encounter those same issues, and the net result would be that your new codebase would be as messy as the original. However, if you have a deep understanding of the domain and its various problems – or better yet, if you were the original developer and you know specifically how you would have done it better in hindsight – then you might be better equipped to build a better version from scratch.
- What other real value would be gained from a rewrite? Seriously think about this. If it’s just so that the code is a little cleaner, you’re probably not going to get a net gain from rewriting the app. If this is the case, consider refactoring snippets of existing code to make them easier to read and maintain instead.
If you can’t answer all of the questions above favorably, I’d suggest that you think long and hard before diving into a codebase rewrite. The vast majority of the time, a rewrite is not a good idea – at best, it is a huge time sink, and it could even be the difference between getting your product to market and having your business fail outright.
But ultimately, it’s up to you. You can use my advice to influence your decision, but whether to rewrite your app ends up being a subjective decision – only you can decide if it’s truly worth it.