Dropbox Engineer Explains Why the Company Stopped Sharing Code Between iOS and Android And Started Using Native Languages on Each Platform (dropbox.com) 63
Eyal Guthmann, a software engineer at cloud storage service Dropbox, writes: 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. We adopted this C++ strategy back in 2013, when our mobile engineering team was relatively small and needed to support a fast growing mobile roadmap. We needed to find a way to leverage this small team to quickly ship lots of code on both Android and iOS. We have now completely backed off from this strategy in favor of using each platforms' native languages (primarily Swift and Kotlin, which didn't exist when we started out). This decision was due to the (not so) hidden cost associated with code sharing.
Here are some of the things we learned as a company on what it costs to effectively share code. And they all stem from the same basic issue: By writing code in a non-standard fashion, we took on overhead that we would have not had to worry about had we stayed with the widely used platform defaults. This overhead ended up being more expensive than just writing the code twice.
Here are some of the things we learned as a company on what it costs to effectively share code. And they all stem from the same basic issue: By writing code in a non-standard fashion, we took on overhead that we would have not had to worry about had we stayed with the widely used platform defaults. This overhead ended up being more expensive than just writing the code twice.
Language change, not just platform specific coding (Score:3, Interesting)
Re: (Score:2)
No, because now any changes to "common code" need to be implemented twice. Once for each platform.
Re: (Score:2)
Without plugging Qt for example, this is the approach I'd go with instead. if the overhead of cross platform code is too large, then there's a market for a product that provides that functionality. All the platform vendors are deliberately going their own way and hiding behind various self-serving principles to justify their desire not to support cross platform languages, but at the end of the day, that's not good for anyone but them.
Possibly DropBox has figured out a revenue model that justifies hiring to
Re: (Score:1)
The article implied C++ was the only language that had cross-compilers available for the two platforms, at least when they started. I'm not sure how a different language would solve the problems listed anyhow.
Re: (Score:3)
Re: (Score:2)
Perhaps the article implied that, but it's clearly wrong. I believe that C, Fortran, and Ada had cross-compilers, and I'm rather certain that Forth either had cross-compilers, or could easily have had them added. Perhaps he meant that they chose C++ as the best language for the purpose that had cross-compilers available.
Re: (Score:1)
"My phone app is written in Fortran!" didn't work at the last party.
Good article (Score:5, Insightful)
The kind of things that a codebase shared across platforms helps with is not the tricky stuff, but the simple stuff that is easy to just write as appropriate for each platform.
Over decades of programming I've found the real enemy of stable and good code is complexity. The truth is that writing the code as simply as you can for two platforms is always going to be less complex (In many respects) than writing code that is shared but has to adapt for the needs to many platforms...
Also the thing I didn't see mentioned is that invariably sharing code across platforms means slower to adopt new features for each platform, or sometimes never adopting really useful platform features because it would be too hard to add to the shared codebase.
So glad this article exists that I can point to when someone considers sharing code across platforms...
Re:Good article (Score:5, Insightful)
Mod the parent up!
Well said indeed!
This has been a major disappointment that I keep seeing happening everywhere: simple code evolves into complex code for no good reason, other than new developers wanting to do things the only way they learned or know. Whether it is making procedural code object oriented for no good reason, adding components that will not be often used, or many other reasons.
The end result is that the code base becomes more complex, and less stable, less maintainable, and less secure.
Technical debt ...
Re: (Score:2)
Using a "common" layer makes things more complex. If you encounter a bug, it could be in the common layer or in the native code. It makes debugging a PITA
At least when you write native code you know that the SDK you work with is supported by the manufacturer of the device and that it will be well maintained. Not so with all kinds of javascripty/Csharpy/darty mobile solutions that are often 3rd party. They also tend to lag behind the latest versions of the native platform.
So the received de
Re: (Score:2)
I think it greatly depends on the type of application. I write games (for PCs currently, but will eventually port engine to mobile), and my game engine and game code vastly overweighs any platform-specific interfaces I need. Something like a videogame interfaces with native systems in a fairly narrow and specific manner (video, audio, input, filesystem). My rough guess is that about 95% of my engine code is modern, platform-neutral C++, and virtually 100% of game code is cross-platform. It would absolut
the world according to house elves (Score:3)
Did you ever stop to ask yourself where all that "tricky stuff" comes from?
Likely answer: badly engineered APIs that export platform complexity to the application codebase in ways they really shouldn't be doing.
Second root cause: this is almost always because our APIs are excessively procedural and insufficiently declarative. In a dec
Re: (Score:2)
Over decades of programming I've found the real enemy of stable and good code is complexity. The truth is that writing the code as simply as you can for two platforms is always going to be less complex (In many respects) than writing code that is shared but has to adapt for the needs to many platforms...
The good thing about common code: It behaves the same.
The bad thing about common code: It behaves the same.
I've dealt with a lot of bugs where the programmer didn't use the common functionality, they simply copy-pasted or hard coded. Like you got 100 reports, 95 use the correct header/footer template and 5 simply copy-pasted from another report. Looks right until somebody modifies the template and suddenly those 5 reports are off but unless you manually go in and see okay report 1 looks good, report 2 looks
Re: (Score:2)
It depends on the platform too. iOS and Android both have a rich set of libraries that cover a lot of functionality. There really is little benefit to trying to commonize code between them, since most of what you are doing is putting a UI on top of a specific configuration of library functionality. If you try to commonize there, most of your effort ends up being spent on duplicating functionality already available in the platform libraries just so you can have a common implementation. For more bare bones
Re: (Score:1)
Great design and smart people to work on both products at the very start of the project.
Cant pay the 2X expert wages? Make a great Windows product.
Re: Good article (Score:2)
Re: (Score:2)
OK, take a look at the codebase of MAME [github.com]. It's fully cross-platform with only a small platform-dependent layer. Are you seriously going to try and tell me that the the millions of lines of cross-platform emulation code is the simple stuff, and it should be re-written for each platform? What planet do you come from?
Re: (Score:2)
Probably both ways it does just because it shakes things up and cuts a significant amount of legacy rubbish out. It also has an expense
"... but, but, reusability, but , but..." (Score:3)
Many of the old precepts we were taught about programming ... may turn out to be shit in today's world. Ideas that made sense 25 years ago might be laughable today.
Solve Once, Implement Twice (Score:2, Interesting)
The real challenge of programming is problem solving, not writing the code. You can take a working code base and give it to another developer and they'll have very little trouble translating it into another language or platform as long as the original code isn't a mess. But even then, they'll figure out how to untangle it and then they can pass their solution back to the original team so they can see how to untangle their own code.
Re:Solve Once, Implement Twice (Score:4, Insightful)
If only that were true.
What's more likely to happen is that the developer will copy the code, which is the worst possible thing you could do.
Better just explain what the code does and let the developer rewrite it from scratch.
Re: (Score:2)
When you do that, you run the risk of re-implementing Objective-C features in Java or vice-versa rather than using native features.
No, the code should be for reference only. Give the developer the complete set of requirements that "contain everything you need to know to write software that is acceptable to the customer...if a product satisfies every state [tufts.edu]
Re: (Score:2)
I have never in my life seen such a spec written for anything in technology. I do not expect I ever will.
Re: (Score:2)
I have never in my life seen such a spec written for anything in technology. I do not expect I ever will.
I had 2 days to write a spec partway through a project - 130 pages, nicely indexed, with example code for the tricky stuff. Turns out it was "too complicated" for them to understand - though the project itself was complicated.
I told them that until they can pass a test proving they read it, I'll never write another one.
"We wanted to see if you understand it," Of course I did, I spent a couple of years fixing it after several teams got bogged down and polished their resumes rather than admitting they coul
Re: (Score:2)
they'll have very little trouble translating it into another language or platform
No, they'll have quite a bit of trouble.
But that doesn't mean it wouldn't be the right decision. When you do cost-benefit analysis, both costs and benefits have to be counted.
Re: (Score:2)
The real challenge of programming is problem solving, not writing the code. You can take a working code base and give it to another developer and they'll have very little trouble translating it into another language or platform as long as the original code isn't a mess. But even then, they'll figure out how to untangle it and then they can pass their solution back to the original team so they can see how to untangle their own code.
Verifying that it is the same, functionally, as the original is non-trivial. Test cases help but it's more the case that a case that fails means it is not the same more than something passing all the test cases means it is the same. Formal proofs of congruence across two different languages aren't really available. And this is before new features are added to each new code base.
Re: (Score:1)
The GUI work great, look great?
Expected speed on the OS/GUI the same?
People on each OS expect GUI perfection as thats what they are paying for.
Hire two teams after the problem solving part? Version drift between the OS?
Comment removed (Score:5, Insightful)
Re: (Score:2)
Essentially they switched to the "official language" so that they could sit a code monkey at a desk with an Android/iOS IDE and have them glue together frameworks instead of having real developers who understand how software is built and interacts with the system analyze the problems and develop solutions.
A common practice in the app/web world. No wonder they have retention problems.
Re: (Score:2)
Using a particular kind of life cycle management doesn't mean someone is "not good at C++". It is a strength and a weakness of C++ that it gives programmers so many options, and programmers have to be conscious of the trade-off of using one or the other or using both with the added complexity that that implies.
Someone who thinks there's exactly one way to do *anything* in C++ has missed the point.
Re: (Score:1)
Re: (Score:3, Interesting)
If you don't need to communicate with Javascript (i.e. web browsers), then JSON is completely the wrong tool, and adds many more problems than it fixes. No wonder they were having a tough time, they were trying to use untyped data or weakly typed data in a strongly typed language.
What do you propose? Dumping C++ structures straight from memory to disk or a socket?
If so, Good luck ever changing anything, even your compiler flags. (Not to mention that using unsanitized data a security nightmare waiting to happen.)
If not, you have to parse the incoming data somehow (even if it's some kind of binary format). If you have to do any parsing at all, then you might as well use a JSON library, because it's mature, universally supported, and simple.
Re: (Score:1)
Re: (Score:2)
It's also stupid when you have a website that already uses a well-tested REST api that communicates using JSON.
Re: (Score:1)
The main problem was that they did not build a clean seam between C++ and platform-specific layers, but decided to use djinni that would automagically connect the two worlds.
We tried djinni in a smaller project, and our team faced many problems with this framework – not because it did not deliver on its promises, but because it turned our execution flow into a callback chaos, and debugging into nightmare.
Eyal writes about the same experiences, but attributes them to the hybrid C++/(Java and Obj-C) nat
Re: (Score:2)
they actually spent time on non-nullable pointers instead of just using the C++ standard shared pointers and unique pointers. They were writing and using JSON in a capacity where they did not need to talk to anything Javascript related
Where are you getting all of this? This wasn't in the article.
Re: (Score:2)
He pulled it out of his ass, obviously. Dropbox has had a website far longer than it has had mobile clients. The website almost certainly uses a REST api (or some such) which communicates using JSON. It's a well-tested API that would be foolish to duplicate in binary format, having to write new parsers on both ends and keeping them up-to-date with the JSON format over time.
Re: (Score:3)
In short, you didn't read the entire article and you don't understand mobile platforms (particularly iOS and Android). An app such as Dropbox has the vast majority of its code interfacing with the system. The systems are very different, and writing common code to present an abstraction just means maintaining two concrete implementations in a language that each platform has to jump through hoops to interface with. It's not worth the effort because you spend more time debugging than you do writing. You lo
Re: (Score:1)
Re: (Score:2)
About JSON: Dropbox has a website. Quite likely it uses a REST api that communicates using JSON. It would make little sense to provide a separate API for the use of mobile clients, but would make a lot of sense to reuse the existing API. You sound like an utter moron, and I hope I never have to interact with any software you had a hand in.
Hire experts for each platform you develop (Score:2)
And let them use the language and tools they consider the best for their platform. You will have productive, and most importantly, happy developers.
Re: (Score:1)
Who know that the "OS" brand will never allow that amount of CPU to be accessed by an app.
The GPU limitations.
What the users expect from a GUI they use everyday as set by the OS brand.
Who are ready for OS changes. Hardware changes.
Who can keep each OS app working as it should.
Who can get the best out of power saving limits on CPU/GPU so the GUI stays responsive on that OS.
That needs really great code an
Cross platform framework makes sense in some cases (Score:1)
non-standard (Score:3)
"By writing code in a non-standard fashion, we took on overhead that we would have not had to worry about had we stayed with the widely used platform defaults"
What? Why did you write code in a "non-standard" fashion? I think the problem is that they are morons that depend on "frameworks" for everything.
Re: (Score:2)
I found that part odd - I don't doubt that it means some additional complexity but there's no reason for any of it to be non-standard. Especially since there's enough standards that you can pick the one you like.
Re: (Score:2)
What is the standard way to run code concurrently on iOS? How about Android? What are the preferred mechanisms for network communication? How do you handle background processing when your app isn't active?
There's very little that's common between iOS and Android at the system level. If you try to commonize, you are fighting both platforms.
Buzzword Feedback Loop (Score:1)
So the org has to use whatever is "in" because everybody is chasing "in".
Yet Video Game companies do this successfully (Score:5, Insightful)
Why did DropBox have so much trouble making a cross-platform C++ mobile application while video game studios makes cross-platform C++ video games so easily? The article is light on details, but I can make some guesses:
1. Their mobile developers refused to learn C++. This sounds like a culture gap: they hired people who wanted to make a phone app because that's all the rage, but they weren't real coders. This is similar to the late 1990s when companies hired "web developers" who knew only HTML or the dreaded Visual Basic developers who had no grasp of computer science. Going even further back, it was the FoxPro and dBase developers.
2. Dropbox designed their application inside-out. They wrote a C++ application with callbacks into Java/Swift, instead of a Java/Swift application with callbacks into C++. C++ is the lowest-common-denominator language and anything can call into it. But it is often difficult to call from C++ into other languages. Those languages expect all the callers to be using their runtime.
3. Apple and Google intentionally made their platforms with lock-in in mind. Most major OSs are natively written in C and C++ so that any language can call into the OS. That is generally a feature. But Android's APIs are natively Java, so writing in anything lower-level than Java is a problem. They *want* it to be hard to port code to their platforms.
4. Video games often have limited integration with the OS -- once you create a graphical window and open a network socket, the rest can be handled by your native code. But a mobile application might need to integrate with the "sharing" features of the OS, or the background service capabilities of the OS, or the bluetooth features.
Overall, this article would not dissuade me from sharing code between OSs. But it is a cautionary tale about making sure the architecture is right, that you are sharing the right code, and that you don't hire computer pseudo-scientists who quit as soon as they have to write actual code.
Re:Yet Video Game companies do this successfully (Score:4, Interesting)
Not quite true.
Android uses Java because at the time, Java was a popular language for mobile phones. That's why there was J2ME profile. Of course, there weren't many mobile phone apps back then as carriers ruled the roost and made it hard to bring an app to a phone, plus each JVM was quirky with each phone so "write once run anywhere" was more of a joke when it came to phones. And the NDK was not available when Android came out, showing this heritage. They only added the NDK because the Dalvik JVM at that time was crap and did nothing but make things slower. The NDK uses standard JNI hooks so any competent Java coder could get settled in with Android development and NDK development easily.
Apple used Objective C for iOS because their main OS (MacOS at the time) was developed in Obj-C, so all their frameworks and base OS came that way. Obj-C has direct C support - you can compile C code using an Obj-C compiler directly. So Apple went this route when they added app support. A competent Mac programmer could easily create iOS apps using the new UI toolkit, and like on the desktop, if they needed native code they just added it in directly inline or as a separate file to be linked in.
Of course, that was then, now we have Swift and Kotlin, which change the game from compatibility to lock in.
And the real reason is twofold - first, the amount of "core code" is probably shrinking - how much code does it take to access a cloud storage service nowadays? You could create a socket and handle the HTTPS connection yourself in core code, but that doesn't make much sense anymore since both OSes offer the same functionality in a library that's easy to call and use. The OS specific bits are OS specific and can never be shared. At some point it just makes sense to make it all native because the OS interfacing code is taking it all over.
Second, well, iOS and Android developers are a dime a dozen. Just using native code for it all means you can easily hire cheap programmers for this job and leave the former app programmers working on the server end.
Re: (Score:1)
Re: (Score:2)
I don't doubt that you're right, but the choice of target developer community seems odd to me. Smartphones have more in common with PDAs than feature phones, and while you could develop for PocketPC with Java (CDC/PP, not the ultra-limited CLDC/MIDP of feature phones), there wasn't a built-in JVM. I think most devs used C++.
Re: (Score:1)
Re: (Score:2)
Calling from C++ into Java is not difficult at all!
Loading the JVM from the C++ side is actually the preferred way. Obviously that does not indicate who us calling whom.
Set up for outsourcing (Score:2)
By going back to standard toolkits, you don't have to depend on as much 'institutional' knowledge, and can outsource lots of coding, saving money (ha ha).
Re: (Score:1)
The GUI will look ok again after some testing
With todays fast CPU and GPU the GUI will be responsive.
The hi res art work will always just fit in.
A notch... ?
Lens hole is where now?
Re: (Score:2)
If the software is once written and working, rewriting/porting it, is relatively easy.
Re: (Score:2)
Re: (Score:1)
It's pretty much always been this way (Score:1)
This is 100% in my confirmation bias zone :-)
Example: We've been using React Native. It got us going really quickly and initially had a lot of advantages. It's good, as far as these things go. But I see a lot of effort going into nursemaiding the UI through stuff implemented by the UI framework in iOS which also obeys a hundred different UI settings of which the React code is entirely unaware and unresponsive. Larger or smaller text sizes, the 'bold' setting, reduced transparency, reduced animation mode
Easy solution (Score:2)
Easy solution: just drop Apple. Only a sliver of the market anyway, not worth the bother.