Dropbox 与 C++ 的“七年之痒”难跨越,跨平台真的是伪命题吗?

局长
 局长
发布于 2019年08月19日
收藏 32

Perl 语言创建者 Larry Wall 曾总结过好的程序员有 3 种美德:懒惰、急躁和傲慢(Laziness, Impatience and hubris)。因为懒惰,程序员绞尽脑汁地将大量的重复性劳动交由机器处理;因为懒惰,程序员希望通过“一次编写,处处运行”而实现“一劳永逸”的美好愿望。

“一次编写,处处运行” —— 简单来说就是跨平台。然而这个十分符合程序员思维,且承载着他们美好愿望的方案,在实际操作中往往不能如其所愿,甚至会适得其反。

Dropbox 工程师近日在其官方博客和大家分享了他们“弃暗投明”的经历 —— 放弃在其 iOS 和 Android 客户端之间共用同一套代码的策略,转而使用各自平台的原生语言进行开发。

工程师表示,Dropbox 在 2013 年开发 iOS 和 Android 平台的移动应用时,采用了通过 C++ 语言在两个平台之间共享同一套代码的策略。当时的想法十分简单,开发团队希望使用 C++ 编写一次代码即可,无需分别针对 iOS 和 Android 平台各使用 Objective-C 和 Java 编写两次代码。另外,当时负责移动应用开发的团队规模相对较小,为支持快速增长的移动应用,他们需要找到一种方法以通过这个小团队在 iOS 和 Android 平台上快速部署大量代码。

但现在 Dropbox 放弃了这个策略,转而使用各自平台的原生语言(主要是 Swift 和 Kotlin)。之所以做出这个决定,是因为在两个平台共用同一套代码的隐藏开销其实很高。他们从中总结到的经验就是:如果遵循广泛使用的平台默认标准,而不是以非标准方式编写代码,他们可以不用承担本应不必考虑的开销,这种开销最终比编写代码两次更昂贵。

Dropbox 工程师将这些隐藏开销归纳为四类,在介绍这些隐藏开销之前,工程师强调他们实际上从未达到大多数代码库均使用 C++ 开发的阶段,因为正是采用 C++ 带来的隐藏开销阻止了他们完全朝这个方向发展。

维护自研框架和库的开销

使用 C++ 首先面临的开销是需要自己构建框架和库,这大致分为 2 个子类别:

  • 支持与主机环境交互以构建完整的移动应用程序的框架。例如:
    • Djinni:用于生成跨语言类型声明和接口绑定的工具
    • 用于在后台运行任务与主线程的框架(使用平台原生语言执行简单任务)
  • 用于替代本可以在平台原生语言中使用的默认或者开源标准库。例如:
    • json11:用于 JSON 的 (反)序列化
    • nn:C++ 的非可空指针

Dropbox 工程师表示,如果采用平台原生语言,这些代码都不是必需的,而且他们对开源项目的贡献可能会使更多的开发者受益于平台原生语言。值得注意的是,上述的这些开销在 C++ 中尤其高(与其他非原生语言如 Python 和 C# 相比),因为它缺少单一的全功能标准库。话虽如此,C/C++ 是唯一包含受 Google 和 Apple 支持的编译器的语言,如果使用不同的语言会产生许多其他需要处理的问题。

维护自研开发环境的开销

移动生态系统有许多工具可帮助提升开发效率。其中用于移动开发的 IDE 也非常丰富,Google 和 Apple 为其投入了大量资源,让开发者在相应的平台上拥有最佳的开发体验。由于 Dropbox 没有使用平台的默认方案,他们自然无法享用这些便利。其中最值得注意的是调试体验,在平台的默认 IDE 中调试平台原生语言的体验通常优于调试 C++ 代码的体验。

Dropbox 工程师举了一个尤其令他们印象深刻的例子,在其后台线程框架中出现了导致应用程序随机崩溃的错误。为此他们使用了简单的标准堆栈,但是也难以定位这些类型的错误。因为这个问题涉及调试在 C++ 和 Java 之间来回运行的多线程代码,最终他们花费了几周的时间才定位了问题所在。

除了工具的缺失,工程师还需要花费时间构建支持共用同一套 C++ 代码的工具。最重要的是,他们需要一个自定义构建系统,该系统用于创建包含 C++ 代码以及封装 Java 和 Objective-C 代码的库,并且可以生成 Xcodebuild 和 Gradle 都能理解的对象。正是这个系统对 Dropbox 的资源造成巨大的拖累,因为它需要不断更新以支持两个构建系统的变更。

可以看到,大量的时间被耗费在造轮子 -> 补轮子的重复中。

解决不同平台之间的差异的开销

虽然 iOS 和 Android 应用程序都统称为“移动应用程序”,并且两者通常具有相同的特性和功能,但平台本身存在一些影响功能实现的差异。例如,应用程序在每个平台上执行后台任务的方式是不同的。即使刚开始采用这种跨平台策略时具有一定的相似之处,但随着时间的推移这些差异会大相径庭(例如,与系统相册的交互)。

因此,工程师甚至无法真正实现编写一次代码并让它在不同平台上开箱即用地运行。他们必须花费大量时间将代码集成到不同的平台,并编写特定于平台的代码。

所以这里的“只编写一次代码”并不能如愿以偿,大大降低了这种方法的便利性。

招聘、培训和留住开发者的开销

当 Dropbox 在其移动应用产品上采用这种策略时,他们拥有一批经验丰富的 C++ 开发者。这个团队启动了 C++ 项目,并对其他的开发者进行了培训以为项目贡献代码。

但随着时间的推移,这些有经验的开发者逐渐去了其他团队或者其他公司。剩下的开发者缺乏足够的经验来支撑和推进项目,而招聘具有相关 C++ 开发经验的高级工程师也变得越来越困难。

最后团队缺乏维护 C++ 代码库的关键专业知识,而要满足这一需求团队有以下两种选择:

  1. 找到并雇用具有这种特定技能的候选人(现实情况是招聘了一年仍未能找到合适的人选)
  2. 针对缺失的技能,在内部培训移动(或 C++)工程师。但现实情况是缺少拥有所需技能的人员来进行培训,所以这个目标也难以实现。甚至在培训前,就有移动工程师透露出对学习 C++ 不感兴趣。为此培训所需的开发者也是一大问题。

在招聘问题上,Dropbox 工程师发现许多移动开发者根本不想在 C++ 项目中工作,这也导致他们许多优秀的工程师离开项目。毕竟移动开发技术的更新非常快,这些开发者希望自己的技术栈能时刻跟上潮流。

结论

Dropbox 表示隐藏开销导致最终的成本超过了收益,还不如使用各自平台的 IDE 开发更为简单和便宜。所以最后他们不再通过 C++(或任何其他非标准方式)共用同一套移动端代码,而是使用各自平台的原生语言编写代码。

相关阅读
Airbnb 宣布放弃使用 React Native,回归使用原生技术
Airbnb 之后,Udacity 也加入弃用 React Native 队列

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
转载请注明:文章转载自 OSCHINA 社区 [http://www.oschina.net]
本文标题:Dropbox 与 C++ 的“七年之痒”难跨越,跨平台真的是伪命题吗?
加载中

精彩评论

卫慧杰
卫慧杰
估计主要还是招人的问题吧,C++写Mobile,也真是为难了他们的工程师
itfanr
itfanr
在招聘问题上,Dropbox 工程师发现许多移动开发者根本不想在 C++ 项目中工作,这也导致他们许多优秀的工程师离开项目。毕竟移动开发技术的更新非常快,这些开发者希望自己的技术栈能时刻跟上潮流。
喵星人123
喵星人123
其实我在学phonegap的时候就意识到这个问题了,后来果断放弃
haitaosoft
haitaosoft
我总结的 好的程序员有 3 种美德:
好逸恶劳,得寸进尺,喜新厌旧
手握华为赛神仙
手握华为赛神仙
用c#可能还好点

最新评论(36

waylau
waylau
Java为啥可以?
dhssingle
dhssingle
微软用 C++ 跨平台不干的挺好的。
猴子叫你一声敢答应吗
猴子叫你一声敢答应吗
其实跨平台最简单的就是开发一套在各个平台都能用的虚拟机,然后你就将程序夸平台的问题转换成为了虚拟机跨平台的问题(和数学家处理问题的思路一样)。比如说jvm
dwingo
dwingo
"但随着时间的推移,这些有经验的开发者逐渐去了其他团队或者其他公司。剩下的开发者缺乏足够的经验来支撑和推进项目,而招聘具有相关 C++ 开发经验的高级工程师也变得越来越困难。"
这确实是挺现实的问题, 尤其在中小公司. C++确实在开发的敏捷度上有些落后, 最关键的是没有很好的包/库管理器, 这在新生的语言里都是标配, 维护生态的基础.
s
shby
其实原生的代码写才十王道,因为即使其他所谓的快平台在处理系统差异的时候需要一个封装层。这个封装层如果不得到及时更新,将会造成很大的麻烦。
bkkkd
bkkkd
主要是成本问题.老板考虑的是解决问题的成本的时间效率,而使用 c++,明显成本和效率都不高.
shzwork
shzwork
真实原因是 c++要干的活更多,但工资却没有更多 有时还更少
lichoking
lichoking
所以傲慢到底为何是美德呢?
zhjphp
zhjphp
qt挺好用啊,为啥不用?
开源中国首席罗纳尔多
开源中国首席罗纳尔多
您好,请问写win和linux内核的,已经适配了机器底层,那exe运行在win上,这个exe是不是编译成win内核可以阅读的机器码,而不是真正的,硬件上面的机器码,因为那部分系统层已经做了?
st_lein
st_lein
机器码肯定是CPU直接执行的啊,操作系统只是提供底层的资源/权限管理和运行环境/标准库什么的
maxiaoxia
maxiaoxia
你的理解是对的,虽然最终是机器码,但中间api是不同的,而且文件组织架构也不同,了解一下PE和ELF
猴子叫你一声敢答应吗
猴子叫你一声敢答应吗
你好,这个问题我可以回答。windows和linux要是都是x86架构的那么他们的机器语言是一样的,不同的是,系统调用不同,库接口的内存地址,参数的传入方式不一样。但是你要是在win上用的是.net,和jvm类似的东西拿些叫虚拟机,有自己的一套很没效率的指令集。
xoHome
xoHome
exe只是一种打包格式,内部包含很多信息,机器码只是一部分。在window上,可执行文件格式是PE,linux下是ELF,MacOS下是Mach-O,每种格式的组织方式都是不同的,内部包含架构信息、加载器信息、动态库依赖信息、符号信息、字符信息等等,描述的是进程在特定平台上运行需要的所有东西,牵扯面非常广。 感兴趣的话可以去了解下具体文件的格式,很扩展知识面。
返回顶部
顶部