
The not so hidden cost of sharing code between iOS and Android - dankohn1
https://blogs.dropbox.com/tech/2019/08/the-not-so-hidden-cost-of-sharing-code-between-ios-and-android/
======
dougk16
I have come to this same conclusion after many years. It's not cost-effective
to have any bespoke business logic (models, controllers, etc.) shared between
the two mobile platforms (don't get me started on sharing UI code). If you
have some incredibly tricky low-level algorithm/library and/or need for speed,
think database, crypto, intense graphics, etc., then fine, you may be able to
swing a shared module in C++ or something. Other than that, it's almost like
the collective consciousnesses of Google and Apple conspire to make cost-
effective code-sharing of typical CRUD apps almost impossible.

Here's a fine alternative to code-sharing: well first and foremost you need to
have a good requirements spec. After that, implement it on one platform first
in a platform agnostic way. So heavy use of delegates/interfaces/injections to
handle platform-specific functionality, even for one-liners like getting
current system time. So the code should be pure, boring, plain old Java,
Kotlin, Swift, whatever. Minimal use of fancy language features that may not
port cleanly. After one platform has the module in place and well-tested, do a
copy/paste port to the other platform. You will find that the copy/paste port
will actually uncover bugs, optimizations, edge cases, etc., that can then be
ported back to the original platform. Things you would not have found if you
were only writing the code once. It's like the most intense kind of PR code
review you can get.

So I've found that copy/paste-port-based code sharing between platforms is not
just a lesser evil, but actually a strategy that has its own unique benefits.
If you get into a groove you can build up a set of regexes to give you a
sloppy transpiler that does most of the tedious porting for you.

~~~
weq
The article says it all - they chose the wrong language with no community
support for the trail they were blazing and that technical debt destroyed
their productivity.

I achieved 90+% code share in Xamarin including UI across windows - ios -
andriod. 100% buisness logic shared. You can write cross-platform UIs, and
swap out to native code on a widget by widget basis. Threading is seemless.
Sure it has its own set of issues, but everything is a trade-off. Look at your
use case, and define what trade-offs you are happy with.

The drop-box use-case is also an outlier - to achieve high levels of
responsiveness, it must integrate with low level platform specific APIs to the
point their entire app may be some kind OS specific service. Look at blogs
about their desktop apps and you see my point.

If you going to drink cool-aid from companies just because they are dominant
in an area, atleast drink the cool-aid of a startup which was created for the
purpose of building cross-platform apps.

~~~
m0dest
I took a look at Xamarin recently to see how far it had come, and the tooling
is really impressive. They seem to do a great job of keeping up to date with
iOS/Android SDK changes, too.

But when trying to find an example of a native-feeling Xamarin-based app for
iOS, I was really underwhelmed. I tried to find one that was (a) well-known
and (b) third-party (not developed by Xamarin or Microsoft). The 4 contenders
were:

\- UPS - 1/4 stars - All views of the app are awkward embedded web views.
Every page has a full screen modal spinner.

\- Outback Steakhouse - 1/4 stars - Not updated for modern iPhones, so the
whole app is letterboxed. UI is completely custom, so didn't attempt to feel
native. Crashed as soon as it tried to get my location.

\- Alaska Airlines - 3/4 stars - Feels native-ish, nice "vanilla" design. Mix
of native forms and web views. All UI related to searching flights & buying
tickets is a web view. Every tap on the tab bar causes a full screen modal
spinner.

\- FOX Sports - 4/4 stars - Wow, impressive. Lots of native-feeling views with
their own branded styling. The custom widgets feel native.

It was great to find one "hero" app for Xamarin (FOX Sports), but the fact
that it's an outlier is a little concerning.

~~~
wilsonnb3
I believe the Fox Sports app was done by a company called WillowTree.

[https://willowtreeapps.com/company](https://willowtreeapps.com/company)

They specifically mentioned when I was interviewing there that the reason
their Xamarin apps are so good is because they already know how to make good
native iOS apps.

Also, I specifically asked about whether or not they would be using more
technologies like Xamarin in the future and they didn't seem too keen on it.

According to them, making a truly native seeming app in Xamarin isn't much
less work than making two separate native apps.

~~~
postfacto
Many businesses go with Xamarin because some guy in a management mandates it
because he feels it will be a silver bullet that will let them get around
having to hire skilled native mobile developers.

The reality is that to do Xamarin well you’ll have to wander outside out
Xamarin Forms, and to do that well not only do you need native mobile
developers but you need far higher caliber native mobile devs who are able to
mentally translate swift/objc and android calls into their C# equivalent, and
who have an idea of what’s going on the os when there’s a crash at a level
lower than the .NET runtime caused by a native part that’s not apparent in the
crappy Xamarin stack trace.

Xamarin really only makes sense if your company has a mountain of existing
complicated .NET code with priceless business logic that you absolutely have
to reuse.

------
mmastrac
We've had a mostly different (positive) experience doing a similar thing at
FullStory for mobile instrumentation, though I think I know where some of the
key differences are.

Our core "business logic" lives in Rust. This is a shared bit of code between
Android & iOS that mainly deals with orchestration, serialization, and server
communication. We managed to extract ~1/2 of each platform's native code into
this shared orchestration. What's left on each platform is more like a
platform driver.

I fully admit that things are different for us because we're not dealing with
a bunch of UI that we manage (instead we're dealing with UI that our customers
have written in Java/Swift/Objective-C/etc), but I think that there's a few
places where we've made this work in a better way:

\- We've chosen flatbuffers to serialize most (not all) of the data between
the platform drivers and the shared library.

\- We're using a language that's a little more hip. It's still not very easy
to hire Rust developers, but developers interested in Rust are _very_
interested.

\- We built tooling early on to make this pretty seamless. Our Rust code
builds in XCode and gradle, so there's no real friction to a developer getting
up and running.

Our team is about a year in on this transition to Rust and so far it's helped
us move far quicker, especially given the size of our team.

~~~
debt
“Our core "business logic" lives in Rust.”

Uh oh. So immediately you do understand that you have taken on the risk of
potentially being unable to find any good(or bad) Rust engineers in the
future, correct? Also they won’t be cheap as there won’t be many of them.

A smarter, business-friendly, future-proof approach would be to have done that
in Java. Future you will want you to have done that in Java, but if you’re
trying to retain good engineers maybe I get the Rust thing.

~~~
mmastrac
I see you got downvoted here, but I think it is worth replying. We evaluated
using Java on both iOS + Android (transpiled to iOS in some form), but what
tipped the scales towards Rust was the "fearless concurrency" (that turned out
to match the marketing) and the risk around the current state of transpilers.

I was a fan of Java for a very long time. It was my language of choice from
early 2000s to mid 2010s. It does _amazing_ things with keeping memory
management out of mind (while still giving you the the "backdoors" to make
things work well if you need a non-gc approach), but thread safety continues
to be a glaring hole.

From a former Java super-fan, I honestly think the future is Go + Rust.

FWIW we also evaluated Go as a shared language, but there were risks around
integrating our Go shared library with apps that may include some pre-existing
Go code.

~~~
PunksATawnyFill
Why not Kotlin? Isn't it Google's anointed successor to Java?

------
psyclobe
I was the engineering manager for a time at a company who launched a competing
product to dropbox (its dead now). During my time there we deployed a common
c++ core that did the business logic, and we wrote the uis in Qt with Qml for
the forms. We also used swig to export the c++ objects to java. Our ui forms
looked native, and they ran on every mobile os at the time (Windows phone,
iphone, android), and we even used some of the Qml forms on our desktop ui.

Yes it was kind of a pain in the ass to share code like this, but it worked,
and the mobile guys mostly just dealt with the specific problems relative to
the mobile domain and not api integration issues with our cloud.

That being said, I can tell you for certain our mobile devs (most of them
anyway) would've preferred writing their own client api in the native language
of the platform. Maybe Dropbox just got tired of dealing with that, they have
the money now to hire fleets of engineers to write just about anything on any
platform, why would you even bother sharing a client library in that case? But
in our case, we were a small team, so we really didn't feel comfortable just
letting the next mobile dev who walked in the door come up with another
foundation library.

Coding is hard, coding with a team is even harder.

------
jugg1es
I often struggle trying to explain to more junior developers that there are
times when it's OK to write code more than once. There is a mindset that you
should only ever write code once. It exists for (very) good reason. But if you
follow it dogmatically, you may end up with an unmaintainable tangle of
dependencies that can only be resolved with a rewrite.

Sometimes, it's OK to write the same thing twice if the alternative is a major
refactor - such as inventing your own stack.

~~~
reallydontask
You are fortunate if you only have to explain it to juniors.

This seems pretty prevalent among senior developers too, in my experience.

The most egregious case was, this guy I worked with, who would just straight
up start with abstractions to avoid _any_ duplication and enable other use
cases. Now, 9 out 10 times the use cases catered for by the abstraction failed
to materialise (bloody customers) but boy did he let you know when he hit the
abstraction lottery and what he'd done neatly fitted in with a new use case.

I think the term for what he created was ravioli code although maybe some of
it was lasagne code

~~~
Roritharr
>hit the abstraction lottery

Thanks, I'll use that from now on. A lot of wisdom in those 4 words.

------
softfalcon
Recently worked at a company doing similar to this to support Windows and
macOS.

To add to the difficulty, they used Chromium as a UI front end much like
Electron. All built in house though.

They hired me as a JS/HTML/CSS dev, but same as the article states, the C++
work was the true bottleneck.

They knew I had some C++ chops and set me to work doing C++ with a sprinkle of
JS here and there.

Due to incompatibilities in the compilers, there was a rats nest of
dependencies, thousands of #ifdef’s to cover differing OS implementations, and
we had to use some of the oldest versions of C++ to be compatible with both
XCode and Visual Studio.

As the article states, we had custom background job libraries and debugging
them was a nightmare.

Also similar to the article, we spent more time than one ever should setting
up builds to handle our ludicrously complicated build configurations.

And lastly, as the article stated, we had a hard time finding new talent to
cover the growing amount of work required to deliver our product. There just
aren’t many C++/JS devs out there.

~~~
ben-schaaf
> Due to incompatibilities in the compilers, there was a rats nest of
> dependencies, thousands of #ifdef’s to cover differing OS implementations,
> and we had to use some of the oldest versions of C++ to be compatible with
> both XCode and Visual Studio.

My current work has me on a single C++ code-base for Linux, Windows and MacOS
(not electron though, just native). You can avoid a _lot_ of headaches by
avoiding the platform specific tools and instead cross compile using clang
with a build system that works on all platforms (eg. ninja + meson).

~~~
lstamour
+1 for Clang. It integrates with everything. But like most open source
options, it plays second fiddle to each company’s primary languages, and so
thee’s no one IDE so perfectly integrated into these mobile dev C++ use cases
as to make it easy to work with, the way, say, you can be productive on .NET
framework with either C# or C++. Google and Apple are both C++ compatible, or
have native bindings, but... they target their examples and ease of use at the
languages that best integrate with the respective IDEs. (Swift for Xcode,
Kotlin for Android Studio) The end result is possible, but it’s like picking
Cordova/PhoneGap/Electron for your native app. You’re going to struggle to use
native technologies at some point, and there are few examples to follow.
Allowing for the realization that 80% of your app code is likely platform-
specific even if the UI doesn’t vary much means you can adopt new approaches
and native UI conventions faster. It’s like the difference in programming
speed when you simply target Chrome for your web development vs when you’re
trying to write code that runs on Internet Explorer also. It’s getting to the
point where platform functionality diverges so much that writing it but from
the same design/spec/data model is faster than trying to maintain
compatibility. Especially if you need to support multiple versions of iOS and
Android in a backwards compatible way and with different UI conventions in
different OS releases. Native is native, nothing else looks or feels like
native, when that’s what you need, and there’s more hand-holding for apps when
they follow the latest spec from the platform, rather than try to chase it
with their custom bindings/implementation...

Note re. targeting a platform — often learning and reading some C++ is
inescapable. For me, reading Chrome source code makes it easier to work with
Puppeteer in JS, or deliver a better web app because I know how things work
under the hood and it’s easier to read the C++ than the read the web standards
themselves. Similarly, C++ really is portable and fast, so it shows up in many
places. But on mobile, the mix of C++ to Swift/Kotlin should be 90%-platform
native if your app is a traditional CRUD app that deeply integrates with the
platform. If it’s simpler than that, build a website, or if it’s a game engine
or some custom UI, use that, sure, but if you want to benefit the most from
Apple and Google implementations, native (with shared spec/data models) is the
way to go...

------
cbsks
It seems like the real issue was that Dropbox lost all of their senior C++
engineers. That’s a real mistake on their part, losing the only people who
truly understand your product can be a death sentence for a company. I know my
employer is very conscious of who knows what part of our products, and does
their best to ensure that we never have any knowledge gaps.

~~~
chadaustin
You’re definitely warm. I worked at Dropbox around this time and there was
very little C++ or systems experience in the building. I think it’s expertise
they tried to build but for whatever reason didn’t. I work at Facebook now and
the difference is night and day. FB does share a ton of code across platforms,
and it doesn’t even feel controversial.

I don’t think Dropbox made a mistake in cutting out their shared C++ code, but
I would caution against generalizing code sharing as a bad idea.

~~~
babesh
It was partly organizational imho. Oftentimes non mobile teams would write C++
modules. After writing the module, that team would refocus on server but the
module would have remaining hard to find bugs (sometimes due to lack of mobile
expertise) or could just use additional love and care. Sometimes these modules
needing care and attention were even written by mobile specific teams. These
were also due to insufficient organizational attention.

------
jdswain
I've been using C++ to share code between iOS and Android for years and have
come to the same conclusion. I developed the C++ code on desktop operating
systems which was easier to debug, but once you move it to mobile then the
debugging gets a lot harder (on Android at least).

The overhead of the JNI interface is quite a lot of work too. Luckily I had a
UML model that I generated the interfaces out of, so adding JNI was just a
matter of templating this out of the UML, but it was still quite a bit of
work.

On iOS the situation has gotten worse in that the interface between Swift and
C++ has to go through C, so if you are using C++ you need a special interface
layer, which is almost like the JNI situation on Android.

So you have the trade-off of on one hand having two code bases (Swift, Kotlin)
and the associated headache of keeping them in sync, versus the extra work of
maintaining the C++ interface layers and testing and debugging on each
platform. In the end I now believe that it is better to work with the platform
native development tools rather than trying to share C++.

As far as finding developers goes, because of the rarity of using C++ on
mobile there will not be a lot of developers with this experience. I work
remotely and have found that any remote C++ work is very rare, Swift and
Kotlin are a lot easier to find work with (it's still more difficult that you
would think to get remote work of any type).

~~~
therockhead
>On iOS the situation has gotten worse in that the interface between Swift and
C++ has to go through C, so if you are using C++ you need a special interface
layer, which is almost like the JNI situation on Android.

I’m curious why you don’t add an Objective c layer for C++ interoperability,
I’ve done this in the past and it works a great.

~~~
jdswain
It's mainly because I'm trying to write everything in Swift now rather than
Objective-C. I still think Objective-C is a great language, but Swift is the
future of iOS development.

It was easier in Objective-C as you could just rename your code file with an
extension .mm rather than .m and that made it Objective-C++ and then you could
import your C++ headers and use your library as you should. With Swift you
don't have that option, and even the interface to C is more difficult.

Even with Objective-C there is still some work in converting data formats
(NSString to std::string etc.) and you need to be careful of C++ exceptions
and NSException.

------
IloveHN84
It looks like that took very poor decisions such as bad frameworks and in-
house made libraries vs what was already existing.

First, it's not true that there's no C++ mobile community. There are plenty of
forums, blog posts, projects, using C++ in mobile field. Xamarin and Qt are
helping C++ Devs go mobile since years.

Second, it depends on which standard they've used. It looks like they choose a
pre-C++11 standard, making things more complicated (in 2013 there were already
full C++11 compliant compilers, even for mobile), especially threads. They
probably forgot that Boost itself has modules for JSON, checks for non null
objects and so on.

Third, they probably kicked off the project with some average C++ developers
and they left. They haven't found cheap experts (compared to Kotlin/Swift,
which are really cheaper) and didn't want to pay high salaries. The story that
those Kotlin/Swift developers didn't want to learn C++ says a lot of the
quality of those developers as well. Sure, it's matter of interest, but it was
also a great opportunity to earn much more money as well.

As for build systems, it's true that it's an unsolved issue, but CMake is
pretty much a standard and it can handle dependencies, if someone knows how it
works. Sorry, but this is a story of poor choices and unskilled people for
this huge job.

------
jamil7
The cross platform landscape is pretty daunting for a solo dev. I ended up
just writing my app natively, time will tell if that was the right decision or
not. Most of my business logic is handled by my backend. I like the
performance and being able to implement platform specific features as soon as
they're released. I might look into doing some codesharing in Rust if it
becomes more straightforward. Sometimes it's OK to write things twice.

------
jkereako
This article hits close to home. I've been working with Xamarin for almost two
years now. It has done its job and provided a quick avenue to prototype a
concept and deliver a product. However, as the article mentions, the
maintenance is a bear. Here are some of the issues I face:

\- The developer experience is awful. Visual Studio for Mac causes so many
issues (crashes, mangled project files) it hinders productivity. About once
every two weeks I spend half a day wrestling with a VS issue.

\- As AirBnB's article mentioned, to be effective in cross-platform
development, you need to know three platforms well which is a difficult task.

\- Xamarin's performance on Android has notoriously been poor and only has
marginally improved. Try using a Xamarin app on a cheaper Android device or an
older version of Android.

\- No mobile engineers want to work on Xamarin.

That said, the good news about working with Xamarin is that it exposed me to
C# and the .NET ecosystem. I'm truly impressed with these technologies.

EDIT

I forgot to mention that I think the complexity of an app ought to determine
whether a cross-platform technology is a good idea. Xamarin is a great
solution for prototypes and simple apps.

~~~
king_magic
I’ve come to almost exactly the same conclusions. And it really is sad:
Xamarin developer tools _used_ to be decent, almost even good.

Today? I’d rather try to build mobile apps in COBOL than Xamarin. The
developer tools are so broken, so buggy, and so poorly documented that it’s
just not worth it.

I thought Microsoft purchasing Xamarin would have made things better at the
lowest level of the dev tools stack - hey, finally some investment will go
toward shoring up the dev stack! Nope, apparently not.

Years later, trying to connect VS for Windows to a Mac build server is still
astoundingly, soul-crushingly broken. No way to get support. No
straightforward way to file bugs.

Just a truly awful developer experience.

------
alexashka
Having worked in multiple places that ship iOS and Android, the real thing to
focus on is cross-platform requirements, not code.

Writing mobile apps is fairly trivial - writing good requirement documents is
black magic I have yet to see in the real world.

Trying to share code is like trying scratch your left foot when your right
foot itches. The issue with two codebases that are supposed to do the same
thing is keeping them in sync over time. The only way to do that is by having
actual requirement documents.

~~~
kelnos
This made me think: I've found it hard enough to share code effectively on the
backend, even when we're all using the same language and frameworks.

And people think it'll be easy to share code when you're targeting two
completely different platforms with completely different frameworks in
completely different languages?

------
jacobsenscott
Add more fuel to the "write once, run anywhere" dumpster fire. Let's peek in
there - I see C, C++, Java, JavaScript, stored procedures, wxWidgets,
RubyMotion, GTK, QT, object oriented programming, functional programming,
PhoneGap, React Native, Flutter, ... It is getting full in there.

What's that about the definition of insanity? Doing the same thing over and
over and expecting a different result?

Sever side rendered HTML is the closest we've come, but that's not cool
anymore.

~~~
mleonhard
I'm using Flutter successfully. It has the potential to become a really great
platform.

Java is a good language, as long as you rarely use implementation inheritance.

I would not recommend using React Native or C++ for any project.

~~~
pjmlp
React Native - JavaScript, plenty of jobs outside mobile dev.

C++, plenty of jobs outside mobile dev, and a very nice pay to come along.

Flutter - Dart, death silence outside Flutter use cases.

~~~
la_fayette
I like doing projects with ionic, which have the great advantage to be ported
to the web and also packaged as desktop apps. From all the apps i have
developed with web tech or even i know of no users are complaining about lower
performance or similar. Why developers have this opinion?

------
eridius
1.5 years ago Dropbox was looking into rewriting their shared mobile codebase
in Rust. It's a shame this blog post doesn't touch upon that at all, instead
focusing on C++.

~~~
zZorgz
Their hinted opinion on that:

> That being said, C/C++ are the only languages with a compiler supported by
> both Google and Apple, so using a different language would have created a
> whole host of other problems to deal with.

~~~
eridius
I'm not sure why "supported by both Google and Apple" is supposed to matter.
Apple doesn't need to ship a Rust compiler for me to use Rust.

~~~
zZorgz
Likely too much friction. Native environments benefit from using the expected
IDE and tooling integration to build UI apps on respective platform. C or C++
is the best common supported language, and they didn't even like that.

Also the UI frameworks are being written in said preferred language these
days, eg SwiftUI, and adding one additional language could be perceived as a
pain.

~~~
eridius
Apple ships a C++ compiler but you can't use C++ with Apple's platform SDKs.
IF you want to use C++ you need to write Obj-C++ glue code to access most of
the system frameworks, including UI code.

~~~
pjmlp
Metal and driver SDKs require C++.

~~~
eridius
Metal is Obj-C.

~~~
pjmlp
Then try to write Metal shaders in Objective-C.

~~~
eridius
Metal shaders != Metal API. Metal API is Obj-C. Metal shaders are written in
MSL (Metal Shading Language). C++ is still not involved, though MSL is
admittedly based on C++.

~~~
pjmlp
Metal API ⊇ Metal Shaders, it is useless without them.

[https://developer.apple.com/metal/Metal-Shading-Language-
Spe...](https://developer.apple.com/metal/Metal-Shading-Language-
Specification.pdf)

"The Metal programming language is a C++14-based Specification with extensions
and restrictions. Refer to the C++14 Specification (also known as the ISO/IEC
JTC1/SC22/WG21 N4431 Language Specification) for a detailed description of the
language grammar. This section and its subsections describe the modifications
and restrictions to the C++14 language supported in Metal."

Also, the MSL and Objective-C compilers are built on top of LLVM, written in
C++.

~~~
eridius
I don't know what point you're trying to make. MSL doesn't link with the rest
of your program. No matter what language you use for your program, the shaders
are written in MSL. For my program if I use Rust or C++ or Obj-C or Swift or a
microscopic magnet and a very careful hand, I write my Metal shaders in MSL.

~~~
pjmlp
1 - MSL is a set of extensions on top of C++14

2 - Metal requires MSL

3 - IO Kit is a C++ framework for macOS, iOS, iPadOS and watchOS drivers

4 - Metal GPGPU drivers are written in IO Kit

5 - Metal is useless without MSL and GPGPU drivers

6 - Ergo, Metal requires C++

~~~
eridius
The fact that Metal itself requires the existence of C++ really has nothing to
do with this topic though, which is whether there's any downside to writing
your app in a language that Apple doesn't ship a compiler for. The fact that
Metal shaders are written in a language based on C++ is irrelevant to this
question, because it doesn't matter what language you pick for the rest of
your app as Metal shaders don't link with your app. Swift has zero integration
with C++ and yet I can write a Metal app using Swift, because the fact that
the shaders are written in MSL has no impact on the fact that the app uses
Swift.

And the language for writing drivers in is even more irrelevant because we're
not talking about writing drivers. You can't write drivers in Swift either.

------
s_y_n_t_a_x
It baffles me that people think duplicating application code for every device
is the way to go. Cross platform can be done correctly. I'm working on a stack
that can natively target Windows, Mac, Linux, Android, iOS, MacOS, and Web. I
couldn't imagine duplicating my code for each one of these devices. If
something special needs to be done, I write an extension.

I have a feeling posts like these get upvoted because developers who make the
native apps want to keep their jobs. But those developers will always be
needed for the native bridges, just not as many of them.

~~~
K0nserv
I'm very much in the cross platform is a bad idea camp. It's fine for sharing
business logic and other non-UI code, but having tried several cross platform
UI kits I've never found it to work well. Cross platform UI always ends up
compromising on the native UIs strengths and uniqueness resulting in poor UX,
poor accessibility, unaccceptable resource usage, bloated binary size etc.
Just a few concrete examples:

\- Non standard UI/UX is super common because cross platform UI targets the
lowest common denominator. Flutter is the quintessential example of this, it
throws away all native UI support and renders everything from scratch with low
level graphics. In React Native I've observed several cases where iOS UI has
been re-implemented, poorly, in Javascript and shipped on Android and iOS.

\- Poor accessibility. Native iOS apps get a lot of accessibility for free
because Apple has done a great job, with RN and especially Flutter you don't
get this benefit.

\- Resource consumption. Electron is terrible in this regard as is the common
meme. React Native runs a JS VM for every app which surely has a negative
impact on both battery and performance.

\- Binary size. A basic Flutter/RN app easily pushes you past 20MB in app size
on iOS, whereas a complex and complete app like Tweetbot is ~7MB.

It's certainly possible to build great UX with cross platform UI frameworks,
but the amount of work required to do it well starts to get into the territory
where you are better of just doing it natively in the first place.

~~~
s_y_n_t_a_x
React Native can wrap any native component and bridge it into your app. If you
had bad experience with a 3rd party component, that's not RN's fault, build
your own extensions you need, but for the most part you just need the core.
It's still easier than rebuilding your app X times.

\- React Native you most certainly do get accessibility.

\- Running a JS VM isn't that bad, but it is a tradeoff. Imo it's completely
worth it to prevent having to learn X different languages for each platform.

\- The app size evens out, but yes the minimal is higher. However many apps
are much larger than 20MB, it's better than other cross platform solutions

In no way are any of these things so bad where I would duplicate my code 6
times and then maintain them throughout the life of the project. That's just
crazy.

~~~
K0nserv
> React Native can wrap any native component and bridge it into your app. If
> you had bad experience with a 3rd party component, that's not RN's fault,
> build your own extensions you need, but for the most part you just need the
> core. It's still easier than rebuilding your app X times.

Yes a great strength of React Native is that it still leverages the native UI
kits and makes it possible to do so when building custom components. My
comment wasn't about my experience, in fact I've built numerous bridged
components in RN, but and observation about the react native community. In
fact one of the most crucial lessons I've gathered when working with RN is
that you must have both iOS and Android experts in your team to build good
apps with RN successfully.

Here's just a few examples of popular 3rd party components(from awesome-react-
native[0]) that are problematic in my eyes:

\- react-native-swiper[1]. Completely custom JS implementation with a "iOS"y
look. 8k stars

\- react-native-gifted-chat[2]. Large completely custom JS implementation of
chat UI. 8k stars

\- react-native-slider[3]: A pure JS implementation of a slider. 1k stars

> \- React Native you most certainly do get accessibility.

My point wasn't that it can't be done, but that it requires significantly more
work that, let's face it, most developers will not do. With native UI you get
a lot more for free which results in a better user experience for everyone.

See
[https://news.ycombinator.com/item?id=20709259](https://news.ycombinator.com/item?id=20709259)

> \- Running a JS VM isn't that bad, but it is a tradeoff. Imo it's completely
> worth it to prevent having to learn X different languages for each platform.

I agree it's a tradeoff and to be fair I don't have more than a hunch that
running a JS VM is bad for energy and resource usage. The tradeoff is
distinctively on the user's expense in favour of the developers. As developers
shouldn't we be making tradeoffs that benefit our users instead?

> \- The app size evens out, but yes the minimal is higher. However many apps
> are much larger than 20MB, it's better than other cross platform solutions

Yes many native apps do grow quite large too, my point is the default. The
most basic RN, but especially Flutter, app is much larger than the native
counterpart. Again a distinct tradeoff on the user's experience in favour of
the developer.

0: [https://github.com/jondot/awesome-react-
native#components](https://github.com/jondot/awesome-react-native#components)

1: [https://github.com/leecade/react-native-
swiper](https://github.com/leecade/react-native-swiper)

2: [https://github.com/FaridSafi/react-native-gifted-
chat](https://github.com/FaridSafi/react-native-gifted-chat)

3: [https://github.com/jeanregisser/react-native-
slider](https://github.com/jeanregisser/react-native-slider)

------
eejjjj82
The best way I've seen this work (inside Google Apps) is to write shared
business-logic in a common layer (here it (often) gets written in Java, then
transpiled to Obj->C and Javascript, other teams go from C++ -> Java & JS, and
other other teams embed JS inside of everything.. and other other other teams
write everything in a native language (there is no one single way at Google))

then use a data-definition-language (like protobuffers) to define a bridge
from inside of transpiled code land to your native layer, and compile native
language bindings for your UI to read & write data models.

then stack a mechanism like GRPC which takes the DDL to the next level and
makes services a declarative, language agnostic definition... and compile your
service stubs for each platform.

...then write the UI in a native layer for each platform, using the native
service stubs and data models compiled from your DDL.

Once you start trying to abstract the UI models between iOS, Android, and web
you are stuck with a shitty status quo solution that leads to terrible hacks
or boring concessions that ignore platform differences.

However abstracting the common (non-ui) mechanisms like asynchronous data
structures, sockets, and storage is a relatively solved problem.

~~~
leadingthenet
Oooor, you could just use Kotlin and Swift and be done with it.

------
dpezely
_The overhead of C++ adoption actually prevented us from ever moving fully in
this direction._

Today, unlike in 2013 when they started, there are other options.

For others considering code-sharing, another option not mentioned in their
article is Rust for the core with Swift and Kotlin. Between bindgen, futures,
serde_json and non-nullable pointers in Rust, those would satisfy their stated
subcategories today.

Companion templates are explained here: (January 2019)

Medium.com/visly/rust-on-ios-39f799b3c1dd

Medium.com/visly/rust-on-android-19f34a2fb43

(No affiliation other than starting to proceed down this path myself.)

For Common Lisp heads, there's also MOCL, which seemed quite reasonable when I
explored it years ago: wukix.com/mocl

~~~
saagarjha
How does Rust differ significantly from C++, other than the fact that neither
platform's toolchain can compile it out of the box?

~~~
rapsey
It is really easy to make a blunder in c++ that will require a lot of effort
to find. Debugging that on mobile platforms is not fun. Like they mention a
deadlocking issue that was difficult to solve.

Rust is built for memory and thread safety. Also the much better build system
and open source ecosystem.

~~~
saagarjha
> Debugging that on mobile platforms is not fun

That's debatable ;)

------
dragonsh
This is precisely the experience of my startup trying to rely on flutter. It's
a constant battle. Moreover Android and iOS are different implementation with
different capability with constantly evolving API. It's hard to keep cross
platform code in sync many #ifdef with edge cases.

Moreover with REST API architecture majority of the common code is in back-
end. So building in Swift and kotlin for respective platform is not as
tedious.

~~~
The_rationalist
Could you explain what you think of the pros and cons of flutter VS IONIC? I
think flutter and it's astonishing number of issues on github + their lack of
manpower + their lack of major features + the presence of major performance
and behavior bugs + the extremely small lib ecosystem (dart) is a major,
useless risk for a startup for the benefit of tech hype. (just my point of
view, don't take it personally)

~~~
Diesel555
I've been writing in Ionic for a while now. I enjoy their philosophy. They put
out their own description of the differences with Flutter (biased I'm sure).
[https://ionicframework.com/resources/articles/ionic-vs-
flutt...](https://ionicframework.com/resources/articles/ionic-vs-flutter-
comparison-guide)

Ionic lets me build a web app and publish it to any device pretty easily. I
don't have to use their components either... in fact after using Ionic, you
may not use Ionic anymore at all. All you need is Capacitor to publish it.

Flutter is it's own rendering engine, non-standard web language (Dart), and
ecosystem. Ionic is just a CLI and collection of web components. Capacitor is
Ionic's version of Cordova. It gives you access to device capabilities such as
storage, camera, etc with very little code. So you can build a website, ask if
it's Native on a device, and do more cool things if it is. Then push it to
Android, iOS, and the Web.

Ionic supports Angular, React (now in RC0), and Vue (Beta). This allows you to
learn popular frameworks while still developing with one code base.

Lastly, Ionic's Web Components are built using standard-compliant Web
Components generated by a tool they made called StencilJS. So, now you can
build a component in Stencil and publish it for simply the Web (No framework)
or have them work with Angular, Vue or React. Larger corporations have started
using StencilJS to manage their components when they use many frameworks. I
use it because I don't know which framework I'll use next, or if I'll even use
one.

~~~
The_rationalist
What are the pro and cons of ionic Cordova vs ionic capacitor? How feature
complete and stable is capacitor vs Cordova?

~~~
Diesel555
Cordova is time tested and has a large community behind it. I choose Capacitor
if it's available and then go to Cordova if it's not. Ionic has a collection
of easy to use Cordova plugins
([https://ionicframework.com/docs/native/overview](https://ionicframework.com/docs/native/overview)).
I have honestly found they they are not that well maintained. I ran into
enough issues that I avoid them if I can. To be fair, the contributors are
people contributing on their own free time with no financial incentive. Hence,
I choose Capacitor when I can. They have a financial incentive (Ionic is open
about this [https://ionicframework.com/blog/ionic-2019-business-
update/](https://ionicframework.com/blog/ionic-2019-business-update/))

I joined when Capacitor was in beta and figured I'd use the up and coming.
From research, it appeared there was a good reason Ionic created their own
product. They didn't do it to simply stop using a tried and true product.

Also to be clear, Cordova is not an Ionic product. It was a great community
thing for a while to talk to native devices.

------
pjmlp
Having done this quite a few times, it looks more like they are having issues
to retain C++ developers, are too picky on their hiring process and the
original devs have left, than anything else.

And given some of the macOS client practices, the engineering quality is also
to wonder.

For me, C++ with native views, or Xamarin, will keep on being the way to do
mobile apps that can't be done as PWAs.

------
commanderjroc
I don't understand why someone at Dropbox's size and scale would go after C++
on mobile and blaze their own trail, when its probably more pragmatic to go
native.

With that being said, I worked for a firm that extended the life of old ERP
systems and we had to do a few mobile apps, we chose Xamarin because we were a
shop of 7ish devs that had many projects to maintain and the cost of code
sharing and familiarity with C# were our driving factors. It was a trade off
most definitely but it was a pragmatic choice as well.

If you are capable of hiring more developers who know Java or Obj-C and can
allow them to do only mobile development then its worth it to go native.

But, if you are a small company and know that Java,C# and Obj-C, C# developers
are a little bit hard to find (depending on your developer market) then its
probably more cost effective to go Xamarin or any other cross-platform code
sharing model.

In the end its all about pragmatism.

~~~
bena
Isn't Xamarin the IDE and cross-compiler? Last I saw, it took C# and cross-
compiled to native Android and iOS apps.

Or had a .net runtime that ran on both.

Regardless, you need a C# developer if you're choosing Xamarin as your
tooling.

~~~
amaccuish
iOS requires AOT compilation as interpreted/bytecode languages AFAIK are
restricted to the Nitro JS engine. With Android it compiles with a .NET
runtime included IIRC.

~~~
commanderjroc
Yes, it uses Mono under the hood as the .NET runtime.

------
breatheoften
> Because this issue involved debugging multi-threaded code running back and
> forth between C++ and Java it took weeks to nail down!

I don’t think the issue here is the use of c++ — it sounds to me like it’s the
use of c++ on problems that would have been far simpler solve on the native
code ... not all problems are that way — but even where it makes sense to
solve with c++, you have to be careful about the glue.

I developed and maintained cross platform c++ for iOS/Android in a previous
role and the platform to native glue is inherently complicated — among the
most complicated parts of the program to reason about if you get into the
details of it. I solved by making this layer dead simple — you could almost
never pass objects in or out — just primitive values.

The c++ layer exposed to platform was just static methods — including a bunch
of methods for retrieving state and we added more static methods when new
kinds of communication were required. Every c++ method grabbed the largest
lock it could prior to doing anything natively (and in debug mode related
methods associated with some kind of stateful lifecycle would fatalError if
they couldn’t get the needed lock — the app code shouldn’t have been calling
into native code in a way that violated simple assumptions about how the state
was allowed to change).

Interestingly — this forced the platform layers above to comply with the
assumptions needed to keep the native code simple — and helped those working
on the UI immediately find out when they were violating these assumptions —
things like click handlers that weren’t debounced or weren’t switching to a
disabled mode after being clicked — when those click handlers invoke native
code and that native code mutates state — you have a potential nightmare
scenario for robustness ...

This model actually was quite straightforward to add new functionality to over
time and we frequently moved decision authority over complicated logic into
the native layer so that we could make it robust and cross platform ...

------
saagarjha
I'm somewhat disappointed that this didn't work out, as I have usually
promoted a C++ core along with a thin native wrapper as the solution for those
looking to share code across platforms. At least they moved to native
development, though, instead of some poor facsimile that was "easier"…

~~~
barbs
Curious about how well having that C++ core to share code has worked out for
you in the past. Apart from low-level contained code that doesn't require
access to too many OS interfaces (user I/O, network, threading, GPS etc) I
can't imagine it would be easy or useful to have a C++ core.

~~~
saagarjha
Usually C++ runs core logic that cannot go on the server (that's things like
your own custom client-side crypto, parsing, or other "pure computation") and
then you make the user interface in Swift or Java depending on your platform.

~~~
barbs
That makes sense - basically anything that is self-contained and can run "in a
vacuum" so to speak can be C/C++.

------
archeantus
Interesting post. I wonder if the major pain point was the fact that they were
doing dev with a language that had nothing to do with either platform.

We’re currently investigating Kotlin/native and it looks really promising. We
don’t have to write stuff in a foreign language, but can repurpose our
existing Kotlin code and share with iOS. This model seems promising.

Does anyone have any experience with Kotlin/native?

~~~
pjmlp
C++ has lots to do with Android and iOS.

On Android side, Vulkan, ML, real time audio are all only available via the
NDK.

Project Treble allows for Java and C++ drivers, but the large majority of them
are actually written in C++.

Real time audio framework, Oboe, is written in C++.

The Play Games infrastructure is written in C++.

On the iOS side, Metal shaders, former driver framework and the new one use
C++.

Objective-C++ is part of the SDK and allows for easy interoperability between
Objective-C and C++.

Swift and clang build on top of C++, thanks to LLVM.

Finally, C++ is part of the official language list on both platforms.

So contrary to urban myths, C++ has plenty to do with both platforms.

~~~
archeantus
Good points. I guess I didn’t mean that the language wasn’t valid or
supported, but rather, that it wasn’t the main first-class language of the
platform.

------
wpietri
What I don't see them saying was that it was the wrong choice in 2013 for a
scrappy team and an evolving product, just that it's not the right choice in
2019 for a company with ~infinite dollars and a stable product.

I'm looking at building a mobile product solo right now, and I'm finding
Flutter a pretty compelling idea. Building everything twice means being circa
twice as slow, meaning I can learn about what the market needs half as fast.

I might be wrong, of course, but this isn't the article to persuade me
otherwise.

~~~
h3ctic
I'm in the same boat, but chose React Native instead because learning more
React + JS/TS has additional benefits

------
petters
Hasn't Microsoft successfully written their mobile Office apps in C++ in a
single codebase?

~~~
therockhead
Indeed they have. What’s missing in some of the discussion here is the size of
the application. For large applications like Office, a shared code base is
often the correct strategy.

~~~
NickGerleman
I work on Office and am glad someone brought up this point. Writing a C++
business logic layer is probably too much for a simple CRUD style app, but the
equation changes once the view/platform layers are a tiny minority of the
logic in your app.

------
asdfman123
It's funny that they have a hard time hiring experienced senior C++ devs even
though the language has been around so long. Presumably it would have been
easier to find someone really good at something newer like, say, Vue.

~~~
jjtheblunt
I wonder if that is a symptom of C++ having many recent revisions, thereby
influencing, misleadingly, the definition of "experienced".

~~~
rabidrat
Yeah, I have 15 years of C++ experience, but not since 2012. So with C++11 and
C++17 (and soon C++20) my skills have not aged well, even though I can still
write C++03 just fine. It's no wonder 'senior' devs prefer to use plain C,
where even C11 is not that different from C99.

~~~
ryl00
> my skills have not aged well

I don't think that's necessarily the case. C++'s famed backwards
compatibility, source of so many issues, is also a fabulous strength. There's
nothing stopping one from writing C++03, while gradually adapting C++11 and
beyond as time/circumstances permit (which is what I'm doing at my job,
maintaining a massive legacy codebase while stymied by slow uptake on newer
compilers by my corporate overlords...)

> It's no wonder 'senior' devs prefer to use plain C

Not this senior (in years, at least :)) dev. I've tasted RAII and I can't go
back...

~~~
elgenie
The problem from Dropbox's perspective is that they're not merely hiring
someone to create a solo greenfield C++ codebase, but to contribute quickly to
a codebase written in whatever arbitrary subset of C++ they blessed.

------
rock_artist
I'm also in that approach for the same reasons. Currently I have an app I'm
cross-developing with separate iOS / Android codebase. the only 'shared-code'
is Firebase libs for each platform (which seems to be written in itself cpp
and bind to Kotlin / Swift).

C++ itself is pretty portable. There are actually frameworks (QT / JUCE) that
allow true cross-platform builds. They work, but you'll eventually end up
having a lot of branches for specific platform.

Still if you just need basic algorithms (signal processing or anything
expensive CPU based) C++ might be good enough to write simple callbacks with
bindings.

Evil UX/UI: \-----------

Xamarin, Flutter, React Native - It really depends on the app. but if the app
needs to be in the "device" UX and the unique APIs provided by the platform.
people can glorify the cross-platform all they want but, You'll eventually end
up with branches for each platform in the good case and bad performance in the
worse case.

------
shultays
I worked in a company that makes games for both ios and android and it shares
majority of the code in between. It was using libgdx which uses Java & opengl
and it was working very well for us.

I would say things are not so bad when you pick your tools right.

~~~
manmal
I think the use case Dropbox has is quite different, because they have a lot
of native code surface, needing lots of interactions with the shared code
base. A game can get by with only a few lines of native code, AFAIK.

------
irjustin
The common thread that I personally see between dropbox and airbnb, though
completely different language sets, is adopting a shared codebase in a "brown
field" manner.

Airbnb admits if they were able to greenfield React Native then there's a
world where it would have worked.

Separately, the complexity of Airbnb and Dropbox as apps is very high compared
to what I believe are the ideal use cases - simple interface apps that are
thin wrappers on top of APIs.

------
dilawar
How's was your experience in writing iOS and Android app in Cordova? I have a
small community app written in Cordova+f7+vue2 which works pretty well on
Android.

I want to port it to iOS now as there is some demand. I also want to add push
notifications later. So far there is a inhouse API+server which serves as
backend. Not dependant on Google for any services as of now; only if there is
a non-firebase solution to push notifications?

------
ksec
I wish all the articles and blog post are like that. The first sentence sort
of gives away what you need to know.

 _Until very recently, Dropbox had a technical strategy on mobile of sharing
code between iOS and Android via C++. The idea behind this strategy was
simple—write the code once in C++ instead of twice in Java and Objective C._

A lot of people will stop reading after this, for those interested they could
continue with the details.

------
avinium
TLDR - it's too hard to find senior C++ mobile devs.

I'm more intrigued by AirBNB moving away from React Native - the linked
article says "RN was too small a component to bother supporting, and the
developer experience wasn't up to par", but I'd like more detail than that.

I've been working with Flutter for the past 6 months, and it would definitely
be my "go-to" for any mobile application.

To be fair, I did spend 2 weeks going down a rabbit-hole to get Flutter
talking to a .NET assembly by embedding Mono and invoking via JNI/Obj C, so I
know the pain of native interop. If you're mostly doing work at the native
platform level, then I can imagine why you'd stay away from a cross-platform
VM.

In my case, I ended up with a brittle project that was clearly going to be a
PITA to maintain & automate builds for, so I just rewrote the component in
question in Dart.

~~~
bobthepanda
AirBnB has a series of in depth blog posts about their decision to abandon RN.
In particular this quote seemed extremely worrying to me:

> While debugging, React Native attaches to a Chrome Developer Tools instance.
> This is great because it is a powerful debugger. However, once the debugger
> is attached, all JavaScript runs within Chrome’s V8 engine. This is fine
> 99.9% of the time. However, in one instance, we got bit when toLocaleString
> worked on iOS but only worked on Android while debugging. It turns out that
> the Android JSC doesn’t include it and it was silently failing unless you
> were debugging in which case it was using V8 which does. Without knowing
> technical details like this, it can lead to days of painful debugging for
> product engineers.

[https://medium.com/airbnb-engineering/react-native-at-
airbnb...](https://medium.com/airbnb-engineering/react-native-at-airbnb-the-
technology-dafd0b43838)

~~~
abacadaba
Having been bitten by this exact issue one or two times, meh. Par for the
course in the life of a Javascript dev, really.

RN would definitely still be my go to tool for the majority of green-field
mobile apps. If I'd already invested in learning flutter/Dart I'd probably
feel the same about that, but certainly feel no urgent need to go out and
learn it. As in, I don't think there's a significant difference in what I'd be
able to accomplish, and my time is probably better invested elsewhere.

~~~
bobthepanda
That's great from a dev perspective. Not so much from a product perspective,
particularly if you operate at AirBNB scale and your issue could be costing
lots of money for every second of failed debugging.

~~~
abacadaba
i don't remember exactly how long this cost me, but it sure as fsck wasn't
days. ymmv.

------
unnouinceput
Due to C++ inherently close connection with the OS I see this as an absolute
happening. But they should've go with Objective-C and Java and stay with them,
as they were the matured technologies back in 2013 for their target OSes.
Instead they chose another young ones. Oh well, not going to cry due to
Dropbox making Kotlin and Swift better due to still lack of libraries there
for their purposes. The more the merrier, that's my motto. My absolute fear is
the manager's dream to only UML be as programming language and they
drag'n'drop with no coding behind (the wet dream back in 2005 my manager at
Siemens had, and he told me the world is going that way. Ya sure buddy, not if
we let it happen and so far instead of unification we have even more
diversification)

------
lenkite
Using C++ for libraries was not a bad idea but I think they got the
architecture wrong. They should have used a protocol like gRPC streams or
flat-buffers to communicate between core libraries and the platform UX
libraries. Basically the mobile app is treated as a frontend talking to a
backend using a communication protocol. You can design this to be stream-
based, event-based, whatever fits the boat best. Depending on the platform,
you can choose what should be part of the frontend versus what should go into
the backend.

This is the way a lot of the big C++ mobile apps are built. Also there are
lesser debugging headaches as each part can developed independently thanks to
de-coupling, so you can hire native platform developers to do the job they
know best without messing with C++.

------
joeblau
Here is the genesis of this blog post: CppCon 2014: Alex Allain & Andrew
Twyman "Practical Cross-Platform Mobile C++ Development[1].

[1] - [https://www.youtube.com/watch?v=ZcBtF-
JWJhM](https://www.youtube.com/watch?v=ZcBtF-JWJhM)

------
aedron
Does anyone have experience trying to do this kind of thing with LibGDX?

LibGDX is a layer on top of OpenGL (lwjgl actually), and used a lot for game
development. It is based on Java, and is able to package the application for
Android, iOS, Windows, Linux, Mac, and even web (targeting WebGL). For iOS it
uses RoboVM, and for the web export it uses GWT to compile to JavaScript.

Obviously this is best suited for custom UIs (like games), but with some
frameworks on top it seems it would be possible to build a decent interface.
The framework already has support for most platform specific functionality
(like text input). Performance should be great because it runs close to the
metal, so to speak.

Just curious if anyone has tried this, as I am considering the approach.

~~~
la_fayette
Actually flutter is based on this approach. The native widgets are completely
recreated with this dart based runtime. Performance is indeed great, however
it seems like a hell lot of work to create all these widgets...

------
olalonde
As usual, what is true for a 1000+ people org might not be true for your
bootstrapped startup.

------
m3kw9
Code reuse on anything that is too complex will usually give you these issues
as reuse doesn’t scale unless is very simple and function is super well
defined and focused. Programmers will turn it into a monster as it evolves,
usually

------
CalChris
This reminds me of LLD’s approach of sharing an architecture but having
separate ELF, COFF and Mach-O implementations. This made it much faster than
gold which wasn’t actually slow.

Apparently sharing code isn’t necessarily a great idea.

~~~
fsfod
They did start out with a shared atom model for all three platforms but
switched away from to separate implementations for ELF and COFF
[http://lists.llvm.org/pipermail/llvm-
dev/2015-May/085088.htm...](http://lists.llvm.org/pipermail/llvm-
dev/2015-May/085088.html)

------
darshan
I just launched (like, an hour ago:
[https://news.ycombinator.com/item?id=20700196](https://news.ycombinator.com/item?id=20700196))
a cross-platform app that is almost all shared code. In my case, the solution
is a web app with very lightweight native wrappers, and I'm quite happy with
it. Obviously that wouldn't be the perfect fit for all apps, but none of
Dropbox's "(not so) hidden costs" are relevant in my case, and I suspect many
apps _would_ be a good fit for the architecture I went with.

~~~
morcutt
Most cross-platform solutions are great in the beginning and then the problems
start to come to surface as teams grow, requirements change, bugs are harder
to track down, code needs to be updated, the next hot cross-platform framework
comes along with new promises, etc.

~~~
Scarbutt
You seem to be describing problems with _all_ software that has to grow.

~~~
morcutt
Sure but, these issues come to surface much quicker.

Every time I've started a new iOS project in the past ~2 years, I've reached
out to a handful of developers and managers on how cross-platform is going for
them. None have been completely sold on it. The ones that are, are the ones
that have been doing it for a few months. I've come back around to talk to
them months later and they aren't so confident in the decision anymore.

------
PunksATawnyFill
OK, but they didn't attempt to use Qt.

I'm currently working on a project where we have indeed decided we needed to
go Swift/Kotlin native on each platform, but with the long-term goal of
building a cross-platform app with Qt.

Qt certainly has its issues, but I respect what its developers have
accomplished. And it appears to offer adequate ways to do common things like
parse JSON, and it abstracts things like Bluetooth usage and file storage in
the apps' sandboxes; so I don't see some of the hurdles cited in this article.

------
bstar77
I shudder to think how many people will read this headline and immediately
takeaway that React Native/Flutter/Electron are terrible cross platform
solutions.

~~~
chipotle_coyote
I'm hoping more people will read this headline and at least take away that
RN/Flutter/Electron should be approached with caution and care rather than
"slap it in an Electron shell and it'll run great everywhere and everyone will
love it," which is the implicit attitude that makes so many people, uh, not
love it.

------
Shorel
This is more about not finding enough developers for mobile C++, not much
because of any sharing of code.

A single platform application with a C++ back-end would have the same issues.

------
krzat
Current state of sharing code between platforms is quite terrible. Most
languages support only C FFI, so if you write shared code in C++, will require
bridge from C++ to C and then bridges from C to native platforms.

For CRUD core, this kind of overhead makes no sense.

I think this situation could be improved with automated generation of bridges.
Apple implemented this pretty well for their own purposes, you can call Swift
from ObjC and ObjC from Swift quite easily.

------
nbevans
When you're at Dropbox's scale it's easy to just hire a load of iOS and
Android devs, and some product managers to keep them all in sync.

But when you're not at that scale - you can't afford to build the same app
twice - you are often left with a choice of either Xamarin or React Native.
Both of these are perfectly good frameworks on which to build software; don't
let the FUD win.

------
kdaker
As someone who has built a C++ library to share across iOS and Android I
completely agree. The biggest issue for us was finding developers willing to
learn and adopt C++.

For our use case we weren’t writing UI or user flow logic, it was an ‘engine’
that handled complex business logic. It used JSON as input and output.

If I were to do that same project again I would use mostly native code and
write our engine in Javascript.

------
wsc981
Since it's not stated in the article, I am going to assume they haven't tried
Xamarin.

I've been really pleasantly surprised lately how much code can be effectively
shared when using Xamarin Forms. I haven't encountered much problems, except
when dealing with tricky stuff like the Android camera API's (which, from what
I understand, is problematic in native Android code as well).

~~~
dmitrybrant
How about running a background service to synchronize a local folder of
content with a remote server? Making sure the background service is launched
correctly upon startup? Integrating with the OS's native sharing features with
other apps? And so on.

In my experience, using a "cross-platform" framework means that you'll write
the code not once, but three times: once for the cross-platform framework, and
once per platform (Android / iOS) given all the quirks and unavoidable
customizations that will need to be made to make your app function correctly.

~~~
wsc981
For platform specific stuff it's easy to write a wrapper. Most of the time
Xamarin is very closely up to date with Apple's SDK, due to some automated
tooling that generates the C# classes, interfaces and such. So you should be
able to either use the C# wrappers for platform specific functionality, or
alternatively can quite easily create your own binding using the Sharpie tool
[0].

The last 2 apps I've been working on were Xamarin apps and I'd guess the first
app probably shares 80% - 85% of the code base and the second app 95%. The
first app less, because the client wanted a specialised camera module, which
required me to create bindings for the Fotoapparat [1] library on the Android
platform.

Both apps used Xamarin Forms. The platform specific code, all things
considered, is really small.

I should note I've also done a lot of Swift & Objective-C development in the
past and a little bit of Java. I also tried Xamarin around 2013 and back then
the experience wasn't as good as it's right now.

My major gripes with Xamarin currently are: \- The IDE becomes slow sometimes
(fixed with a restart) \- The IDE sometimes has issues connecting to the
Android emulator for debugging (often restarting the computer fixes this).

I should also note that if I were to write an iOS only app, I'd definitely use
Swift (I love working in Swift, more than C#, Objective-C, Java, …). But for
multi-platform apps, currently my tool of choice is Xamarin.

\---

[0]: [https://docs.microsoft.com/en-us/xamarin/cross-
platform/maci...](https://docs.microsoft.com/en-us/xamarin/cross-
platform/macios/binding/objective-sharpie/)

[1]:
[https://github.com/RedApparat/Fotoapparat](https://github.com/RedApparat/Fotoapparat)

~~~
vlozko
I wonder how well Xamarin will work with Swift-only frameworks, like the
upcoming SwiftUI and Combine frameworks. They make heavy use of Swift
generics. It’s been a long time since I’ve touched Xamarin so it’s a genuine
curiosity.

~~~
wsc981
I've used Sharpie Bind with a private (internal use) Swift Framework and it
worked fine for me. But the Swift stuff is currently not officially supported.
I've used these instructions: [https://medium.com/@Flash3001/binding-swift-
libraries-xamari...](https://medium.com/@Flash3001/binding-swift-libraries-
xamarin-ios-ff32adbc7c76)

I did have to make some adjustments to the library, so I guess it could be
tricky to use Sharpie Bind with Swift frameworks, if you're not in control of
the Framework yourself.

------
tyingq
There's quite a few places that are still dealing with 4 codebases with
varying degrees of shared code. Desktop, mobile web, native Android, native
iOS.

A shame, since many of them don't really need more than one responsive web
codebase. Native apps do add value for many use cases, but not all.

~~~
jdnenej
They add value in all cases by not needing 200mb memory to run what would be a
20mb app for native. It's crazy how my phone runs perfectly fine on 2gb ram
but my laptop is swapping with 16gb just because slack, vscode and whatever
else election app is running.

~~~
tyingq
I wasn't suggesting electron. Just a responsive website when that's
sufficient.

~~~
tim58
Most websites are resource hogs.

~~~
tyingq
So, 3 codebases or be careful about your website...for cases where a native
app isn't truly needed.

------
iainmerrick
I think in the specific case of C++, this is mostly an Android problem, not a
general cross-platform problem.

C++ works just fine on iOS, and interoperates very well with Obj-C (not sure
about Swift, though).

C++ is a mess on Android. It can certainly be made to work, but the tooling
and library support is minimal.

------
shmerl
Apple also still refuse to support Vulkan natively. They are one of the worst
lock-in offenders today.

~~~
pjmlp
Unreal, Unity, Adobe, Disney, OTOY, Fusion, Cinema4D, ... are pretty fine with
it.

~~~
shmerl
What's fine with wasting effort on pointless duplication? You made this false
claim many times in the past, but it's as false as it was before. And your
support of lock-in practices is strange to begin with.

~~~
pjmlp
Go learn about the industry business practices to start with, an advice you
keep ignoring.

Some people never get tired to fight windmills.

~~~
shmerl
You repeating the same thing won't change the fact that lock-in is a foul
practice that simply taxes developers for the benefit of those who want to
hamper competition. Only shills support such approaches. You perfectly well
know it yourself.

~~~
pjmlp
Somehow it makes you feel good to call me and others that enjoy the
productivity of better tooling shills.

Do you think it matters at all to us with actual experience passing by the
soap box?

~~~
shmerl
Enjoying lock-in - that's a new one. Instead, I enjoy breaking it (for example
by using dxvk).

~~~
pjmlp
What you call lock in, we in the industry call productivity of being able to
use SDKs not stuck in 80's UNIX world, full of endless extensions.

Instead of shouting from a soap box that no one cares to listen to, get
Khronos to actually provide a 21st SDK tooling.

Then Sony, Microsoft, Nintendo (Vulkan is 2nd class on the Switch), Apple,
Hollywood and all their partners might care.

Until then, the wind takes it all.

~~~
shmerl
You know what lock-in is, so no point in pretending you don't understand what
its problems are. It's not about productivity, it's about anti-competitive
jerks who use development tools to hamper competition.

Of course those who push lock-in like to present it as a positive thing and
hide its real nature, but it's just a smokescreen which is easy to see
through. Once in a while, they just can't help it, and express their real
views:
[https://en.wikipedia.org/wiki/Criticism_of_Microsoft#Vendor_...](https://en.wikipedia.org/wiki/Criticism_of_Microsoft#Vendor_lock-
in)

Anyway, I don't think explaining this to you in particular is useful. You know
it all well, but pretend it's a good thing. Which is very shill-like.

Unlike you, even developers of such lock-in stuff admit, it's a bad thing for
the industry. Those who are interested, can find comments by Dan Baker (from
Oxide Games) for example, who is a former developer of DirectX.

~~~
pjmlp
Jerks, shills, ....

Plenty of nice words for someone that advocates APIs that are portable only on
paper, as the best features are all hidden away on OEM specific extensions,
leading to multiple incompatible code paths.

Psst, lets not reveal the Achilles heel from the soap box.

As for Dan Baker, enjoy.

"Benefits of DirectX 12 on Ashes of Singularity"

[https://youtu.be/9cvmDjVYSNk](https://youtu.be/9cvmDjVYSNk)

~~~
shmerl
Whitewashing lock-in is pretty much a shill thing. And pushing it on others is
a jerk one.

As for Dan Baker, he meant low level APIs, not DX12 in particular. He
explicitly said, that MS only API is harmful for developers, and non lock-in
one is needed. Not surprisingly, Ashes of the Singularity is in the process of
getting rid of DX12 for Vulkan. Have fun trying to dismiss it.

~~~
pjmlp
Ah, still being creative with names, I should offer you a name calling
dictionary.

I don't need to dismiss anything, the industry giants haven spoken, multiple
times since the early 80's on graphics API adoption.

Nice way to avoid talking about lock-in in OpenGL, WebGL and Vulkan OEM
private extensions.

As for Dan Baker, you put words on his mouth, while I show him actually
speaking....

~~~
shmerl
_> I don't need to dismiss anything <...> As for Dan Baker, you put words on
his mouth_

Sure, keep pretending it didn't happen. Totally not a shill thing to do ;)

~~~
pjmlp
Still waiting for the proof he actually said that.

Then again, I expect you to just keep on doing the name calling thing.

------
taurath
Over time as well, you cannot keep up with features. You will always be lowest
common denominator, because if a system handles 6 platforms, and you want the
feature of 1 platform on that platform, it will triple or more your amount of
effort to implement it.

------
JamesSwift
_Find and hire candidates with this very specific skillset (we tried to hire
for this role for over a year with no success)_

Really? You weren't able to fill this role? I can almost guarantee that you
could throw an extra 25-50k at someone competent to fill it.

 _In the end we no longer share mobile code via C++ (or any other non-standard
way) and instead write code in the platform native languages._

I've started to comment on this across the interwebs. If you are a cross-
platform (native) mobile developer, and haven't taken a look at Xamarin, you
_need_ to give it some attention. Xamarin.Native specifically is the best
solution I've come across that mostly gets out of your way, and has robust
library ecosystems and sane interop.

~~~
psyclobe
Funny, I applied, 20+ years experience in C++, on mobile too, writing a
competing product.. odd never got a call back ;p

------
babesh
Would like to see an analysis of the costs and benefits of two separate
codebases after they are done with that and have given it time to prove
itself... especially with the more complex code.

------
rkagerer
Write once run anywhere seems to be the eternally elusive holy grail of cross
platform software development. It's a shame AppForge died right before mobile
took off (tongue in cheek).

------
reindeerer
Nah, this is bunk. The cost of code sharing on top of something like Ionic is
next to nothing. And for every platform specific feature you can just plumb in
whatever plugins you want.

------
auggierose
Just look at the code needed to support the file system on iOS 13 to write a
file provider. It changed a lot, and non-native code to adopt to that would be
a nightmare I imagine.

------
zwetan
another code-sharing solution that everyone enjoy to ignore is Adobe AIR

in 2013, AIR was v3.6, now in 2019, AIR is v33.0

not only you share code via ActionScript 3 (something like TypeScript just
available 10+ years ago)

but you can also develop ActionScript Native Extension (ANE) in C, C++,
Objective-C, Java, C#, Swift, etc.

and it does not only publish to mobile it also publish to desktop

but that's OK, keep ignoring it

~~~
trixie_
You are right. I've done a lot of development in AIR myself and it is super
impressive. Easy TypeScript like language. The Flex SDK is mature with all the
standard stylable controls you need. Dedicated IDE that just works great. Easy
deployment. I was able to build a cross platform (iOS/Android/Web/Desktop)
video chat application with it and it looked and worked great everywhere.
Someone dropped the ball somewhere with AIR.. I'm amazed they're still
updating it.. that's something at least.

I guess it lives on here? [https://github.com/apache/royale-
asjs](https://github.com/apache/royale-asjs) Still looks active..

Here's a demo
[https://royale.apache.org/tourdejewel](https://royale.apache.org/tourdejewel)

~~~
seabrookmx
I think it was sullied by the poor reputation of the Flash Player browser
plugin.

I agree that ActionScript was a pretty decent language to work in.

I investigated Haxe briefly but found the community wasn't very big and the
community that did exist was really fragmented.

~~~
zwetan
Indeed ActionScript is a pretty decent language to work with

imagine if you could write command-line tools and server-side apps with it,
that would be the dream

------
wildduck
Unless you need something very specific for the display UI. Try cordova (open
source version of PhoneGap), and stuff like ionic, framework7.io, mithril.js
will mostly get your most apps done needed while still sharing the code via
JavaScript, HTML5/CSS. for anything native you can always write your own
cordova-plugin if it doesn't already exist.

------
stephc_int13
This comment will probably be viewed as preposterous or based on ignorance.

But from my perspective, you're probably doing it wrong.

And based on my experiences with different dropbox clients, I'm not too
surprised, those apps all seem to be very badly built.

Switching language or framework won't help that much, I'm afraid.

------
drabinowitz
I've been considering building a pwa and using a webview as a pseudo native
app I know iOS support isn't great but it seems to be improving and iOS push
notifications could be built separately in the meantime. How's anyone tried
this approach?

~~~
t1amat
While PWA’s largely work, they provide a poor installation experience and
little device integration. Most people use Apache Cordova, PhoneGap, or Ionic
as wrappers to their mobile web app, providing expected installation
experiences through app stores and common device integrations.

------
vpontis
For UI, react-native is really good for sharing code between platforms

~~~
bfrog
If your a sadist maybe

~~~
zwetan
/your/you're/

and I think you meant masochist

------
HN-VIC
Web, IOS and Android should be the same code base.

------
tomovo
Hard to take any of the arguments seriously when looking at the Electron app
they just released on desktop.

~~~
kelnos
I initially had a similar thought, but I don't think that applies here.

With Electron, you don't write a cross-platform base and then write all the
platform-specific goo on top of it. You just write your app using web
technologies, press the build button, and ship it on all the platforms you
want to support.

Since web technologies are popular, you don't end up with the same issues
hiring and training developers like you do when you need to teach a new hire
about your bespoke cross-platform mobile solution.

With Electron, essentially your users pay for all of this by being forced to
adopt a resource-hungry platform, while the development team gets a mostly-
free pass.

~~~
seabrookmx
And while a lot of developer-y types complain, a bit of extra resource usage
on a laptop/desktop isn't nearly as big of deal as it is on mobile.

Especially if your business (like so many nowadays) has way more users on
mobile than it does on the desktop.

------
emsy
This is wild. So Unreal/Unity and others somehow get to run their arguably
vastly more complex engines on mobile desktop and consoles, but sharing some
logic between iOS and Android is too complicated for Dropbox. What are they
smoking?

~~~
ardit33
I see you haven't worked on that level (or maybe you are young)....

First, unreal/unity work at a different level of the hardware, and they have
to deal with different graphic drivers, in the same type of the OS.

But keep in mind that they are not the end product! The end product is the
game that run on them.

So, the cost to building a multiplatform game, is having a whole Game
Framework (which are whole companies), to deal with the lower level details
and help abstracting out the differences of the platforms.

Dropbox is the end product. So, to make the code shareable, they have to build
something like the equivalent of a game engine....

which is not a simple task....

I have worked at Spotify, and we had a lower level library to help (built in
C++) to help out with some of the common features across platforms. It was
ported from the desktop app, to iOS and Android, and it was a separate
project. Over time, as features kept piling in, it turned into a giant un-
manageable mess. It got so bad at some point, that we had to skip a couple of
scheduled releases to clean up/fix some of its issues.

The problem became even worse when Spotify tried to build a unified UI on top
of it (HTML 5 based), with a bridge layer to the C++. The idea was to write
once, and (haha) run it everywhere. It failed, for the reasons many of them
failed in other companies as well (facebook was doing HTML5 at the time as
well).

That got removed, but the problem still remains that "Core" got overly complex
as many platforms had their own features, which often were "one off", A/B
testing, to see if it works or not. And separate teams (iOS, Android, and
Desktop) had their own schedule on this. (It makes perfectly sense to A/B test
one feature in Android, and another one in iOS, to see if people even like
that feature before making is x-ross platform.

Common platform code, massively slowed down A/B testing of new experimental
features, and thus it was a huge cost to the company.

The only solution to this was to keep the common "Core" (as it was called), to
the most minimal features needed, and mostly related to playback (ie. song
retrieval, caching, retrieval, decryption, playback, and some account
features).

Do, the A/B testing on the platform level (iOS, or Android), of it was
successful then roll what made sense to the rest (but still trying to keep
core as lean as possible).

But since I left few years ago, things might have changed again....

~~~
Orphis
I was on that core team and that's not quite what I recall regarding the core
library.

We had some hard requirements on that library because of protocols used by the
backend and other reasons. And when you mention features "mostly related to
playback", well, it was 95% of the library from its conception (the rest being
login and communication with backend). Most of it is quite complex code and
not anything you want to rewrite for each platform (mainly offline storage,
remote control, playback).

The issues we had were caused by growing pain from having the library
initially mixed in the desktop code (back when mobile wasn't a thing). It
needed to be extracted, productified and a whole lot of tooling and testing
written for it. Once we got there, the quality of the code was much nicer and
the integration in the various clients easy and automated (which it couldn't
be at first). It certainly took sometime, but it wasn't a problem caused by it
being cross platform, only that we needed a better infra. We were there when I
left the company about the same time as you for quite a while already.

The integration with various clients got later easier once we removed the need
to reach into that library for just fetching simple server side data. But that
wasn't a cross-platform library issue, it was mainly a backend issue.

