By James Rochabrun, Software Apps Engineer
Launching Yahoo Mail 6 for iOS required us to re-architect our navigation system, while also migrating from Objective-C to Swift without negatively impacting the experience of our production app.
With 4.6 stars in the App Store and millions of daily active users, we maintain a rigorous system that allows us to maintain our low average crash rate of just 0.02%, so this was an interesting challenge.
From an engineering perspective, this was not technically a re-write but rather a re-implementation of our container and navigation system, and re-skinning of various existing UI components. It was the perfect opportunity for us to gradually move away from Objective-C and old school frame-based layouts and adopt new Apple technologies like AutoLayout and Swift.
Navigation through the old Yahoo Mail App is initiated via a “Hamburger” menu. In our new app the most important content from your email is now divided across different tabs at the bottom of the screen, while key components like Search and Compose reside in the top navigation, and the folder switching function has been brought into the Inbox button.
Early on in the process, only a few engineers were tasked with working on these changes to set base infrastructure, leaving the majority of the team focused on maintaining our app in production. This approach was key because we could ensure that our production app was not impacted as new features were built. As the year went by, more engineers were moved into the project until we were fully staffed on building out the new Yahoo Mail. We divided our entire build and deployment process into 5 phases:
We built a skeleton app with key features in place such as account management, instrumentation, and database support that lived in a new target alongside our existing app. This way, we could share files and as new UI components were completed, they'd only be added to the new skeleton app.
In the meantime, we could readily prototype our new navigation in a lite version of our app and share the experience easily with product and designers. This later helped our engineering team identify some customization limitations in native iOS components.
Our entire navigation system was handled by just one sided menu and in code, our approach turned out to be equally monolithic: everything was handled by a huge container controller - almost 4,000 lines of code!
This was a great opportunity for us to rethink the architecture, so we created smaller containers that allowed us to easily present our new smart views (e.g. Attachments, Deals, Groceries, Subscriptions, etc.) from the bottom navigation bar. And we also implemented a "Router" system creating small helper classes that encapsulated our navigation and custom transition code, greatly improving our navigation system’s reusability.
So at this point there were 3 sets of files:
In this phase, we started to build out our new screens and features while keeping in mind the strategy of “reuse as much as you can.” In doing so we had to improvise and devised 3 basic ways to reuse our existing code:
Code duplication was kept at a minimum, and any refactored or new code was written in Swift.
Ready for Testflight! The plan was to release this as a brand new app with its own app id, provisioning profiles, and certs, etc. This app would not actually go out to production, yet, but allowed us to test with real customers. This went well until our PMs threw us a curveball by introducing the following additional requirements:
Basically we would have to do a gradual phased rollout and, most importantly, we would need a way to turn off the new experience if necessary.
At this point, the engineering team came up with a solution:
Our app was ready to change its colors at any time. We released to 2% of our users in production, made sure their feedback was addressed, fixed crashes and blockers -- and finally were ready to scale our release gradually to 25%, 50% and finally 100% of our users. By the way, our app size only went up 5% and there was no performance impact at all!
This is our future strategy, one we are in the process of implementing. In this phase, we plan to ditch our old target code. When done, both of our targets and functionality will be the same.
So what were the results of all this work?
If you didn’t already, go to the App Store and give it a try. Let us know what you think by submitting feedback via the app.