How we rewrote a 4-year-old mobile app in 6 months

Gustavo Costa
Passei Direto Product and Engineering
12 min readJan 16, 2019

Half a year later and after lots of plannings, retros, design reviews, checkpoints and other tons of meetings. Now I can take the time to write down how was the entire process, what we learned on the way and a few reflections from the product side of this project.

Who we are?

Passei Direto is an student network with over 15 million students sharing study resources, course notes, test preps, homework help and more.
Users can access our product through the website or the mobile app (Android / iOS)

Why rewrite the apps?

Our mobile team had only two developers, one for iOS and another for Android. That means, every time we were going to build a feature, we had two different products to deal with (Androidd & iOS). Besides that, features on our website were being shipped way faster.

At the end with this situation repeating for a while we had:

  • The apps didn’t have the same features as in our website and even the look and feel was out of date. In addition, our Android and iOS app also had significantly differences between themselves.
  • The constant feeling of “…Mobile is slow / This feature will be shipped later in mobile / We can think about this in mobile later…”, although it was a fact, it was detrimental to the team’s self-esteem.
  • Both iOS and Android projects were in need of lots of refactorings. It was difficult to have time for technical debt without slowing down the pace even more. Balancing tech debt, bugs, improvements and features was a big problem.
  • Re-work due lack of alignment between mobile and website.

So we started to give a look to a few other technologies and React Native was the one that seemed more promising. One of the main advantages, write one code that could be used to both apps...

Hands on React Native

None of us had experience with react before so, while still working with the native apps, we researched more about it and developed a small proof of concept. The idea was to learn and see if rewriting the app in react would be possible and bring satisfactory results.

At the end, after reading articles, benchmarking and testing we didn’t find any significant reason to give up of the project (although we also weren’t 100% sure react would be good and work as expected). The problem was, when to start it?. It was easily going to take a lot of time and we wouldn’t be able to maintain the native apps in parallel with the react app.

Going all-in

The react project was in the paper but not sure when we would do it. Then an opportunity has arisen with a bigger project we were starting in the company. The back-end, API’s, databases and so on would be refactored. Meanwhile, the web team would refactor their front-end so they wouldn’t have important releases with new features for a while. We were in June and all of these projects should be launched still in that same year. All should be deployed together (due the back-end changes and everything being attached).

At that time we had hired one more dev for mobile, so we had three devs and our options were:

  • A: Only adapt our apps for the changes in the back-end and use the rest of the time to speed up a little bit with the missing features for both iOS and Android.
    We would be ready to launch in time with the other teams and also deliver some new features but keeping the native technologies.
  • B: Completely stop developing for the native apps and go all-in react native. Rewrite the new app already considering the changes in the back-end that would go live months later.
    It was a little risky because maybe we could not finish the app in time to launch and as I said before we weren’t 100% sure if react would in fact be good.
  • C: Mix A+C, adapt our apps for the changes in the back-end and use part of the time, not to build new features but to build the new react app.
    We probably wouldn’t finish the react app for complete until the end of the year and we knew it would be a problem to continue working on this the next year with all teams already done with their refactorings.

We decided to calculate and assume the risk to go with the option B, go all-in with react and make sure we had a new deploy coming out still that year. Maintaining two native apps (iOS & Android) at the same time wasn’t working well. Next I will describe how we planned and managed the risk of the project.

Project planning and Risk management

Planning a project is an interactive process and it’s always in review but there were a few things we did on the beginning that helped us to have a good overview of what was to come.

Research and Analysis

On the beginning the devs spent a few days doing a deep research on react native, trying to predict possible mistakes we could make, what were the main challenges and how to avoid problems that could slow down our progress.

Since no one of us had a good experience with the new technology, we knew we would inevitably need to refactor the structure of the new app a few times before doing it right, so it was good to use part of the time on the beginning to study more and minimize possible errors.

Planning

Meanwhile, from the product side I was acting more as project manager and product owner. While the team was busy with the researches I used the time to scratch our planning and prepare for action.

First thing I had on my mind was prioritization. We had an app already in production and the new app should have the same features and functionalities, at least the most important, the ones who creates more value to the user. So I mapped every screen we had on the app, every single feature and put everything together in a presentation. To have a good big picture I grouped them in modules.

Overview of product specs that should be prioritized.

Later, I looked individually to each module, screen, feature and took notes of important details or characteristics that couldn’t be missed. This was good because the rest of the team would also check it later and we would need to discuss.

Prioritization and Estimatives

With the big picture ready it was time to estimate effort and prioritize. We did a few meetings with the team, going for each screen and getting a roughly estimative of its complexity. Each member exposed the effort on that and its reason, then we compared with the other members and if it was too different from each other, we tried to find out why and get in an agreement, always trying to think in a conservative way. In addition to that, we also used one main feature as a basis for the other estimations, this way we knew there was a fair balance among the tasks. During this proccess, often checking to see if, in a high level view, it was making sense.

The end result was a spreadsheet with a summary of the tasks, how long it should take and the weeks until the end of the project. This spreadsheet was updated basically everyday by me throughout the entire project, so we could see what we were spending more time, what was going faster and so on…

Example of a spreadsheet to be prioritized and organized throughout the development process.

Risk management

In order to make sure we had the right estimative of effort and the most important things delivered first. After having the first estimation done we also added some “fat” of 30% to 50% trying to minimize chances of missing deadlines and unexpected things that may could happen on the way.

Macro and micro prioritization was another key initiative that helped us to minimize the risk. Since we have everything split into modules, I organized their order and this was the macro prioritization. We ordered it in such a way to respect its dependences and getting first the things that were more questionable, so if we had to face any big problem, it would be better to face it earlier, instead of getting stuck with this at the end. All the modules had important core features for the users so I had to have it in mind the need to going throughout every module throughout the development proccess.
The micro prioritization was inside each module, focusing to deliver the main features of that specific module, the things that were the most important to the user. If we reached a deadline, I would analyze what was missing to finish that module and skip those to the end of the project if they weren’t essential or more important than what was to come.

The thing is, each module is a mini-project. if we try to make it perfect, we will stay forever working on this and at the end only one would be developed, that’s why we had to know when to stop working and keep going.

The idea was to focus on the most important features of every module first and later after having the core of the app working, we could work on what was skipped. At the end this worked very well, if we hadn’t used this approach we wouldn’t be able to finish all modules.

Deliverables

We had only one deploy that would be at the end of the project and in sync with the other teams. Instead of developing everything and use the last few weeks to validate the entire app, we split our modules in versions and continued to run our sprints as usual. Every single flow or action that had to take the user to a non-developed yet situation, we would show a temporary 404 screen. So we knew that at the end of the project no 404 screen should be on code anymore.

The first version we had app structure and login, this was developed and validated. After validation we would consider this version as completed (although after login a 404 screen was shown) with the difference that it wasn’t deployed to the end user. It was just internally for us to know that that module was done.

At the end of the project, Q&A shouldn’t have too much effort on validating the entire final app since the validation occurred throughout the development and the modules were tested already.

Learnings, challenges and unforeseen

In this section I will describe the learnings, challenges, unexpected things that happened on the way and how we dealt with them.

The beginning was marked by two factors: Learning curve and refactorings. Since none of us had experience with react before, everything that we were building was learned shortly before, no matter how hard we try to do the best we can the first time, usually we will find out that wasn’t the best way. Therefore, the first weeks we had to refactor some things quite often.

We also realized that due the learning curve and first-time build of every component, the first features were taking more time to finish, which was going way over our deadline sometimes but later on we could reuse them and that speeded things up a lot.

After two months or so we could see this reflection on our schedule, some features taking a lot of time, others taking less and it was starting to get visible that we would need to speed up more to be able to finish in time. Fortunately we were able to shift one developer from another team to help us in the mobile project. It was his first experience working with mobile as well but no problem at all, the core of the project was well built and in a matter of days he was able to understand its structure and the technology.

A few weeks later the back-end project that was going on with the other team was well advanced and we needed to adapt our services to the new API. At this time we also had the opportunity to have one more person joining the team and he could exclusively work with our API so this helped us a lot.

To summarize:

  • Learning curve was visible and felt by everyone. First time to build anything takes time while the other times are way faster, this was also due the need to build anything from scratch initially, later the reuse of components help a lot.
  • Refactoring more often on the beginning, especially with the app structure which is critical and more difficult to change later. At the end things were clearly more smooth.
  • Foreseen the need of more members in the team to speed up everything and delivery on time.

Launching the new app

Since we would deploy three big projects together we thought it could be a little more difficult to handle the bugs and errors post-launching because we would have to identify what was causing what and the source of the problem could be one of the three projects so we focused in develop the new app also working for our old back-end. It means we would be able to deploy before the other projects, detecting and solving problems earlier.

We developed our new API supporting both situations, before and after the deployment of the other projects.

Here’s the sequence of events:

  1. Deploy of our API to old native apps. Our new API had a few services that the new app would require so we deployed the API first to see if we would have any problem or bug.
    We did have a few problems, so we solved and it was fine!
  2. Days later we deployed our new app only for 1% of the Android users. Same as before, with this we could start getting the problems and fixing them upfront before the deploy of the other two big projects that the other teams were working on.
    Throughout the days we increased the % of Android users having access to the new app.
    Few days before the deploy of all projects, we sent the iOS app to apple review and also released it to everyone.
  3. Finally the last deploy was together with the other teams. All the services were shutdown, website and mobile stopped. Our users saw a screen informing about our maintenance.
    When the migration of data from the other teams were done, everything went online again.
    Our mobile users now were seeing a screen asking them to update the app since the old native app wouldn’t work anymore.

Of course we had some problems with specific devices and isolated issues but nothing that couldn’t be fixed soon. I am very satisfied with the final result, for a project like this that was the first one for me and a new technology for the whole team I think we did a good job.

I’m sure that not only me but everyone involved learned a ton and for the next projects we will perform even more.

It’s important to emphasize that none of this would be possible without the support and comprehension of my team members, our friends from the other projects and the whole company itself. What we’ve done was a real example of fellowship and teamwork, the challenges I mentioned here were just a few of the many others we had during the projects.

Special thanks to Antônio Cláudio, Bruno Rodrigues, Carla Vitorino, Ellis Carvalho, Pedro Diniz, Pedro Fernandes and Rubens Lopes 👏👏👏

Now, check it out the final result on Google Play or App Store

--

--