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.
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.
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.
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.
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.
The Xamarin folks are native platform engineers first. Xamarin teams comprise Android experts and iOS experts who did then went on to learn Xamarin on top.
Given advances in mobile platform and Native SDK a company like Google, Microsoft or Facebook will not be able to keep up with native SDK and will be one or two generations behind. You can see the result in issues on flutter project. Also given Swift has Python like syntax and ease of use with powerful toolchain and Kotlin with nice syntax with functional programming efforts are not that different working with native SDK.
Obviously this cross platform mobile framework are ok for simple crud apps. But when it comes to building a mobile app using modern vision, audio, keyboard, touch and gesture input along with modern sensors in the platform and provide a consistent UX is a big challenge. Also UI and UX have enough subtle differences across iOS and Android the code written to manage them is also substantial. So its nice to go native SDK route for mobile apps.
I'd be happy to hear if the project you worked on has been cost-effective to maintain in the long term. Then at least someone has seen the mountain top!
You can directly access native apis within your js/ts code. And they provide good cross platform defaults for widgets.
so basically you can either have one application on top of a custom ui framework (xamarin.forms) or you can only share business logic, and write controllers, which feels native in c# or the native language.
i.e. without forms you can build a controller with objc or you can have the implementation in c#, and call into a shared business logic library.
unfortunatly the docs are really really weak when you consider what you really can do with xamarin.
with forms you can build a ui that works on both platforms so basically you have 100% shared code.
The reasons for regretting it were similar: lack of available engineers on the market, incompatibilities between runtimes, and lagging support for platform features (although in the Xamarin case it's not even in your hands to fix it)
- The entire organization uses a single framework (and improves on it), which will lead to a bunch of teams grumbling that "We are only using X because of organizational pressure, while Y is much better"
- You leave freedom to the org to pick their technology, and hope/steer people towards certain parts. But you will have to accept some divergence from the norm
I prefer the second org, and luckily I am in such a place where we can use Go while the team next to us is on Scala, and we weigh in-house developed technology against publicly available technology on ROI.
Other article talking about it:
Xamarin for .NET devs, React Native for C++ devs (a bit like QML/Qt).
Office naturally fits the C++ devs way.
But the Office team is also a right tool for each job group and has both Xamarin and React Native apps and telling the difference between them is getting tougher to do. You can already integrate React Native components inside a Xamarin app and vice versa because they each can look like native components to each other, and it's not entirely an either/or decision.
And the same problem with using C++, you have to build the app around it, rather than using the best arch for android and ios.
I implemented targets for JS, php and C++. It worked okayish but in the end it was more work to maintain the separate language than just write everything 3 times with some help of a simple macro/template language. I still sometimes wonder if the concept would be developed further, with a proper team and good tooling etc, if it would be a practical way of doing large scale cross platform software development.
If I understand you correctly, this feature is available in Haxe : https://haxe.org/manual/target-syntax.html
It targets js, php, C++, has a proper team and good tooling.. so you might be interested in giving it a try.
But this is different, if you write things simply, so the code can be ported easily. Then you're essentially making the code easier to share, without tightly coupling it to a specific platform... seems like a big win to me
This also has the benefits of:
- Being easier to on-board new developers, as the architecture is generally language agnostic.
- Easier to add new OS clients, as the system is easily portable
- Harder to incorporate language specific dependencies, as they are much harder to find in multiple languages.
- Code duplication...
Always important to weigh up the trade-off's
I think that kills a lot of interesting projects right there. If I could write a solid spec, that would mean I believe I wouldn't learn much from shipping the product. And also that my competitors aren't learning or advancing.
As long as you don’t blurt a lazy “use the source Luke” and take the effort to document and edit the spec during or right after implementing something, it’s ok.
What's the point of writing the spec after? At best, it's duplicative. At worst, it diverges, making it incorrect.
One just has to have an idea where to go before starting, and a good description where one went when you’re done.
A good requirements spec doesn’t mean it has to be heavyweight with all the corners and edges figured out. Instead, it can be just lightweight enough to get things moving in the proper direction... but some little direction is certainly needed.
In theory the shared code approach means platforms could be tested in parallel.
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.
Maybe my own viewpoint is twisting the amount of devs I think are available, but I don't think the choice dropbox originally made was crazy. C++ is a great way to share complex code over multiple platforms (i.e. desktop + mobile) if you're running a relatively small engineering team with limited resources.
Now, if you have semi unlimited resources, it makes sense to rebuild things natively for each platform in many cases. But Dropbox might not have been around, had they not maken the choice to share part of their codebase cross platforms.
Do you also keep ViewModels or things like an AuthManager (incl Keychain) or view coordinators in Rust?
I have code that contains useful parts that are worth publishing, but it also contains horrorshow code and library/tooling specific dependencies that are useless to anyone else.
I don't want to make the code useful for others, but I would remove comments/keys/PI, and parts of the code would remain useful to others to copy or use as a reference for how to do something.
The main issue is avoiding getting roasted by some random dev blogger for some of the technical debt (the embarrassing code you remove or fix if publishing properly). Maybe a click-through agreement before you can read the code?
Under the hood, Android is very much a Linux-looking system and iOS is very much a Darwin/OSX-looking system, so as long as you avoid moving too far into the UI layers, they'll behave exactly as you expect.
BTW I'm pretty sure I simply just misunderstood their platform support page. https://forge.rust-lang.org/platform-support.html
I did run into a bug with the rand crate running out of randomness on Android, but that's a different story. :)
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.
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.
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.
Sometimes, it's OK to write the same thing twice if the alternative is a major refactor - such as inventing your own stack.
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
Thanks, I'll use that from now on. A lot of wisdom in those 4 words.
1. There is actually a need to use this code in multiple places
2. You know where the places that need this code actually are, and what they need, so what you write will actually be practical for all of them to use
3. Or maybe you can tell that, despite the seeming similarity, the different places are too far apart or too different for sharing code to actually make sense
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.
Reading the article and now this, I really can't grok this perception. There are plenty of us out here, I think, it's just we're buried in the heap caused by mass resume farming, aka modern recruiting. Recruiters and hiring managers don't think of me as a senior dev with 15 years writing software and delivering value to end-users... I'm just YA candidate who doesn't have any experience in the latest JS framework du jour, so I might as well not exist.
As for finding people like yourself, all I kept hearing was that they had trouble finding new people to fit their specific needs.
I agree with you though, there is likely a lot of missed opportunities due to the resume farming going on and bad filters.
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).
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...
Unfortunately, once you get into users wanting OS specific feature support, all that goes out the window.
You now are forced to maintain multiple versions of your product that differ greatly per operating system.
Pair that with the fact the codebase was almost 20 years old, you get some fun legacy code support issues that a lot of C++ projects naturally have due to the fact that C++ is not a new language.
However, in our case (like with many C++ code bases) the code was almost 20 years old. Even with the Herculean efforts made by the teams to keep the code base up to date and refactored, you run into issues of backwards compatibility with older libraries.
C++17 is definitely the go to for new projects! However, I've never personally worked on a pure green field project written in C++ that didn't have to latch onto some older libraries that require older C++ std versions.
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.
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).
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.
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.
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.
- 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.
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.
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.
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.
Nothing in this industry lasts forever. I'd certainly rather inherit a Java/Swing or Qt app from the early '00s than an MFC or Carbon dinosaur.
Oof. Yeah MFC was something else.
I hated Swing the bit that I worked with it.. but I'm always blown away when I see the Jetbrains IDE's in the wild (I'm a VS Code guy but a few people I work with prefer the Jetbrains stuff). They managed to make a really slick, and pretty performant (if you ignore startup time) app with it.
I guess you could say VS Code is a similar exception to the rule in Electron land.
Furthermore, it looks like their team changed a lot and they were unable to retain the C++ talent that implemented the original strategy, nor were they able to find interested developers.
The mobile landscape has also changed enormously during those 5 years, even the official programming languages have changed.
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.
C++, plenty of jobs outside mobile dev, and a very nice pay to come along.
Flutter - Dart, death silence outside Flutter use cases.
In my experience, while Flutter may not be elegant because of Dart, it more or less just works.
Developing in React Native is mostly just debugging the framework itself and browsing through React Native Github issues.
It's evolving pretty quickly, too. Non-nullable by default is coming up, along with extension methods, FFI. Possibly implicit conversions.
I've been working with Flutter/Dart for the past 8 months or so, and I have to say...I'm pretty into it.
Non-nullable by default will be a huge win. It does feel like a huge step backwards having to deal with nulls again.
I don't know what you are trying to build on mobile but I'd definitely learn Flutter instead of RN, which I have. Others here have said you should just go full native instead, and they're probably right.
Isn't that an oxymoron?
If the user interface is usable and snappy, it is probably fine that it consumes twice as many resources as a similar native app would require for the same result.
Example: Slack.app is a huge memory hog (though not as bad as it was before their rewrite), but it fits decently into OS X and does not lag on me.
I have lots of RAM, so the extra consumption is fine.
Sure, it annoys some programmers that it could be more efficient, but other than them, who cares? Those guys are probably using Emacs or a CLI program as their client anyway.
(I must be a rare breed, since I do email, writing, and programming in Emacs, but not chat)
I switched from Sublime to VS Code and went from 20MB of RAM usage to 500. Add slack, add discord, you now have GBs of RAM getting eaten up just for the UIs. Most mid-range laptops still only have 8GB of RAM, add a browser to the mix and it's a constant battle to have everything running smoothly, the programs frequently crash due to memory issues.
It's a real problem and not solely programmer efficiency-OCD.
My laptop has 8 gigs of RAM, and I run many programs simultaneously (usually including several codebase analysis servers behind Emacs, a VirtualBox VM or two, Slack, and of course tens of Chrome tabs, several in development mode), but I don't have anything like the problems you describe. I do use The Great Suspender aggressively in Chrome and that does help a lot.
My Emacs instance itself is extremely tricked out with extensions and usually weighs in between 100 and 200 MB of RAM. Maybe that's the difference - sounds like VS Code eats a lot more.
I'm on a MacBook Pro from 2015 at work, if memory serves.
What setup are you running that handles your needs so poorly?
No wonder I don't have issues.
I hope tab suspension helps you. It certainly made Chrome more usable for me (but I do have a bad habit of getting to fifty or seventy tabs open).
Even worse it's using significant amounts of video card memory, and I have a tenth as much of that.
And then the IDE of another guy does its indexing really fast zillions of times per second, great, but then another guy sits there waiting for "git status" to complete for several minutes.
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.
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?
> 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.
The platform developers will do their best to keep 1st tier tooling working and fix it when it breaks.
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.
"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++.
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++
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.
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.
- 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.
- 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.
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) that are problematic in my eyes:
- react-native-swiper. Completely custom JS implementation with a "iOS"y look. 8k stars
- react-native-gifted-chat. Large completely custom JS implementation of chat UI. 8k stars
- react-native-slider: 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.
> - 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.
> - 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.
I have working examples of fairly complex production applications that are <=10 MB on 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.
False statement. React Native provides you with ability to tag elements so you can use accessibility-tools to navigate the app. I have recently tested this with a RN app running on iOS 13 using the new voice control feature. Several testing frameworks also rely on these features being available.
Fair, the problem isn't as bad for RN, for Flutter it's still very bad though.
> False statement. React Native provides you with ability to tag elements so you can use accessibility-tools to navigate the app. I have recently tested this with a RN app running on iOS 13 using the new voice control feature. Several testing frameworks also rely on these features being available.
The ability to tag elements is only a very simple basic requirment to get accessibility right. My point was more that if you use UIKit you get significant levels of accessibility for free.
Just as a quick example I did a quick ddg search for "react native how to create custom button" and all 5-7 top results that I looked at failed to set the appropriate accessibility roles so the button actually appears as button to a user with the screen reader. Yes you can still do accessibility right with RN, but it's not the easy to get it right be default and most app developers will not do this on their own.
Appreciate that you looked into it. On iOS and you do not need to set anything to become screen reader friendly _in React Native_. The default TouchableOpacity with a simple piece of text inside of it will become focusable and iOS will read the text aloud for you. This works because RN uses native elements unlike Flutter, Electron, and others.
In fact, I took you up on the claim that it wouldn't read correctly. I used my app just now which has never been tested or optimized for accessibility. Covered my eyes and began navigating. It works just fine! All tappable elements are indeed read aloud. I was able to navigate through the app settings, change them, go back, and reload other screens, navigate to the updated content, and perform actions on the new content.
Please do not put RN in the same bucket as Flutter or Electron. They are fundamentally differently.
That said, myself I still write Flutter too, having jumped ship from React Native.
But yes, there can be differences, but that doesn't mean give up and write the application code 6x.
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.
Wouldn't it be dramatically simpler to just build the app twice?
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)
(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
1. People may be more willing to learn Rust. I much prefer the language itself, but also it's clearly on the rise, so it may feel like a better learning investment.
2. The standard library is broader and the package ecosystem is easier to work with, so you might be able to have a more standard stack with fewer proprietary bits.
3. One complication with integrating multiple languages is making different memory management strategies coexist. Rust's type system seems to have ways of making that easier, e.g. neon-bindings.com
Rust is built for memory and thread safety. Also the much better build system and open source ecosystem.
That's debatable ;)
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.
I can't see how duplicating code in Swift/Kotlin would be any better than just writing it once in Dart. Dart is also quite a nice language to work in. Easy to get up to speed and a nice mix of static/dynamic typing. The optional Provider api make state management a breeze, no more Stateful widgets.
I've also switched from REST to GraphQL. I was a long time hold out there, but now I really see the advantages.
Anyway, just throwing this out there as another data point.
I like dart lang and done some small apps in it. It's Javaesque with similar style and learning curve. But still prefer Swift which is closer to python (we use python for back-end development) and Kotlin which has some nice functional programming primitives.
Also UX and guidelines are not uniform across mobile platforms. Android and iOS works in their own way to integrate different input like voice, visual and keyboard. Also mobile platforms on Android and iPhone are constantly evolving with new sensors, capabilities. Keeping native SDK itself is a gigantic task not sure how to manage cross platform SDK's. I am sure cross platform SDK can work for some use cases, but I feel it will still be way behind native SDK.
If back-end can take care of all the business logic and front-end manages UI and states with small necessary local data for offline, the efforts spend to develop cross platform app using flutter or natively in Swift and Kotlin won't be very different.
I still prefer REST over GraphQL because I like predictable performance in query and standard interface. Zen of Python PEP-20, explicit is better than implicit.
GraphQL is a solution to a problem of trying to manage business logic on client side so that it can manage ad-hoc query and get ad-hoc results from back-end. It was designed for a problem faced by Facebook. I have seen enough GraphQL code and still stay with REST Architecture, sometimes use protocol buffers for performance intensive parts.
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.
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.
I haven't tried Ionic myself, but I have tried both React Native and Flutter for a small project and found Flutter to be more enjoyable and productive.
So if you compare ionic vs flutter I will still go with flutter given it generate binary app store package file by compiling dart code into native platform code. But given choice between native vs flutter I think except few use cases native still makes more sense.
So I'm also interested in hearing more elaboration on how Flutter has been a struggle for you.
If I use swift I get all the code examples and tons of documentation from Apple itself. In flutter I need to rely on some package which might not be supported, if my team takes over it's double the job fix the package bugs and also change the resulting changed in code, compile and test individually on iOS and Android.
Another one https://pub.dev/packages/sensors#-changelog-tab-
And there are many such issues.
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.
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.
Or had a .net runtime that ran on both.
Regardless, you need a C# developer if you're choosing Xamarin as your tooling.
Xamarin is both yes, though it really integrates into Visual Studio so its more of a tool? I am not sure, definitions like that are a bit murky.
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 ...
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?
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.
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.
However, in the mobile world, from my experience, hiring good senior mobile engineers means they come with a specific skillsets already. They can take a view, animate it a certain way, and then respond to touches. Those are things that are entirely platform specific domains. So they will come from Swift/Kotlin or ObjC/Java backgrounds. The ultimate problem here is those same engineers are typically turned off by C++ nor have the desire to learn it.
You can throw C++ engineers at the problem, but they will most likely be turned off by having to solve animation timing issues or custom navigation stack designs.
If you have a venn diagram of the two sets, there would probably be very little overlap.
There are plenty of C++ devs out there (myself among them) that will jump ship for the right offer.
It's not just familiarity with the language, it's being willing and able to develop within the mobile development context, which as stated in the article is a whole other beast
Google and Apple keep piling feature on top, so mobile has the 2nd biggest churn after front-end. Recently even the preferred programming language changed on both platforms.
It's under pressure from web-applications, which although of inferior quality are easier to develop.
Most apps aren't anything special and require mostly UI and UI framework skills (animations, platform-specific APIs, etc).
I find the '14 and '17 additions vastly improve C++ and in fact added things that I had just come to appreciate in Swift. So don't be too put off; learning the new stuff will help you if you need to adopt a more-recent language too.
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...
Compilation was incredibly slow. Maybe when C++ modules finally arrive things will improve.
The biggest winner, in my experience, was reducing dependencies in headers. Use forword declarations, etc. Precompiled headers helped a lot on Windows, but less so on Linux for the same code (but it still helped).
Incremental builds were fairly snappy, a minute or two (pretty good for a large C++ project).
I like the language, but the compiler is painful.
I actually like the language but stopped using it because it was so slow to compile. I hear that it has gotten better so I’ve been revisiting it.
Worksheets seem to help with development.
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.
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.
I would say things are not so bad when you pick your tools right.
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.
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?
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.
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.
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.
It's a different story if you want to use native features. Plugins provided by community offer only basic functionality, and are often very buggy: you will encounter iOS bugs, Android bugs, Flutter bugs and plugin bugs, all in one package. Anyway, it sort of works if you plugins provide stuff that you need. If they don't, you are forced to fork the plugin and add ad those features, learning Android or iOS during the process, and writing a lot of boilerplate for communication.
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++.
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.
 - https://www.youtube.com/watch?v=ZcBtF-JWJhM