At Chariot Solutions, we have been developing mobile apps since the release of the first iOS SDK in early 2008. Back then, all app development was new. A lot of developers flocked to mobile development as the new shiny object. As is the case with all new software development stacks, some apps were developed better than others. After a few years of this, mobile development projects weren’t always about developing new apps. A good number of projects were around rescue missions. We would hear things from our clients and prospects like “Help us improve the performance of our apps” or “It’s almost impossible to add new features to our app”. As a result of these comments, our first task on the project was to perform an evaluation of their code base. This led to various recommendations based on what we saw during the evaluation. Sometimes we would recommend some refactoring to improve the overall stability, maintainability and extensibility of the app, while other times we would recommend a full rewrite.
We realize the negative connotation that often comes with the word “rewrite”. It has some serious impact on the business at hand. In 2000, Joel Spolsky famously labeled it the “single worst strategic mistake that any software company can make”. While that article makes a lot of great points, my experience in the mobile space differs. There are certainly different ways to go about rewriting an app. You could start refactoring pieces of the app until eventually you have a “new app”, or you could rewrite the app from the ground up. The former can be difficult to do depending on the level of technical debt in the current app. A lot of interdependencies can make this approach very difficult, if not impossible. The latter can delay implementation of new features, which can have a near term business impact. The balance of this post will be spent reviewing some real life examples of rewriting an app versus reusing the existing code base and improving it while iterating on new features.
This client had iOS and Android phone and tablet apps that acted as the user’s primary interface into their system. Their Android app was developed in house while they partnered with a company to develop their iOS app. They came to Chariot Solutions because they had a lot of difficulty adding features to their iOS app and its performance was unacceptable. We performed a code assessment on the iOS app and because the code was so poorly architected (think big bowl of spaghetti) we recommended a rewrite. Client #1 agreed, but was not willing to take the same path for the Android app. It took a team of 2 iOS developers about 3 months to get the iOS app feature-equivalent to the “legacy” iOS version as well as the Android app. Both teams had resources with similar levels of experience. Due to the improved quality of the code base, Chariot’s iOS team of 2 developers was able to implement features faster and more reliably than the Android team of 5 developers. That’s a 60% reduction in ongoing development cost, not to mention the reduction in time and cost required for bug fixes in addition to the soft benefit of a greatly improved user experience in terms of reliability.
Client #2 was building a new system and needed an iOS and Android app that served as the interface into this system. They had existing apps that were going to be repurposed for this new system. Client #2’s Android app had a UI that was fairly well fleshed-out and really needed to implement the business logic and server integration in order to get to market. At least this is what everyone thought, including Chariot Solutions. The iOS app had a very generic approach to its architecture, using metamodels, where everything is represented in an abstract way to provide maximum flexibility. This served to be very complex for developers to understand, extend, and troubleshoot. Also, this code base was implemented several years earlier following older design patterns, using code that would compensate for parts of the SDK that weren’t available yet, and written entirely using objective-c. It also had a significant amount of technical debt. After working on this code base for a while, we realized that things were taking much longer to develop then they should have. At this point, we recommended rewriting the IOS app, but continuing to use the current Android code base.
It took 2 iOS developers approximately 4 months to get feature equivalent to the Android app, which was continuing to implement new features. The Android team consisted of 4 developers. So in this case, a 50% reduction in development costs. As with Client #1, due to the improved quality of the code base, the time to implement new features on iOS was significantly quicker than on the Android app. There was also a significant reduction in bugs as seen in the number of crash reports. The iOS app consistently had almost no crash reports. As we got further into the project, we realized that we should have rewritten the Android app as well. Features were taking much longer to implement then they should, and we were seeing more frequent bug reports. Fortunately, the client was willing to allowed us to take a pause on new feature development and allow for some significant refactoring of the Android app to remove the technical debt and improve stability, maintainability and extensibility.
Where many clients wouldn’t even consider rewriting an app, we have some impactful cases where the benefits of doing so where obvious. Clearly this is not an easy choice. There are many things to consider such as:
- The resources that make up the development team
- The condition of the current code base: A tangled mess will be hard to maintain and extend long term
- What are the current pain points:
- Code complexity
- Tech debt levels
- New technology to improve the quality and understandability of the code
- Level of feature changes required in an upcoming release
- The short (and potentially long) term impact to the business
If you do choose to rewrite, consider the following:
- Don’t reuse portions of current code unless it absolutely makes sense
- Take a ground up approach and do not be impacted by “old” design choices
- Keep it simple (no meta designs)
Rewriting isn’t always the answer, but we have some great success stories where it has worked. This decision cannot be made from a single perspective. It’s not just about the lost time for new features or the immediate cost of rewriting or the reduction in technical debt or getting to use new architectural and programming tools and languages. This decision needs to be made from a long term technical and business perspective.