Transcript
Poggi: We're going to be talking about native and cross-platform apps development. I am Sebastiano. I am an Android GDE, Google Developers Expert. I work at JetBrains. Let's talk about the scope of today's talk. The goal of this talk is to help you choose. How we're going to do that is we're going to be looking at the preconditions for your success. We're going to be mentioning some things about mobile that you might or might not know. Then we're going to be trying to understand how we choose between native and cross-platform. If we do choose cross-platform, then we're going to try and understand how we pick the right cross-platform stack for you. As we then think, in engineering, everything has a big "It Depends" caveat attached to it.
Terminology
I really think it's important to define the terminology for this talk. When I'm talking about a native app or a cross-platform app, what I'm really talking about is native app is something that uses the native build tools for each platform. For example, in the Android case, that would be using Kotlin, Java, C++, Gradle. In the iOS side, that would mean using Objective-C, Swift, and the Xcode build tools. On the cross-platform upside, the difference is that we're talking about non-native build tools, although partially there might be some overlap. Potentially, cross-platform uses web technology even partially. The main point is that when we're talking about cross-platform, we're talking about something that works the same and uses the same technology on both Android and iOS. In neither case, we're talking about something that runs in a browser that's called a website, which is not to say it's worse, it's a different thing.
Company Dynamics
Let's start by talking about company dynamics. We are all here because you want the mobile app. There's two possible scenarios for which you might want the mobile app. The first one is you're doing a greenfield project, so something entirely new. The other scenario is something where you're rewriting an existing application code base that might be either in one go, so more similar to greenfield, or maybe you're trying to progressively rewrite something that for whatever reason doesn't really work for you. Maybe it's because of tech debt. In the latter case, you will have a pre-existing team that wrote the initial or the previous incarnation of your app. Or maybe you have hired someone externally that did the work for you, in which case it's a greenfield for you because nobody knows anything about the code base. The big rewrite generally happens because there's been some degree of failure in the management of the project. Specifically, the application didn't succeed or it doesn't do what it needs to do.
The existence of a team that works on mobile is very important. In mobile, you might not think about it, but there are no such thing as full stack engineers. Mobile engineers tend to focus on their platform of choice and they don't always like working on backend. Again, it all depends. There's cases when they do and whatever. Generally speaking, in my personal anecdotal experience, backend people also don't want/care about doing mobile. There are information silos and knowledge silos on both sides. The mobile team and the backend team don't always work together. They might be forced to work together but they don't work together. This can cause misalignment of goals, of backlogs, and also misunderstandings and a lot of other things that you really should be looking into when you're facing a new or an existing app rewrite.
Then there's something else that's quite important. In particular, there's a big common case in mobile, which is that there are two different chains of command and chain of reporting for mobile and for tech. This is especially in the big rewrite scenario. Where mobile reports to product, it's seen as part of product, whereas backend and web, the architect, they report to the CTO. What this means is that there is a concrete risk that mobile is going to be nobody's child, in a sense, because management doesn't get it. It's like, they're maybe excellent product people, but they don't understand technology in the same way a CTO would. On the other hand, because technology that is not mobile is under a different team, a different lead, a different VP, a different C-level executive, then the technology stack in the company is not built around mobile, is not built for mobile. That can be problematic, because the needs of mobile and web can be different. This leads us to also discussing the fact that, in almost all cases, especially for companies that have existed for a while, web has always been ahead. It tends to be ahead because mobile generally comes later. I'm not saying it's necessarily an afterthought, but web is the easiest and most straightforward way to get something out there. I know this makes it sound like I'm trivializing doing web frontend. I'm not doing that. What I mean by that is that mobile is very complicated, has a lot of scope. Mobile can have wearables, you can have TV apps, you can have car applications. There's a lot of things that go into mobile that is not just the phone, there's a lot more to it. Compared to that, web is relatively straightforward. This complexity and this difficulty of dealing with mobile sometimes can exacerbate existing issues in your company, so you want to be ready for that.
When Things Go Wrong
What happens when things go wrong? Obviously, nobody wants things to go wrong, because nobody likes failing. Failing on a project can cause your bosses to be fairly unhappy and frustrated. That's a shoddy feeling to feel. Nobody really wants your boss to be angry at themselves. Also, especially in some organizations, this can cause the start of blaming games where the mobile team says it's the backend's team fault. Backend team says it's the mobile team's fault. Maybe someone else says, "It's the design team. They did a really bad job." That's not really useful to anyone, except for those that are trying to look not guilty, but they probably know deep down inside that it's also their fault, because when there's a failure, it's everyone's fault. It's nobody's in particular, but everyone's. It needs to be considered as such. Unfortunately, what I have seen happening several times in my career in a mobile agency is that some management sees the change of tech stack as a way to shift future responsibility away from themselves. Like saying, the engineers told me that technology XYZ is going to fix a lot of problems, and we're going to go for it. Then when inevitably that doesn't help, then it's the dev's fault, "They lied to me." Which is not particularly helpful either in the long term because you fail anyway. This is the wrong choices that you make for the wrong reasons. It's very important to be honest with yourself and honest with your team and talking with the rest of your team, the company, and understanding why things went wrong if they did go wrong in the first place.
Because bad apps exist, this isn't obviously all good and dandy, but then things still happen that we wish they didn't, but they do anyway. The reason why most bad apps exist, in my opinion, is that there were some bad choices behind them. In particular, this can happen that someone decided to force some choice, made some bad assumptions. A very common bad assumption that I've seen made is that the existing technology stack in the company will work for mobile just as well as it works for web. That's not always the case. You might have a very nice setup for your web backend, but it doesn't work necessarily well for mobile, because the way people use mobile is different. A website and a mobile app, they have the same goal, but they are fundamentally different in the scope that they have and in the way that they are made. You will need probably to reach outside of your comfort zone and find the best solution for you for your specific needs. This is not always easy. It can be very bad if you do not have management buy-in. Make sure that when you do make a choice, you have higher-ups' buy-in and they will not leave you stranded with whatever you choose.
Lastly, and I want to close this section with a very important consideration, users do not care about the technology stack you use. They couldn't care less. Unless they are nerds like me that are very interested in this thing. The vast majority of people don't know and don't care about the choice you make in terms of tech, they just really want to get stuff done. They have an idea. They want to do something. They want to do something with you, and the technology doesn't help them, it can only get in their way. Your goal as a company would be to help them so that you can transitively help yourself and your business.
(Re)starting
We've talked about all this. We've made this introduction. Let's say, yes, it is the time you want to start or restart work on a mobile application. Before you do, there's really a lot of caveats of things you need to pay attention to, the most important one to me is you need to ask yourself the tough questions. The tough questions when it comes to mobile app are some things like, do users want or need a mobile app? If they don't, you're wasting time and money. There's no point in making an app nobody's going to be using. Then if you're unsure, think, can you help your users get to what they want, do what they want, with a high-quality website that is responsive, that works well on mobile? If the answer is yes, then probably you don't need a native app or a cross-platform app. Then, does your competition have an app? Looking around is always good. You are not in the market alone, you're with competitors. Do they have an app? Do their users use their app? Is there a good app? How good is it? If you're trying to enter a market where everyone has an app or some of your competitors have an app, but that app is mediocre, then you have a relatively low bar to clear for your app to make sense. If you're entering a market where your competitors have a high-quality app, people are more likely to be using your competitor's app if your app is not as good as theirs. This is very important.
Once you have asked the tough questions, then you really need to take some decisions, make some decisions. The best way to do that is to use data to drive those decisions, because gut feeling might be bad for you because your gut feeling might be mostly related to your local market. We are living in a bubble in a sense as tech people, so trust indeed is very important. You should run focus groups. You should run user studies, market research, competitive analysis. All those things are very useful because they give you an insight into what's out there, what people think, what they perceive. Once you have the data, you need to trust it. This also includes treating the data with respect. Respecting what the data says, not twisting data to say what you wish it said. You need to trust the data, even when it says something you don't like. Because if the data says, nobody cares about a mobile app for your product, then don't. It's fine. Maybe do the website. Maybe don't do that either. It really depends on your company, your users, your products.
When you realize that you need to do like your data says, sure, go for it. App, it is. Then you need to understand, who is in charge of the application? Is it the CTO? Is it the CPO? Is it a tech thing? Is it a product thing? My personal recommendation based on experience is that you should really try to align the mobile team with the rest of tech. That means probably the mobile app should be under the CTO not under the CPO, because you do want the various tech teams to work as closely together as you can. Not just having turf wars where the product people blame the tech people and the tech people blame the product people, and then they don't understand each other and they have different needs and different backlogs. Avoid that if you can. Always think about your users. You want to help your users do what they want to help them help your business by using your services, making a purchase from you. What are your users trying to do? That is the fundamental important question when you're doing anything, but specifically when you're thinking about mobile. Because the interaction, the usage that your users will do on your app might be fundamentally different from what you think, from what you're used to from the mobile, from your website. It's very important to understand this. Because this, in turn, allows you to define what is the scope of the application, and most importantly, what is not in the scope of your application. Throwing the baby with the kitchen sink is not going to help. Mobile is complicated. Mobile is expensive. You need to focus your efforts to make sure that it works the way you intend it to work.
It's very important to talk about capability versus capacity. There are two different ways to look at this. Capability is, is your existing team able to work on a mobile app? Versus, I have five people, I'm going to throw them at this mobile thing. What can your existing teams do if you have any? Do you have any mobile devs that know the native platforms? If you decide to go with cross-platform, are they ok with that? Are they going to do it? Remember, the current mobile market, the current job market for mobile engineers is very active, alluring. It's very easy for someone else to just leave and then leave you stranded. It's very important that you consider these things. Also, if you do not have a pre-existing mobile team that knows the platforms, you really need to ensure that you have someone, at least a couple of people, one per platform, that know the platforms very well. You are going to need it at some point. You might not need it on day one, you might not need it on day 10, but you will need it. Because at some point, even if you do cross-platform, you will end up interacting with the underlying platform. If your people have no clue how that works, you're going to be stuck at some point. Please remember, you always need at least one person that knows Android and one person that knows iOS, or maybe one person, if you find a rare developer that knows them both fairly well, then that also is fine. Then you have a bottleneck of just one person that can take care of everything related to platform-specific stuff.
When we're talking about this, why do you need this? You need this because as I said, your application, even if you're writing JavaScript React Native, you will eventually need to go and interact with the operating system. Most mobile apps require this. If you're going to write an application that does not talk to the operating system, then maybe it shouldn't be an app, maybe it should just be a website. Because it's going to be faster, it's going to be cheaper. You probably already have the knowledge in your company to do this. The so-called website apps, so essentially an app that has a listing on a native app store, such as the Apple App Store or Google Play Store, but they are just a WebView, those are useless. Nobody wants them. If your application brings something to the table, then great, but if it doesn't, there's no point in making one. Let's consider an example. You have an existing ReactJS development team, and you want them to do mobile. This is potentially problematic, because the technology and the tools that they will be using are somewhat different. Sure, there is a vast amount of concepts, especially that are shared between ReactJS and mobile. As soon as you need to do something custom, you need someone that knows how to do that custom something. Native knowledge is again required to do some things. Even if you have a third-party vendor that has a native SDK that you want to integrate with, you will need someone that knows how to do that. You will need someone that knows how to write Kotlin. You will need someone that knows how to write Swift, that can write that integration for you if one isn't available, or if the third-party ones that generally you have to use are not very good, which can happen.
Once you have considered what are your team capabilities, you want to involve them in the process. You want your devs to be involved in the choice, because, again, they're the ones that are going to have to work with that, so it makes sense. Listen to what their fears are. It's not uncommon if you have pre-existing native teams, for the people to feel threatened by the adoption or potential adoption of cross-platform frameworks. Because if everything goes well, then you don't need two full teams, you need two persons, one per platform, plus one team, maybe slightly larger than any of the two single ones. That means people are going to lose their job, if you move from native to cross-platform, most likely. They know that. Listen to them, and reassure them. Make it so that they feel safe in your company. Because otherwise, again, they will leave and you will be left without a team that can work on your product. That's not good. When talking with your team, it's important as always, to remember not to chase fads. Developers like ourselves, we like shiny things, we all know that. Your team will be no exception. They will have their favorite technology, and their favorite technology might not be the best one for you. You need to talk to them and make sure that the reason that they might be suggesting to adopt one or the other, if they have any suggestions, is not because they are fanboying Google, for example. It's very important that you choose technology because of its merits and not because of someone's personal preferences. Spikes are a good way to test the water, so putting a time box and a couple of people working on a demo that you can do with a specific framework. Remember that spikes can be very deceiving because people tend to choose things they like and things that are easy. Try to orient your spikes towards a very vertical slice of things, not just developing the UI, because doing just the UI is definitely easier than doing things like storage, caching, networking, database, all that stuff.
Once you commit, remember, you're in for the long run. It is a big investment that you're making, regardless of whether you're going native or cross-platform. There will be huge switching costs if things go wrong. There is in fact a certain amount of lock-in, fairly high, both in terms of the technology you use and the skills of the people that you will have to have to work on those things. There is a very high chance that if you make the wrong choice and you need to change tech, you will have to rewrite everything.
Native or Cross-Platform?
With all the caveats out of the way, it is now time to talk native or cross-platform. Native is always better in some sorts of sense. It has better performances than any cross-platform framework. It will have better integration with the operating system, with third-party libraries, and better support from the community at large, because they're always bigger. Native is more consistent with the operating system because it's native. That's the whole point. You will have access to more APIs and features like wearables, like tvOS. If those are things you care about, then native might be the right way for you to go. The tooling on native is constantly improving, even Xcode is getting better. Now they even have rename for variables in Xcode, mind-blowing. Not everything is great, obviously, otherwise there wouldn't be cross-platform frameworks.
Native is more expensive. You need a dedicated team per each operating system. There are infrastructure and process considerations that you need to consider. For example, you will most likely have to have different CI setups for Android and for iOS. This might also happen in the case of cross-platform, because the tooling between the two different platforms is different. Also, beyond that, deploying and publishing your application to the stores, the Apple App Store, or the Google Play Store, whatever other stores on Android you want to publish to, they are different. They work in different ways. There are different timings, expectations. Consider that.
In some cases, going cross-platform might be the most pragmatic choice for you, for your specific case. Cross-platform might be enough. By that, I don't mean that cross-platform is worse than mobile. I mean that what cross-platform is better at might be all that you care about. In that case, it makes sense because cross-platform has vastly improved over the years. It does have some advantages for developers. For example, Flutter and React Native offer hot reload, which is great, because you can test your changes like you do on the web, without having to redeploy the application to the device or virtual device. If you do go with cross-platform, my personal recommendation is to make sure that you have a very strong design language that is not looking like Android or iOS, because if it looks too much like either platform, it will be looking out of place on the other one. At the same time, it's very hard to mimic the native look and feel of a platform without using native controls. You can get maybe 80% of the way there easily, then the remaining 20% is very hard. There's a very big uncanny valley there. Try to do something like Duolingo does, if you do cross-platform, where they have a very unique design language. Duolingo is a native app, but if you do cross-platform, that's a good example of how you could do it.
A Fictional App Case Study (Wearables Company)
Let's look at a case study. There's a wearables company. They're wondering, do we need an application? They have the need for a companion app, because their point is we have a smartwatch, like the one in the picture. We want to be able to communicate with it, to download data, to show historical trends. Yes, you need an app, you cannot do this from a website. Maybe you could, but you really, probably shouldn't. The next question that they should ask themselves is, do they need a native application? Are they using the operating system APIs heavily? Because this is a big point for using native code. The answer is yes, they're going to be using it a lot, because they're going to be having to do a lot of work in the background. They're going to be having to do all the pairing stuff with the device. If they're only using Bluetooth, there might actually be a case where cross-platform, especially Flutter, can do most of the stuff. If you go on mobile native, then you probably have more control over what you do. You have more possibilities. Then the next question, again, extremely important, can users achieve their goals with a native app? In the case of a native app, users will always be able to achieve their goals if you do a native app, because native app is the gold standard. For as much as cross-platform frameworks are good, native remains the gold standard, because that's where features originate from. That's also a yes. This means that, yes, they do need a native app.
The Main Choices: React Native, Xamarin, and Flutter
I've been talking about native and cross-platform, but when I say cross-platform, what do I mean? The main three choices I see today for someone doing cross-platform, are React Native, Xamarin, and Flutter. There are also web-based frameworks. An example of those would be Cordova, Ionic, and PhoneGap, and others. I would be remiss if I didn't mention that also exists Kotlin multi-platform, which, as you might know, Kotlin is a language that is designed by JetBrains, and worked on with other companies as well. In terms of the web-based, cross-platform frameworks, I would probably avoid them, if at all possible, because they tend to be fairly old and not very good at all. For what concerns Kotlin multi-platform, it's very different from React Native, Xamarin, and Flutter, because right now, Kotlin multi-platform is focused on sharing business logic more than UI. For the scope of today's talk, let's ignore them, and focus on React Native, Xamarin, and Flutter.
React Native is a technology created by Facebook. It's based on ReactJS, also made from Facebook. The good thing about this is that if you have a strong ReactJS presence in your company, you can probably share some of the skills and some of the code with the web team. Because just like ReactJS, React Native is built on JavaScript and npm. One important thing to mention about React Native is that there is third-party support for desktop, and wearables, and TV, to different degrees of experimentality. If your focus is those things, I would not use React Native just for that, because it's all very immature right now, or at least that's the feeling I get. React Native is something mature enough and powerful enough that you can make B2C apps with it. There are, in fact, a lot of big React Native apps out there. Apart from parts of the apps from Facebook, and Instagram, there's also third parties that use React Native, and there's quite a few of them. There are some limitations for what performance is concerned, but they have been improving upon those in the past few years. Especially when it comes to animation, if you're going to do something very animation heavy, I wouldn't do React Native for that. Also, need to remember, if you do need to do custom UI components, you need to create per-platform implementation, which is tedious. At the same time, it's how you get a very native feeling UI at the end of the day from React Native, is because it's using native stuff. There are famous cases of apps having abandoned React Native. Most of all, I think everyone knows about Airbnb a few years back. It doesn't mean it needs to be your case, but just also a data point to consider.
Xamarin instead is a very different beast. It's created by Microsoft. It used to be a paid product, now it's free, and it is open source. If your company is very big on C#, maybe you have ASP.NET, if you are very big on C#, then this will give you the ability to have a full stack .NET implementation from the backend to all the frontends. Xamarin has a fairly unique UI approach in the sense that you can either go multi-platform with Xamarin.Forms, or you can use native views somewhat like React Native does. The latter, I don't think is used that much. I cannot really find much information about it. That probably tells you something already. Xamarin, contrary to React Native and Flutter, tends to be very close to the source operating system API. You need to know the operating systems anyway. Because what they do is they automatically wrap the existing APIs from the Native SDKs, and they expose them in C#. There is somewhat limited support in terms of third parties, there's not that many that have native Xamarin libraries. You can generate bindings, but your mileage may vary. Tooling is somewhat limited. In my personal opinion, Xamarin is probably best for internal and somewhat unsophisticated apps. It is very enterprise oriented. Maybe it's not that great to do B2C apps, probably don't want to do Xamarin for that.
Lastly, Flutter, it's from Google. It is very quickly rising in popularity. There are a lot of investments and marketing that Google is putting behind Flutter, and that may be why it's so quickly rising in popularity. There are a lot of very good first and somewhat second party integrations. For example, as you would expect, Firebase, things that are from Google, are very well integrated with Flutter, for example. Flutter uses Dart as a language and the Pub ecosystem for dependencies. You can technically do almost everything with Flutter. You can do mobile. You can do desktop. They are specifically targeting macOS, Windows, and Linux. You can do web. You can also do embedded IoT. Essentially, anywhere you can run an Android APK, you will be able to run a Flutter app. There is no support for WatchOS and tvOS as far as I can tell right now. If you really want to, if you find someone that will do that for you, if you have a lot of people that do Dart in your company on the backend already, for whatever reason, then you can also do UI with Dart. That's Flutter. Flutter has best-in-class testing capabilities. Important to note, the developer audience of Flutter is heavily skewed towards Android, probably because it is a Google thing.
To give you a sense of scale. These are the numbers from app figures in terms of how many apps on the Android Google Play Store and on the Apple iOS App Store are using different cross-platform frameworks. You can see that, surprisingly to me, Cordova is 17% on iOS and 20% on Android. React Native is the second, somewhat 5% less in terms of usage. Flutter comes after that. You can see the very strong skew here towards Android. Ionic and Xamarin are much lower still. Then there's other things like the recently obsoleted, abandoned Titanium/Appcelerator framework. Those numbers are deceiving because those numbers don't tell you that if you ask how many mobile developers are using cross-platform, it is about a third of them. Consider that when you're building a cross-platform team, you probably have to tap two-thirds less of the work market out there. Also, if you look at historical data, the numbers we saw are different. You can see all of the web-based frameworks and somewhat also React Native and Xamarin. The amount of people over the last three years that have said that they're using those technologies has gone down. React Native is not that much down, but others are very much going down. On the other hand, you have a situation like Flutter that's going up. Looks like Flutter is doing particularly well, there's 42% of mobile apps that have used it. Kotlin multi-platform is going up.
Fictional Fintech Case Study
Here's another fictional case study to wrap things up. You have an investment company, it's a fintech. First consideration, do they need an app? The answer is yes. Their competitors all have an app, so they do need an app. Do they need a native app though? First of all, let's look at the same criteria we looked at earlier. Are they using the OS APIs heavily? Not really. Most will be using push notifications, but that's somewhat of a solved problem. No, they're not. Can their users achieve their goals? Assuming their goals are that they want to look at their stocks and maybe buy some more and track them and get notified, then, yes, they don't need a native app to achieve those goals. You can do that with any cross-platform framework. They probably don't need a native app. We are going cross-platform, which framework? First of all, the company in question does not have a ReactJS team, for whatever reason, maybe they use Angular. They do not have a strong .NET team in-house either. That also rules out Xamarin because it makes no point to use Xamarin if you don't already have .NET in your company. They are using Firebase services quite heavily. Lastly, they are planning to do a lot of custom UI, because all those graphs, all the nice animations, there's a very B2C thing. Given these elements, probably the best solution is to use Flutter.
Testing on Mobile
Last thing, testing on mobile. Remember, unit testing, a solved problem on mobile. Not that big of a deal. UI testing is where the problems are. Flutter is the framework with the best solutions for when it comes to UI testing, because you can run so-called widget tests that are offline UI tests that are very useful, especially on the CI. Native and React Native will end up using per platform tools. Xamarin as well, but I seem to remember they are custom tools still per-platform. When you want to run UI tests on CI, you will be running instrumented tests that are slow. They need a device, physical or emulated, simulated. There are cloud services to have device farms that you can run your UI tests on, but they're really expensive. They are complex to set up and to maintain. The classic workaround is to do more unit testing, especially on Android. You have things like Robolectric that allow you to run what would otherwise be integration tests as if they were unit tests. There's also a market for specialized CI solutions for mobile projects, like Bitrise, and things like that.
Review Decisions
We have made a choice. We are working on our app. It's time to keep an eye on what we have done and what we achieved because bad choices will not be clear right away. For example, you've seen some React Native apps have abandoned React Native after a few years. Flutter might turn out being the same down the line. We don't know. It's important that we remember to keep an eye on the progress of things. Because, yes, failure will be expensive but sunken cost bias will be worse. Stopping early will help you contain the damage in a way.
Takeaways & Resources
First of all, understand if mobile can work for you. Use data. Second of all, make sure your company can do mobile, sort out the organization, sort out the team responsibilities and whatnot. Then, when it's about to make a choice, assess the compromises, trying to understand that there is no silver bullet and every company is different. Lastly, make the right choice and go. You can find some more information and links at go.sebastiano.dev/qcon-2022.
Questions and Answers
Mezzalira: You discussed very well about different types of implementations that are valid. In your experience, which one would you choose 99% of the time?
Poggi: Personally, I do native development. That's the most obvious choice for me. If I found myself in the situation of having to choose across platform framework, I would probably use Flutter mostly because it's the one I have some experience with. Dart is not a language I'm particularly skilled in but it's close enough to Java that it's easy to understand. As a second choice, I will probably choose React Native, but with the caveat that I don't know anything for JavaScript, so that might be a bit complicated. The knowledge gap would be bigger. If you understand how declarative, reactive UI frameworks work, using one or the other is mostly a matter of getting used to the specific semantics and language that you use in one framework versus the other.
Mezzalira: I tend to agree, but obviously then there is a favorite language that kicks in.
See more presentations with transcripts