一套代码两端运行不靠谱?是时候放弃 C+跨Android、iOS 端开发!

「Write once,run anywhere!」想必是很多开发者以及企业梦寐以求的愿望,但是在分析跨平台中的种种成本之后,我们不禁发问,这种策略真的靠谱吗?

近日,云存储公司 Dropbox 就此发文剖析了这一现状,其表示一直以来,他们均使用了 C++ 语言编写跨 Android、iOS 端的代码,但是经过了 6 年的实践之后,他们发现代码共享相关的隐形成本太高,还不如直接动手写两套代码,最终,其放弃了原来的开发模式,转而使用每个平台的原生语言(如 Swift 和 Kotlin)。接下来,我们将详细了解其中的缘由以及在跨开发过程中所消耗的成本。

作者 | Eyal Guthmann

译者 | 弯月,责编 | 屠敏

出品 | CSDN(ID:CSDNnews)

以下为译文:

Dropbox一直有一个共享移动设备上的iOS和Android代码的策略:使用C++语言编写。

这种策略背后的想法很简单:利用C++编写一次代码就够了,否则就需要用Java和Objective C写两次。我们于2013年开始采用这种C++的策略,当时我们的移动工程团队规模相对较小,而且需要支持快速增长的移动发展蓝图。我们需要找到一种方法,让这个小团队快速发布大量iOS和Android代码。

直到最近,我们才决定完全摒弃这种策略,转而使用每个平台的原生语言(主要是Swift和Kotlin,我们刚开始做移动开发的时候这些语言还没有出现)。做这个决定的原因关系到代码共享相关的隐形成本。我将在本文中分享我们公司在有效共享代码方面得到的经验教训。其实,所有这些都源自同一个基本问题:

如果以非标准的方式编写代码,我们就需要承担额外的开销(如果采用广泛使用的平台就没有这种担心)。结果却发现,这种额外的开销超过了写两次代码的代价。

在深入介绍我们遭遇的所有不同的额外开销之前,我想先澄清一下,实际上我们之前的目标(即大多数代码都用C++开发)从未实现。采用C++引发的额外开销导致我们无法完全朝着这个方向迈进。

请注意,多年以来谷歌和Facebook等大公司一直在开发可扩展的代码共享解决方案。然而,迄今为止这些解决方案的采用范围依然很有限。虽然你可以利用React Native或Flutter等第三方代码共享解决方案,来避免本文描述的部分额外开销,但仍有一些开销避无可避,至少在其中一项技术发展成熟之前我们依然需要承担这些额外的开销。例如,Airbnb也因为本文中描述的许多原因,而不再使用React Native。

我们可以将我们遭遇的额外开销大致分为如下四类:

自定义框架和库的开销

采用C++时最显而易见的开销就是构建框架和库。而这又包含两个方面:

1. 框架:通过与主机环境的交互构建完整的移动应用的框架。

例如:

Djinni,一种用于生成跨语言类型声明和接口绑定的工具。

负责在后台运行任务与主线程(用平台原生语言执行的简单任务)的框架。

2. 库:替换我们本可以在平台原生语言中使用的语言默认开源标准的库。

例如:

json11,实现JSON(de)序列化。

nn,C++的非可空指针。

如果我们坚持使用平台原生语言,那么这些代码都没有必要,而且我们为开源项目贡献的代码也可以让更多使用平台原生语言的开发人员受益。虽然我们可以利用开源的C++代码库,但C++开发社区的开源文化并不如移动开发社区那般强大(特别是移动开发社区中没有C++移动社区)。

请注意,这些成本在C++中特别高(与Python或C#等其他非原生语言相比),因为它缺少单一全面的标准库。尽管如此,C / C++是谷歌和苹果唯一支持的带编译器的语言,因此使用其他语言会面临更多其他需要处理的问题。

自定义开发环境的开销

移动生态系统有许多可以提高开发效率的工具。移动的IDE非常丰富,谷歌和苹果为提高各自平台上的开发体验投入了大量资源。由于我们没有采用默认的平台原生语言,所以无法享受这些好处。最值得注意的是,平台原生语言的调试体验通常都远胜于在平台默认的IDE中调试C++代码的体验。

有一个令我特别难忘的例子,有一次引发后台线程框架死锁的某个bug导致我们的应用频频崩溃。即使在简单的标准技术栈中,你也很难确定这类的bug。因为这个问题需要调试在C ++和Java之间反复切换的多线程代码,所以我们花费了数周时间才修复!

除了丧失了一大批工具之外,我们还需要花时间构建支持C++代码共享的工具。最重要的是,我们需要一个自定义的构建系统,其中包含打包C ++代码以及Java和Objective-C的库,还需要生成Xcodebuild和Gradle都能理解的构建目标。这个系统占用了我们的大量资源,因为它需要不断的更新,才能支持两个构建系统的变动。

解决平台之间差异的开销

虽说iOS和Android应用都是“移动应用”,而且二者通常都具备相同的特性和功能,但平台本身确实存在一些影响实现的差异。例如,应用在每个平台上执行后台任务的方式是不同的。即便我们采用了这种跨平台式策略,虽然刚开始还有点相似,可随着时间的推移差异也逐步拉大(例如,与相机相册的交互等)。

因此,实际上“只需编写一次代码就可以在不同平台上开箱即用”的说法只是一个传说。最终为了将代码集成到不同的平台上,你依然需要花费大量时间编写特定于平台的代码(而且有时你需要改动C++层的代码!)。

因此,只需编写一次代码只是一个永远无法兑现的美梦,这种做法并没有太大益处。

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

最后,虽然这不是最重要的因素,但培训和/或雇用开发人员在我们自定义的技术栈上工作也有一定的成本。当初采用这种移动策略时,我们拥有一批经验丰富的C++开发人员。该小组负责启用了这个C++项目,并为Dropbox培训其他移动开发人员。

过了一段时间后,这些开发人员逐步跳转到了其他团队和其他公司。留下的工程师没有足够的经验挑起技术领导的大梁,而且招聘具备C++经验且对移动开发感兴趣的高级工程师也越来越难。

最终,我们深陷缺乏维护C++代码库的关键专业知识的困境。重获这种专业知识的唯一方法是投资如下其中一个方向:

招聘具备这种特定技术力的工程师(我们尝试了一年多,却无果而终)。

培训内部的移动(或C++)工程师,然而如果你没有具备这些技术力的人员来做培训,这种方法也行不通。此外,早在核心小组的人员发生变动之前,大多数移动工程师就对学习C++失去了感兴趣,因此找不到培训对象也是一个大问题。

在招聘问题之上,维持我们的技术栈面临人员去留的问题,因为移动开发人员根本不想掺和C++的项目。这导致许多有才华的移动工程师都离开了这个项目,最后自定义技术栈的维护工作陷入了举步维艰。总的来说,移动开发社区的发展日新月异,新技术和模式频频出现,且被迅速采用。优秀的开发人员都希望尝试最新的技术。

在拥有标准技术栈的成熟产品环境中,跟上最新技术和产品的步伐是一项很大的挑战。有时,为了保持稳定,你不得不牺牲采用新技术的速度。如果你将自己封闭到某个自定义技术栈中,远离移动生态系统的花花世界,那么这种挑战的难度会急剧上升。

总结

虽然“只需编写一次代码”的说法听起来性价比很高,但实际的额外开销会导致这种做法得不偿失(并让你大失所望)。最终,我们放弃利用C++(或任何非标准的方式)共享移动代码,转而使用平台原生的语言编写代码。

另外,我们也希望我们的工程师享受快乐的工作时光,并为回馈社区做贡献。这也是我们决定向行业标准看齐的原因。

网友说

对于这样一套代码两端运行的成本的计算与使用,网友也纷纷发表了自己的看法:

评论1:

我不明白像Dropbox这种规模的公司明明完全可以采用平台原生语言,为什么还要利用C++开发移动应用。

话说回来,我们公司有一个非常老的ERP系统,我们需要开发一些移动应用。当时我们的团队中只有7个人,却有很多项目需要维护,再加上考虑到共享代码的成本以及我们对C#的熟悉程度后,我们选择了Xamarin。这绝对是一个折衷方案,但也不失为一种务实的选择。

如果你有能力雇佣Java或Obj-C的开发人员,而且要求他们承担起移动开发的工作,那么就应该考虑使用平台的原生语言。

但是,如果你是一家小公司,且拥有Java和C#的开发,同时Obj-C和C#开发人员的招聘有难度,那么就可以考虑Xamarin或其他跨平台共享代码。

总结起来就是,根据自身的实际情况而定。

评论2:

经过多年的反复验证后,我也得出了相同的结论。在两个移动平台之间共享任何定制的业务逻辑(模型、控制器等)并不明智。如果你有一些非常棘手的低级算法或库,或者你需要考虑到速度、数据库、加密,丰富的图形等,那么可以尝试利用C ++或其他语言共享模块。除此之外,即便是谷歌和苹果尝试利用CRUD应用来实现高效的代码共享,最后也无果而终。

对此,你怎么看?

原文:https://blogs.dropbox.com/tech/2019/08/the-not-so-hidden-cost-of-sharing-code-between-ios-and-android/

本文为CSDN翻译,转载请注明来源出处。

【END】

热 文推 荐

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20190820A0ESE800?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券