2018-11-27 00:13 |
The Coinbase Android team accomplished two big goals in the last year. First, we shipped a newly redesigned Android app. Second, we’ve made many improvements in how we develop on Android. In this article, I’ll give some insight into the technical improvements that we made and why we made them.
At Coinbase, we strive to ship high quality updates at a rapid pace. At the same time, we need to make sure that the code can effectively scale with the product and team. Because of this, we have to ensure that our code is easy to work with and simple to understand. We also want it to be easily testable and extensible. To accomplish all of this, we took a fresh look at how we structure and write code.
MVPLike many early stage companies that need to move fast, the initial version of the app didn’t have a lot of thought behind how code should be structured and organized. We wanted to choose an architectural pattern that would allow the code to scale with the product and the team. We experimented with a few options but ultimately decided that the MVP pattern made the most sense for us at this stage. The following reasons explains why:
Improved testabilityBetter separation of concernsChanging layouts is easier, important for things like heavy AB testingCode structure scales better with a growing team and can reduce code conflictsAllows easier migration to KotlinRxJavaSome of our goals were to simplify, modernize, and clean up our code. We found that RxJava was a great tool to help us reach that goal. Some of the ways that it helped were:
A clean alternative for AsyncTaskReplacement for EventBus which improves speedCombining actions is much easierReplacement for the listener pattern which helps decouple code and improves reusabilityBetter state handling with clearer scope and immutable propertiesInvites more asynchronous coding and simplifies implementation of thatRxJava isn’t without it’s faults. We also found that there were some drawbacks. Namely:
Learning curve is high and increases ramp up time for those not already familiar with itDocumentation is decent but examples are lacking onlineUnhandled errors and back pressure can cause exceptionsDebugging can be tougher with unhelpful stack tracesUltimately, we decided that the benefits outweighed the costs and are now seeing it pay back in dividends.
Dependency InjectionOur code was originally using the now defunct RoboGuice as our dependency injection framework. Because of this and other reasons which I’ll talk about in a bit, we made the move to Dagger. Among having active community support and being battle tested, some other benefits we saw were:
Predictable components and component initialization with less boilerplate codeComposition over inheritanceMore performant because of compile-time injection and elimination of reflectionTesting advantages, allows easily mocked API responsesIt’s clear that moving away from RoboGuice was a no-brainer.
Single Activity and no FragmentsDuring the redesign of our app, we transitioned from using a side navigation drawer to a bottom navigation bar. This gave us the opportunity to simplify how we worked with views. In particular, we wanted to eliminate the use of Fragments and only have to manage a single Activity for the main portion of our app. Here are the reasons why we did this:
Lifecycle management is simplifiedEasier view managementBetter control over backstacks including managing multiple backstacksFor security, it provides a smaller attack surface than compared to multiple ActivitiesEasier control over transition animationsWe’re now working more efficiently and effectively than ever before. We also understand that we’ll likely revisit these topics as we scale up even more. There’s going to be some interesting challenges for us in the coming days. If you want to help us tackle them, we’re hiring!
Building the Coinbase Android App was originally published in The Coinbase Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.
Similar to Notcoin - Blum - Airdrops In 2024