For many modern businesses, deploying a single mobile platform is no longer sufficient; in order to adequately cover your entire market, user base, or employee base, you need to deploy to both iOS and Android. Luckily, there are many options available for projects that require both iOS and Android applications - Cordova, Xamarin, React Native, and Swift/Kotlin native on Android/iOS (pure native), to name a few. At JBS, we utilize a solution that is both cost-effective and as fast, if not faster, than the multi-platform options available on the market. Our solution allows for rapid development, hardened application logic, and streamlined application support.
Write Once, Deploy Twice?
For non-pure native, choosing one of the multi-platform "write once, deploy twice" build options can sound appealing. However, there are drawbacks to this approach. In choosing a multi-platform approach, you severely limit the pool of engineers you can hire or contract. Developing with a multi-platform application does not eliminate the need to know iOS and Android SDKs. Future improvements and maintenance require development resource who are also familiar with the SDKs of Xamarin, React, or Cordova. Now your developers need to know 4-5 languages instead of just Swift and Kotlin. Furthermore, when building out non-pure native options there are usually some platform-specific customizations required and available customizations are limited by the platform you choose. Writing in pure native code, you are only limited by the Android or iOS operating systems capabilities, allowing you to stay on the cutting edge. Choosing pure native expands your pool of talent you can hire or contract from, as they don't need platform-specific knowledge outside of Android and iOS native.
Architect Once, Build Twice.
The phrase we use to describe our pure native approach is Architect once, build twice. We pick one platform to start, Android or iOS. We then start work on one platform, allowing 2-4 sprints worth of lead time before starting any work on the second platform. This allows work on the leading platform to create a "wake" for the trailing platform, addressing any issues in the APIs/UI/UX that need to be ironed out and resolving any general misconceptions about how any particular feature should work as a whole. From the start, we ensure designs for both platforms are similar to each other, but still adhere to platform-specific UI paradigms. While it is inevitable during the project lifespan that some part of the application will need to be reworked, redesigned, or re-specced as it is developed, our process minimizes the scope of that rework to a single platform. Also, because a lot of the effort on mobile is spent creating the UI/UX, testing concepts, and behaviors in one platform before writing the other saves significant effort and cost.
Separation of Concerns
A central tenet to our "architect once, build twice" approach is to write all the business, domain, and network layers in functional-based methods and commands. Doing this allows for all of the logic of the application to live outside the UI/UX and be easily testable. Writing UI/UX tests can be expensive and time-consuming, but writing unit tests around functional-based logic is straightforward and quick. This also provides good separation of concerns, freeing the UI/UX of application logic and focusing on only being a simple consumer and event output flow. In addition, Swift and Kotlin are very syntactically similar, so the second platform can mimic the logic on the first platform (unit tests and all). The network stacks that JBS uses for each platform, AFNetworking and RetroFit, have very similar API surfaces. This makes porting the entire application stack very straightforward. Generally, the first platform will be well-tested, with all bugs resolved, before the port to the second platform begins.
These applications will also be easier to support long-term. Since both apps have the same architecture and flows, an engineer who understands the project on one platform can apply all that domain-level knowledge to the other platform. A bug on one platform is usually a bug on the other platform and can be fixed in the same place, because of the same logic was reused. There are also less companies you are dependent upon to wait for fixes or future releases; instead of waiting for Facebook/Microsoft/Cordova to update their SDKs after Apple/Google release public versions of their SDKs, you can be testing on each beta the moment it is released. Plus, because there are fewer technologies any person supporting these applications needs know, you have a larger pool for hiring or contracting those engineers.
Using this approach, JBS has seen the work on the "trailing platform" take 30-50% less time and effort. By starting work 2-4 sprints behind the leading platform, the engineers on that team can just build - without needing any additional input since they have a functionally complete example in the business-approved initial platform. Engineers developing without interruption is the best efficiency any development team can hope for. One “Architect once, build twice” project that I worked on, for example, had a 12 week timeline to build out the first platform (which was iOS). Android work started 4 weeks after iOS work started, but was done the same week the iOS platform was completed. The Android application followed in the wake of the iOS application development which, in total, saved the team more than 4 weeks of development time and cost.