Write Once, Deploy Everywhere: When to Go Native?
Write Once, Deploy Everywhere (WODE) has been the promise of many development frameworks over the past decade, whose goal is to ease the pain of writing multiple native applications. Determining which path to take is one of the most critical decisions a project manager has to make due to its high startup cost, impact upon the development team, and potential infeasibility to reverse.
Hybrid solutions such as Ionic leverage web technologies to render applications across platforms, but often, the end product falls short of a user’s expectations of a native look and feel.
This article breaks down the pros and cons of various mobile development paths and weighs them against team makeup, cost, and user experience in an effort to empower product managers to make a more informed decision.
Write Once, Deploy Everywhere
The concept of Write Once, Deploy Everywhere refers to the ability of a development team to write an application once—using a single development stack, abstract of the platform(s) upon which the application will be deployed—and yet maintain the ability to deploy the application to all desired platforms, e.g., Android, iOS, Windows, etc. Ideally, this is accomplished without sacrificing maintainability, performance, or user experience (UX).
The alternative – and historical – method of mobile application development involves the straightforward process of simply writing a separate application for each platform, which, of course, carries with it its own potential high cost of time and resources.
In general, the factors to consider when choosing a development path include:
- Age of the project
- Makeup and size of the development team
- Desired platform(s) for distribution
- Required timeline to market
- Available bandwidth to change to another path if one must
Unfortunately, applying each of these factors to each of the available paths, as well as wading through the myriad of available opinions on the subject, can be quite daunting. Furthermore, this process often leaves the project manager with a sense of uncertainty as to which path is best in order to meet the application’s requirements.
At a high level, the different mobile development paths can be put into two categories: native or WODE, i.e., native or everything else. Put simply, one either writes a native application or one doesn’t. The WODE category is further broken down into two groups:
- Hybrid frameworks – those that leverage web technologies to render applications across multiple platforms.
- Non-hybrid frameworks – those that use native UI components (e.g., buttons, text fields, and even layout managers) instead of rendering a web view inside of an application as hybrid frameworks do.
The majority of WODE frameworks are hybrid; however, in order to improve both performance and UX limitations of hybrid frameworks while still providing the benefits of a WODE framework, the current trend is toward non-hybrid. Due to this trend, frameworks such as React Native, Xamarin, and Appcelerator are gaining popularity.
Each of these paths—native, hybrid, and non-hybrid—has differing strengths and weaknesses, and as a result, each has different use cases for which it is most suited. The rest of this article breaks down the pros and cons of each mobile development path when considering competing priorities such as team makeup, project cost, and UX. With the exception of a few specialized use cases, writing native applications maximizes user experience at a slightly higher cost.
In general, the adage “you get what you pay for” applies, so if cost matters more than the customers’ experience, native may not be the right choice. However, once UX becomes vital, native applications become the clear choice since, in order to improve the UX, WODE-based applications incur a considerable cost in the form of either time or native expertise, which defeats the purpose of choosing a non-native development path in the first place.
Furthermore, even if that cost is paid, the WODE-based end product will always deliver an inferior UX when compared to its native counterpart. As a result, native is almost always the right choice for most development teams and for most projects.
Native applications are written in the core language of the given platform. For example, Android applications are written in Java, while iOS applications are written in either Obj-C or Swift. They require the development engineer to understand the language as well as the platform-specific nuances, which include, for example, third-party package integration, layout management, operating system (OS) interaction, and so on.
Highly customizable. Since each application is written utilizing native components, the only limitation to customization is the interface to the underlying frameworks, and sometimes not even then. As most native development engineers will attest, there is often a way to accomplish a given task in spite of a limited interface.
A simple proof of this idea can be found by browsing the support communities for a given platform. One will find numerous examples of how to accomplish a task that might be “off the reservation,” despite the limitations of the underlying frameworks.
A concrete iOS example of such a seemingly simple task might be to show a fullscreen overlay, above all external UI elements, e.g., a tab bar, navigation bar, etc. As shown in Figure 1, this is normally outside of the scope of the normal UI layer currently being presented. As such, in order to have a fullscreen overlay, it must be added to the hidden layer above the tab bar in the view stack. This kind of customization is typically only possible on native applications.
Highest performance. As expected, a native application sets the benchmark for performance. Since most other framework types add one or more intermediate layers, they inherently run more slowly than a native application.
Most maintainable. Operating systems change constantly. Period. When they do, depending on whether breaking changes were made, an application must be updated in a timely fashion so as not to lose the part of one’s user base that upgrades to the newer OS. Obviously, the less time that passes between when the change is made available to one’s users and an application is updated, the better. This time is minimized when there are no dependencies that need to be updated in order to support this new OS, which is the case when working on a native application.
Additional resources. When writing applications for multiple platforms, a development team typically consists of one or more mobile software engineers for each supported platform. This, of course, inherently increases the size and cost of a development team. It also requires the team of engineers to have a variety of skills, as opposed to having a homogenous skill base. This has the potential to fragment a team with regard to support and collaboration.
Slower development cycle. Native apps have the potential to have a slower development cycle simply because a separate application must be written for each desired platform. The extreme case is when there is a single mobile development engineer on the team since each application is essentially written in series.
Low performance. It might seem odd to have performance as both a pro and a con. On one hand, native applications give the developer enough room to create a finely tuned, high-performance application. On the other hand, however, they also give the developer enough rope to hang themselves. If they don’t know what they are doing, in the end, they will end up with a subpar application at best.
Note: In general, this applies to all framework paths (native, hybrid, and non-hybrid). If the engineers developing an application have insufficient skills for what they are attempting, the resulting application will likely neither meet design requirements nor be well accepted by users.
An example of this type of hybrid framework stack would be an Ionic view layer backed by AngularJS, which is ultimately converted and rendered in a web view on the desired platform using PhoneGap and Cordova. Obviously, this type of WODE framework comes at the cost of added complexity.
Minimal development team. Hybrid frameworks enable a small development team—and particularly one whose primary knowledge base is web development—to quickly produce simple applications across multiple platforms. This allows a project manager to keep his team small as well as remove the need for his team to learn the native languages and frameworks for multiple platforms.
Faster development cycle. In addition to a smaller team, hybrid frameworks afford a faster development cycle when deploying to multiple platforms since only a single view layer needs to be designed using web technologies.
Potentially poor UX. The downside of only having to write a single view layer is that one is left with a single view layer. This can result in a poor UX since a one-size-fits-all approach to UI design fails to give one’s application a look and feel that is comfortable and familiar to users on all platforms. In addition, since hybrid applications are essentially a webview embedded within the UI, it can give users the impression that they are actually viewing a web page instead of interacting with a native application. This experience almost always has a negative impact upon user satisfaction, and ultimately retention.
Costly to customize. Improving upon the UX by designing customized UIs for each platform results in complex and unique UI frameworks that can be costly to create and difficult to maintain over time. Furthermore, in order to create UI elements that will help make one’s application stand out (e.g., animation, custom views, etc.), customized bridge components must be created to translate the high-level UI design into something that the lower-level framework, such as Cordova, will understand. In general, the more one customizes and improves the UX of a hybrid application, the more it diminishes the benefit of a fast and inexpensive design cycle.
Lower performance. Since hybrid applications render the application’s views within a webview, there is a large potential to make implementation mistakes when dealing with OS frameworks (e.g., networking, Bluetooth, on-device contacts, etc.), which result in vastly degraded performance. It is also worth noting that, even if great care is taken with regard to performance since everything is displayed via a webview, the hybrid applications’ maximum performance will always be slightly less than their native counterparts.
Non-trivial plugin management. Remember those custom features the design team spent weeks polishing, which was followed by another few weeks while the development team created the necessary bridge components so that Cordova could work with them? Well, they won’t work unless there is a supporting Cordova plugin for what the team is trying to achieve. This means one of two things: either the team creates it themselves or a suitable third-party plugin will need to be found that does the job. Unfortunately, more often than not, option two does not exist. As a result, it requires additional development time to create the custom plugins, followed by build support effort—over time—to manage the growing library of Cordova plugins required by the application. Of course, when Cordova updates occur, there is a high probability that these plugins will need to be updated as well.
OS support lag. The previously mentioned cascading bridge component/Cordova plugin issue is further exacerbated when the OS changes core functionality. Once Cordova, PhoneGap, and Ionic have been updated to support the changes, it is possible that the custom plugins and bridge components will need to be updated as well. Regardless of the order of magnitude this work would require, it results in additional time during which the application doesn’t support end users who have updated to the new OS. This, of course, is a worst-case scenario in which breaking, non-backward compatible changes are made by Apple or Google, which never happens… right? In general, any intermediate framework that is out of the developer’s control and that must be updated first only serves to delay the process. Finally, relying upon an intermediate framework can be a headache for project managers to plan around since the timing of these frameworks is such an unknown.
However, that is where the similarity ends. Non-hybrid applications compile down to native code and render the application using platform-native components instead of rendering via a webview. This results in a WODE framework that, at least on the surface, has the best of both worlds.
Higher performance than hybrids. As one might expect, non-hybrids inherently have a higher performance than hybrid applications due to their ability to render the application using native UI components (buttons, views, layout managers, etc.) instead of relying on an embedded webview. Of course, developers are still free to write an application that performs either remarkably or horribly. The benefit of non-hybrid applications is simply that they have a higher performance baseline when compared to similar hybrid applications.
Minimal development team. Similar to hybrid frameworks, non-hybrids enable a small development team—and particularly one whose primary knowledge base is web development—to quickly produce simple applications across multiple platforms. This allows project managers to keep their team small and to preclude the team from learning the native languages and frameworks for multiple platforms.
Faster development cycle. In addition to a smaller team, non-hybrid frameworks afford a faster development cycle when deploying to multiple platforms, since only a single view layer needs to be designed.
Faster iterations (React). The React framework provides a powerful feature that allows changes to the application to be rendered in real time: no need to recompile, rebuild, etc. As a result, the React emulator is an incredibly powerful development tool that dramatically reduces the duration of each implementation cycle.
Costly to customize. Much like its hybrid counterpart, when non-hybrid applications require the UX to be improved by designing customized UIs for each platform, it results in complex and unique UI components that can be costly to create and difficult to maintain over time. This also means writing customized bridge components to supplement gaps in the framework’s native element support. Like hybrids, this cost diminishes the benefit of a fast and inexpensive design cycle, but unlike hybrid applications, bridge components are written for each desired platform in their native language. This means that instead of non-hybrid applications being a flexible alternative to a team that is primarily comprised of web developers, teams choosing the non-hybrid path have to learn not only the particular language of the framework (e.g., JSX or C#) but also the native language of each platform(Java, Obj-C, or Swift).
Third-party dependencies. This limitation takes two different forms. In the case of React Native, it takes the form of numerous dependencies, i.e., roughly 650. The result is that there is a very good chance at any particular time that one or more of those dependencies is out of date. It also means that in the event of a large OS-level change, there is a high probability that most or all of those dependencies will need to be updated. The potential saving grace is that Facebook uses React, so one will have the 300lb gorilla in their corner.
In the case of Xamarin, the third-party dependency issue is simply that it is extremely difficult to integrate them in the first place. Xamarin is aware of this issue and provides a utility tool called Sharpie. The tool’s purpose is to help with some of the integration, but unfortunately, Sharpie often attempts to compile and link incorrect resources, which forces the developer to undertake the painstakingly time-consuming task of manually modifying low-level compilation parameters in order to successfully complete the integration.
OS support lag. Non-hybrid applications are plagued by the same issue as hybrid ones. Any intermediate framework that is out of the developer’s control and that must be updated first only serves to delay the process of updating one’s application to support cutting-edge users. Furthermore, as stated before, relying upon an intermediate framework can be a headache for project managers to plan around since the timing of these frameworks is such an unknown.
Long-term support (React Native). This issue is specific to React Native and pertains to the odd fact that, to date, Facebook has not committed to a long-term support plan for its framework. It can be said that this is a low risk since the company utilizes its own framework for its mobile apps, but it is worth a pause for any project manager to consider why Facebook has refused to comment on the subject.
Choosing the Right Approach
When cost is not a primary consideration, Figure 2 shows that writing native applications is almost always the best choice when leveraging the makeup of the development team against the application’s requirements. When there are fewer development engineers than the number of desired platforms, it gets a bit more interesting. In that case, using React is the correct choice if the team is under a very tight release schedule; otherwise, going native is still the best option.
When the team is primarily a web development team, and a customized UX is required, it is better to have some team members change hats or add some team members in order to make one’s applications native. There really isn’t a feasible, maintainable framework option if an application requires custom elements, which many applications do.
However, if a custom UX is not required, then, depending on the release schedule, it might be better to go with Ionic or React. If one’s team has no time to learn JSX, then Ionic is the right choice. Otherwise, it is better to choose React since it already requires many third-party dependencies, and adding more isn’t going to impact one’s development cycle.
Once the cost of the project is a primary concern, typically, the existing team makeup becomes less of a priority since the first step would be to put the proper team in place to execute the project plan for the projected cost. As shown in Figure 3, native applications have a higher starting cost than their WODE counterparts, but also a higher potential UX. Moreover, WODE applications will always be limited in their UX, regardless of how much money and resources are applied to the project.
I hope this article has shed some light on the pros and cons of various mobile development paths, as well as aided in weighing team makeup against both application requirements and the cost of the project. Its message was not to convey that WODE frameworks are inferior and should never be sought out, but rather that even though there are valid use cases for not going native, one should fully understand the ramifications of doing so.