宁愿写两遍代码,也不用C++跨iOS、Android平台开发?

2019 年 8 月 19 日

宁愿写两遍代码,也不用C++跨iOS、Android平台开发?


Dropbox 最近宣布将放弃用 C++ 编写跨 iOS、Android 平台代码,转而使用各平台的原生框架(Swift/Kotlin),理由是代码共享相关的隐藏成本太高。有趣的是,2014 年,Dropbox 在给 Facebook 的开发人员做分享时,却曾直言写两套代码会带来种种弊端,推荐使用 C++ 进行跨平台开发。为什么几年前的经验之谈却成了几年后的技术债?C++ 因何躺枪?跨平台开发前景如何?本文试图一一为你讲解。


事件综述


编写一次,随处运行。这句话不知道被多少工具和框架写在开篇介绍中,用以吸引更多公司和开发者。然而,作为这一策略忠实的实践者,Dropbox 近日宣布放弃这一想法,宁愿为不同的平台写两遍代码,也不用 C++ 跨 iOS、Android 两大平台共享代码的方式进行开发。


早在 2013 年,Dropbox 就采用上述策略进行移动开发,这背后的想法很简单:用 C++ 编写一次代码,而不是用 JavaObjective-C 编写两次。那时,整个移动工程团队相对还比较小,但需要支持快速增长的移动路线图。因此,公司希望找到一种方法,使这个小团队可以快速交付大量 Android 和 iOS 代码。


如今,Dropbox 完全放弃了这个策略,转而使用各个平台的原生语言(主要是 SwiftKotlin,这两种语言在刚开始制定移动策略时还不存在)。这个决定的主要原因是代码共享相关的隐藏成本太高,这源于同一个基本问题:


以非标准的方式编写代码,使 Dropbox 承担了一些开销,而如果采用广泛使用的平台默认选项,就不必担心这些开销,这种开销最终比只编写两次代码要昂贵得多。


C++ 的问题?


随后,Dropbox 总结了成本太过高昂的主要原因,比如自定义框架和库的开销、自定义开发环境的开销、处理不同平台差异的开销以及培训、招聘和留住开发人员的开销,这与 C++ 本身存在的问题密切相关。但是,C/C++ 是唯一一种编译器同时受到谷歌和苹果支持的语言,如果使用其他语言将会产生一系列更麻烦的问题。


1、自定义框架和库的开销


关于使用 C++,最容易出现的开销就是构建框架和库,这大致可以分为两类:


框架,让开发者与主机环境交互,构建一个功能齐全的移动应用程序。例如 Djinni 、用于在后台和主线程中运行任务的框架等。


一些取代本可以在平台原生语言中使用的默认语言或开源标准的库。例如:用于 JSON(反)序列化的 json11 ;C++ 非可空指针 nn 。


如果使用平台原生语言,那么这些代码都是不必要的。当然,并不排除个别开发者可以很好地利用开源 C++ 库,但是 C++ 开发社区中的开源文化并不像移动开发社区那么强大(特别是几乎不存在的 C++ 移动社区)。这些成本在 C++ 中特别高(与 Python 或 C# 等其他可能的非原生语言相比),因为它缺少一个功能齐全的标准库。


虽然 C++ 标准委员会为了这门语言做了大量工作,甚至为了 C++20 的新特性举办了一场历史上规模最大的会议(180 人参会),试图通过会议确定哪些特性可以加入新版本,比如 Concepts、Ranges、Modules、Coroutines 等,但大部分开发人员并不认可此次调整,并将部分新特性归结为“语法糖”,在社交平台进行吐槽。


国外的一位游戏开发人员接连在社交平台发表看法,甚至发表了一篇长文声明自己不看好 C++20 的新特性,并认为新版本没有解决最关键的问题,这让其未出世就被群嘲。可见,整个 C++ 社区是存在一定问题的,很难让其达到移动开发社区中的活跃度,很多问题也是悬而未决。


2、自定义开发环境的开销


移动生态系统有许多工具可用来提高开发效率,但 C++ 社区就不太行。开发者必须投入时间构建支持 C++ 代码共享的工具。甚至,Dropbox 亲自做了定制构建系统,创建了包含 C++ 代码以及 Java 和 Objective-C 封装器的库,并且生成 Xcodebuild 和 Gradle 都能识别的目标文件。这个系统是一个很大的成本支出和拖累,因为需要不断更新以支持两个构建系统中的更改。


3、处理不同平台差异的开销


尽管 iOS 和 Android 应用程序都是“移动应用程序”,通常具有相同的特性和功能,但平台本身存在一些影响实现的差异,甚至不能真正地编写一次代码就在不同的平台上运行,必须花费大量时间将代码集成到不同的平台中,并编写特定于平台的代码(有时这些代码就位于 C++ 层)。


4、培训、招聘和留住开发人员的开销


如今,市面上越来越难招聘到具有相关 C++ 经验、对移动开发感兴趣的高级工程师。当然,如果愿意提高招聘成本,给出更有吸引力的薪水,这个问题不难解决。但是,怎么把这些开发人员留住也是一个大问题。事实上,移动开发社区有大量新技术和新模式层出不穷,移动开发者可能根本不想从事 C++ 项目开发。


如上种种,通过 C++ 共享移动代码的方式让开发成本变得非常高昂,这也让曾经的支持者 Dropbox 不得不选择放弃。


跨平台开发的 Yes or No


“Write once, run anywhere” 一直以来就是开发者的梦想。但从 Dropbox 的经验来看,实现之路堪称曲折甚至反复。


我们发现了一个特别有意思的新闻:2014 年,Dropbox 的开发人员给 Facebook 的开发人员做了个讲座,分享了他们使用 C++ 做跨平台开发的经验之谈。他们特别提到,iOS 和 Android 平台代码库的不一致会带来一系列问题:


  • 开发和维护成本成倍增加。

  • 开发团队需要多次修复同样的缺陷。

  • 针对某个平台报告的缺陷可能会被另一个平台忽视掉。

  • 不同平台的 App 行为可能会有预料之外的细微差异。

  • 性能优化成本高昂并且与平台相关。


Dropbox 赖以克服上述这些问题的策略基础就是为所有 UI 无关的代码建立一个共享的跨平台 C++ 库,例如数据和网络部分的逻辑。UI 部分还是使用原生代码编写,以便尽可能地利用平台对动画特效和设备传感器等的支持,并且确保充分的响应速度。


5 年过去,当年的经验之谈似乎变成了 Dropbox 的技术债,他们最终放弃了用 C++ 做跨平台开发,转而用各平台的原生语言做开发工作。


跨平台开发,是时兴潮流还是明日黄花?


2018 年,Airbnb 放弃使用 React Native,回归使用原生技术,究其原因主要是:项目庞大后,维护困难;第三方库良莠不齐;兼容上需要耗费更多精力……


腾讯客户端工程师方秋枋接受 InfoQ 采访时曾表示:


这些都是跨平台框架的通病。跨平台意味着需要花费很多时间来解决平台差异性问题,同时要面临第三方库不够原生平台丰富健壮的现状。跨平台其实是牺牲部分功能和体验,换取开发速度和一致性的权衡,并不是业务开发的银弹。


微信团队在跨平台开发方面的解决方案是:


目前微信团队并没有统一使用一套跨平台开发框架。我们也在积极探索各种可能性。

微信小程序,是跨平台开发的第一、二阶段的融合做法,利用 Webview 作为渲染容器,通过规定 Web 技术栈的子集(WXML、WXSS),让客户端获得更多的渲染性能优化空间,同时通过规范化组件的使用,逐步引入原生控件代替 Webview 渲染。

除此之外,我们还探索了基于 C++ 进行跨平台开发。实质上还是第二阶段的做法,只不过是使用 C++ 作为中间语言,去编写业务代码和调用原生控件。为什么要采用 C++ 呢? 因为 C++ 安全性会更高一点,同时性能也会更佳。可以应用在一些对安全性要求比较高的场景。


Flutter 会是跨平台开发的终极之选吗?


这个问题很有意义。能实现跨平台开发的框架也五花八门,让人眼花缭乱。最流行的跨平台框架有 Xamarin、PhoneGap、Ionic、Titanium、Monaca、Sencha、jQuery Mobile、React Native、Flutter 等等。但这些工具的表现也是高低有别,各有千秋。热度不减的只有 React Native 和 Flutter,原因在于这二者背后有 Facebook 和 Google 背书,开发者更加信任。


Flutter 的优势在于:它完全免费,彻底开源;可以用来更快地创建应用;具有出色的用户界面(UI);节省代码量;可接入平台原生功能;最适合 MVP 开发(最小化可行产品);较老的设备也使用相同 UI 运行应用;减少测试工作量;更丰富的社区支持;较低的维护难度;内置来自 Dart 的包管理器。


其中不少特性如节省代码量、接入平台原生功能、支持较老设备、较低维护难度等等,都击中了跨平台开发的痛点。业界认为,目前跨平台开发没有一个完美的解决方案,相对来说 Flutter 在兼容上做得好一点,通过自底向上自研框架来尽可能减少平台差异,但是可靠性仍需进一步检验,引入 Flutter 需要大家对自己公司业务有非常清晰的认知,并权衡好利弊。


随着 Google 对 Flutter 的持续加码,也许在不久的未来,Flutter 将成为跨平台开发的最佳解决方案。


2019 年 8 月 19 日 16:5817707
用户头像
赵钰莹 InfoQ高级编辑

发布了 648 篇内容, 共 383.7 次阅读, 收获喜欢 2082 次。

关注

评论 1 条评论

发布
用户头像
挺有意思的,2014年Dropbox把用C++开发作为跨平台开发的经验之谈,2019年Dropbox弃用跨平台开发方式,选择针对不同的平台启用不同的编程语言。两个事件的原因甚至都相同:同一套代码跨平台开发/写两套代码适用不同平台,二者的成本都太高,难以承受。为什么之前的经验谈会变成以后的技术债?这个问题值得思考。
2019 年 08 月 20 日 10:52
回复
没有更多评论了
发现更多内容

架构师训练营第十二周总结

0x12FD16B

极客时间训练营-12周作业

潜默闻雨

大数据总结

周冬辉

大数据技术

大数据简介&架构(一)

dony.zhang

大数据 hdfs hive YARN MAPRED

week12 作业

雪涛公子

Flink从一致性检查点中恢复-14

小知识点

scala 大数据 flink

架构师训练营作业

qihuajun

极客时间训练营-12周作业2

潜默闻雨

w-12

麻辣

极客大学架构师训练营

week12

强哥

极客大学架构师训练营

如何判断程序员的代码是否优美?

Garfield

代码质量 代码 代码优化 代码重构

架构师课程第十二周总结

dongge

第12周作业

Jaye

大数据课程笔记

superman

mapReduce

架构师训练营Week12学习总结

Frank Zeng

JWT认证看这一篇就够了

架构师修行之路

程序员 架构

深度解析OAuth 2.0授权!!

架构师修行之路

架构 高并发系统设计 OAuth 2.0

第 0 期架构师训练营第 7 周作业 1

傅晶

极客大学架构师训练营 0 期 week 12 作业

chun1123

大数据 hive

第 0 期架构师训练营第 7 周作业 2 ----总结

傅晶

架构师训练营学习总结(大数据)

qihuajun

逛过这个商城,摄像机竟然学会了独立思考

脑极体

架构师训练营第十二周作业

吴吴

架构师训练营 week 12 作业

Frank Zeng

Go云原生应用实战系列(一)

田晓亮

go 云计算 微服务 云原生

第 12 周作业

Mr.Monkey

大数据

GalaxyCreater

大数据

week12 总结

雪涛公子

第十二周总结

Linuxer

极客大学架构师训练营 0 期 week 12 学习笔记

chun1123

大数据 学习

宁愿写两遍代码,也不用C++跨iOS、Android平台开发?-InfoQ