Last February, Anghami released a totally revamped version of its iOS application. Since its inception in 2012, Anghami has become the leading music streaming platform in the MENA region, spanning a plethora of platforms and serving millions of users. Apple’s iOS is one of those platforms, and it started with a group of engineers delivering fast results as is the need for many startups. The application kept on growing, with rapid adaptation to business and product requirements, and with multiple engineers coming and going. Each of those engineers developed features and added implementations to the existing codebase.
Years of code being written by different engineers lead to a very complex codebase, which in turn caused more difficulty in adapting and adjusting to new product requirements and features. Even the simplest of changes required more time and effort from engineers to achieve because of the haphazard architecture that the application was built on over the years. Clearly, this was an issue that needed to be addressed.
Given this issue, we managed to release a version of the application that was revamped and felt completely new. What we did to achieve that is a topic that most software engineers still debate to this day; we rewrote the whole UI layer of the application from scratch. Yes, one of the most controversial decisions a tech company could make. However, I will explain to you the reasons for choosing to rewrite a piece of software, and how to manage that task.
Making the Decision
The music streaming industry is booming in the MENA region. Different companies were getting into this market so Anghami had a higher motive to maintain its leadership. We had to separate ourselves from competitors and work harder to give users a better experience. We cannot become stale. Whether there is competition or not, a user expects new features to be added, bugs to be fixed, crashes to be handled; they want a great experience with an application that they use on a daily basis. Therefore, we cannot afford to be slow in our development and maintenance of the application.
How do we handle this? Can we refactor the existing architecture in order to improve it and achieve our goals? The answer was no. Given how much legacy and spaghetti code existed, refactoring that would have been a more arduous task. We had to build on a clean slate that would be founded on a proper architecture with easier adherence to scalability and future changes.
Another reason for taking the decision of rewriting is the growth of our engineers. This reason is one we hold dearly at Anghami, where developers should be exposed to a culture of learning and growing their skills. Faced with an ill-structured architecture, developers would begin to feel demotivated. Their job becomes consistent of mundane work where they have to adapt. They find that improving their skillset is at a halt, and even applying their technical skills is limited to what they have on hand. On the other hand, with a new architecture and clean codebase, they have the means to learn something new. They start to feel that they can apply their technical skills and creative freedom in a faster way. The goal eventually is having our engineers acquire knowledge to better themselves before making Anghami better, and a rewrite would achieve that.
With all those reasons in mind, we decided to take the rewrite path. It was needed to solve those problems we are facing and to help us deliver a better product, and more importantly, delivering better engineers. The task is not an easy one, so how did we end up managing a complete rewrite of our UI layer?
Managing a Rewrite
The first step to take for any rewrite is aligning with the business and product side. It is clear to all that we cannot work on adding new features while a rewrite is underway. It is a sacrifice that has to be made in order for developers to have focus on delivering a completely new polished version. However, this is an application serving millions of users, so if anything is breaking and needs attention, then the rewrite would have to be paused until problems are solved. To shed more light on this, what we did is that we listed what constitutes “breaking events”, which are subscription issues, ads issues, login issues, and playback issues. If a bug happens in any of these subsystems then it needs to be addressed although a rewrite is in the works.
Most of us, especially in a startup environment, are used to rapid development and following Agile practices. However, if you undergo a rewrite, you cannot follow those methodologies, because it will become difficult to manage, identify, and split tasks. The Waterfall model is your best bet for such a large project. You have to let go of sprints and backlogs and whatever Agile principles you are acquainted with. A rewrite follows the good old classic way of planning, designing, developing, and testing.
Since we are going with Waterfall, we have to properly design the implementation of our new UI layer. Most of us would love to start hacking away and write code that shows results. That urge should be thwarted, and instead we had to focus on defining what problems we need to solve, how to solve them, and which architecture would best fit our needs. We ended up on designing a Model-View-ViewModel architecture for the application, which is a standard for most frontend products and had an abundance of references and libraries to help.
We started implementing the basis needed to build on. You should expect that this would be one of the most difficult steps to achieve. This is the cornerstone, so testing and profiling should be done on a regular basis. We were delivering something new, and it was expected from us that it would be better and faster than what we already had. Therefore, we poured all of our focus and effort into it. Once that was complete, we started noticing the results immediately. Adding new screens to the application took a few minutes. Finishing features, debugging, and fixing bugs became much easier and blazing fast. It was a rewarding experience and a step that motivated us to put in even more effort.
Another aspect to keep in mind when implementing a rewrite is expecting refactors to happen. True, we were only rewriting the UI layer of the application, but that layer communicates with different subsystems such as networking, database, cache, and image loaders. Although these subsystems are solid on their own, we had to improve on them to better their inclusion in the UI layer, which ended up improving the performance of the application as a whole.
Now comes the most important aspect to deal with when rewriting, the engineers. A rewrite is no easy task, even with all the above mentioned planning. It will take time and effort, and eventually incur a toll on the people working on it. Although everyone will start with a high level of motivation, they will eventually start burning out when they find how much work is still needed. What we are most proud of is how we overcame such an obstacle. We always kept the big picture in mind. We motivated ourselves as a team by always discussing what we worked on and achieved, how easier it became to implement such and such, how we improved and what we learned in that process. We always expressed gratitude to one another for what we were doing. Simple words such as “Thank You”, “That’s awesome!”, and “Great job” can go a long way. We didn’t shy away from acknowledging our burnouts and taking breaks. If you need day off, two days off, or any other thing that would help you relax and recharge, then you should go for it. The wellbeing of the team, especially mentally, reflects the wellbeing of the product.
After multiple alpha and beta builds, we released the revamped version to the public. Like any major release with a whole lot of changes, there were some bumps and hidden issues that we needed to tackle. Those issues and bugs were solved promptly, and we were able to weed them out in a fast manner. Once everything was stabilized, we managed to achieve a large drop in crash rates. Before the rewrite, we had an average of 5% to 6% of daily active crashes. This number drastically dropped to 0.6%, which in its own shows how much of an improvement the rewrite provided.
The performance of the application improved, and with it the performance of the team. Changes and features that would otherwise take weeks to complete were being done at a much faster pace. Our time estimations improved, our planning and designing skills improved, and with that in mind, it was clear how the rewrite improved the whole workflow.
We onboarded new engineers to the iOS team during and after the rewrite. It was much simpler to explain to them how the architecture of the application works. They felt at ease when being introduced to our tech stack. This is a milestone on its own, where team growth and expansion became more fluid, and it leads to a more productive environment all around.
Should you go for it?
A rewrite is no easy task. Although I detailed how we planned and managed to finish it, it should still be considered as a last resort. If you plan to undertake it, then you need to present a valid justification for its necessity. People will tend to shy away from a rewrite, and you will probably hear the famous statement “Remember what happened to Netscape?”. To be clear, someone else’s failure is not your own. Use that as a reference to learn where did they go wrong instead of generalizing that it will happen to everyone. With careful and thorough planning, managing, and commitment, you can achieve a rewrite with outstanding results that you will feel proud of.
The iOS application revamp was my second rewrite here at Anghami, the first being the rewrite of the whole Android application. These could not have been achieved without the passion, dedication, and support of the Anghami teams behind it. If you are passionate about your product, and dedicated to always making it better, you can pull off delivering an application that millions will enjoy. We will always strive to make our application better, and ourselves better, in order to deliver a product that we and our users are proud of.