When I started working as a software engineer ten years ago, I was tasked to write the Mac version of an existing project, and I was to do it using Visual Studio, on Windows. As a matter of fact, the first decision I made was to pick a cross-platform development framework.

Over the following years, I spent countless days trying to make cross-platform code look decent both on Windows and Mac OS.1 This might explain the strong opinions I have on cross-platform development.

Cross-platform development lets you write common features just once for several platforms.

But there’s something inherently wrong with that. Say you want to write an app for iOS and Android? Each platform has its own story, its own set of metaphors users are familiar with. You can write a common cross-platform UI, but be prepared to spend a lot of time tweaking on each platform. Otherwise, it will just look weird.

But maybe you want the UI to behave the same on all platforms, because “the experience is at the core of your product”? Guess what, that’s bullshit. Exactly 0% of your users care about “cross-platform brand consistency” and no, your product manager does not count. An iOS (or Android, or Mac, Windows, or any OS) user is accustomed to the specific behavior of this platform. How buttons react. How contents scrolls. How text is rendered. There’s a whole lot of untold expectations, and if your app starts to behave differently, it’s just crap.2

Don’t forget your users are not just your users. They are primarily users of a device, and happen to use your app on that device,3 and it coexists with other apps on this platform.

Your app isn’t a platform.

OK, but can we still use a common backend for the app?

You know what? Probably not. There are a lot of non-UI tasks that are specific to the platform. Data storage. Network requests. Background tasks. Push notifications. Password storage.4 Encryption. Either you’re going to reinvent the wheel (several times), or you’ll build an abstraction layer with just the common features. With a common backend, you won’t be using platform-specific technlogies, for example, CoreData on iOS and OS X. Maybe CoreData isn’t the right solution for your app, but “I want the same code to run on Android” is not the right reason to rule it out. The same goes for NSURLSession. Do you really need to reimplement a full network stack?5

OK, maybe just the business-specific logic then?

If you really want. But is it really that much code? Now your business logic is just a layer between a native UI and a native backend. Is it still worth the effort to integrate alien code in each platform-specific project? Is it worth writing Java ↔︎ C++ ↔︎ Scripting language of the day ↔︎ Objective-C bridges, maintaining and debugging them? And then there’s the project management aspect: do you really want the iOS and Android teams to depend on each other? Whose job is it to maintain the cross-platform code? Neither team is going to be happy with it.

If you‘re going to write apps, make them native. Otherwise it’s just not worth the effort. There’s that amazing cross-platform thing called the web, spend those resources on making a great website instead.

  1. Don’t get me wrong, Qt is (was?) a great developement framework otherwise. 

  2. That’s also the reason why websites shouldn’t try to look native. Not only is it impossibly hard for a website to behave like a native app, but “native”, of course doesn’t mean the same thing on different platforms. 

  3. On the other hand, they may be users of your service across different platforms. 

  4. And now you know why I don’t use Firefox. 

  5. And honestly, if you have the resources for this kind of project, writing cross-platform code to save money just doesn’t make sense.