> 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 ...