【值得收藏】首次披露Facebook移动端软件的持续部署 | IDCF

(图片来源于网络)

摘要

持续部署是指软件更新一旦准备好就立即发布的实践方法,在业界越来越多地被采用。移动端软件的更新频率普遍落后于基于云端的服务,原因有很多。比如,移动端软件只能定期发布版本;用户可以选择何时升级以及是否升级,这意味着多个不同的版本需要在生产环境中共存;Android设备多种多样,增加了在部署软件时出错的风险。

Facebook在提升移动端软件部署频率方面取得了重大进展,在4年的时间里,Android版本从每8周发布一次变成了每1周发布一次。本文中,我们详细描述了Facebook移动端软件的部署过程。我们基于7年时间内搜集的数据,对软件工程指标进行广泛分析,提出我们的研究结果。一个关键的发现是,部署的频率并不直接影响开发人员的生产效率或软件质量。我们认为这个发现是由于增加持续部署的频率可以促进发布和部署的自动化,从而减少开发人员的工作量导致的。此外,我们提供的数据表明,从Alpha版本和Beta版本的试用客户那里获得反馈对于保持发布质量至关重要。

软件工程/敏捷软件开发

软件配置管理和版本控制系统

软件实施计划

本著作全部或部分的电子版或硬拷贝可用于个人或课堂使用,但不收取任何费用,前提是拷贝不是为了利润或商业利益而制作或分发,且拷贝在第一页上印有本通知的完整的引文。必须尊重除ACM以外的其他人拥有的本作品的权利。允许被授权的摘录。以其他方式复制、再发行、在服务器上发布或重新发布到列表,需要事先获得特定的许可和/或支付费用。

版权归所有者/著作者所有。授权给ACM出版。

关键词

持续部署;软件发布;移动端代码测试;敏捷开发;持续交付

一、介绍

持续部署是一种将软件增量在准备就绪后就更新到生产环境中的工程实践。持续部署在业界正变得越来越普遍,并具有诸多优势,包括更小的增量式变更带来的低风险,更多来自最终用户的快速反馈,以及对安全漏洞等威胁的更快速的响应能力。

在之前的一篇文章中,我们描述了基于云端软件的持续部署过程,即Facebook和另外一家公司的Web前端和服务端的SAAS软件(点击回顾????16800字|从Facebook到OANDA,持续部署一文全解析)。我们介绍了它的实施过程和一些经验。在Facebook,每个部署的软件更新平均有92行代码(LoC)被添加或修改,每个开发人员平均每周向生产环境推送3.5次更新。考虑到Facebook工程团队的规模,这意味着每天会向生产环境部署1000次。

在提到的两家公司中,开发人员对软件更新完全负责,他们没有(就是这么设计的!)单独的测试团队,开发人员负责测试自己的代码,只是在代码提交之前需要进行同行评审。但是,对于测试和质量有大量的自动化支持,只要开发人员认为软件已经准备就绪,就可以把发布代码并将其部署到生产环境中。

正如在前一篇文章中演示的,基于云端的软件环境允许众多小的增量部署,部分原因是部署不会给最终用户带来不便。此外,环境支持很多特性以管理可能导致部署错误的风险,包括蓝绿部署、功能发布开关和灰度发布。即使最坏的情况,只需要按下一个按钮,就可以“回滚”到任何最近部署的更新,将模块恢复到以前的版本。

与之前相比,在本文中我们描述并分析了持续部署如何应用于Facebook的移动端软件。Facebook移动端软件每天超过10亿人使用,软件部署的关键挑战在于不可能像基于云的服务那样进行持续部署,原因如下:

  • 软件更新的频率可能是有限的,因为移动平台上的软件更新对终端用户来说不完全透明,平台的应用审核也需要时间。例如,苹果对iOS应用的审核。

  • 软件不能按照模块部署。只能作为一个整体进行部署,这会增加部署的风险。

  • 降低风险的措施有限。例如热修复和回滚在很大程度上是不可接受的,只能在极端情况下使用,因为涉及到与发布平台的协作(如苹果)。

  • 最终用户可以选择何时升级(如果允许的话),这意味着不同版本的软件在同时运行时要能够正常工作。

  • 不同的硬件种类(特别是Android平台),以及需要支持多个不同版本的操作系统。笛卡尔乘积:应用的版本数量操作系统类型和版本硬件平台数量,导致每次部署的风险都大大增加。

考虑到上述限制,一个有力的开放式问题出现了: 如何能够“持续”进行移动端软件的部署。

Facebook正在努力挑战极限,尽可能接近移动端软件的持续部署。关键的策略是将软件开发、发布与实际的部署解耦:前者经常以小型增量出现,而后者只是周期性出现。特别是开发人员将移动端软件以和云端软件相同的频率进行更新,以类似大小的增量提交到Master分支。只要开发人员认为他们的软件已经可以部署,他们就会这样做。然后,定期从Master分支中切分出一个发布分支,对于Android是每周一次,对于iOS则是两周一次。这个分支中的代码经过了大量的测试,并进行必要的修复后向公众发布。在Facebook中应用的完整流程在第2节中详细描述。

接下来的一个重要问题是:与更连续的云端软件部署过程相比,移动端软件部署过程如何影响开发生产效率和软件质量?

在5.2节中,我们展示了无论以修改或增加的代码行,还是以每天提交次数为度量指标的生产效率,都与Facebook相当。即使移动端工程师团队增长了15倍,甚至软件随着功能增加变得更加复杂,移动端软件开发生产效率仍然保持不变。事实上,在4年时间里,Android端从每8周部署一次到每1周部署一次,对程序员的工作效率没有明显的影响。

测试对移动端应用尤其重要,因为在部署后出现关键问题时,可供采取的补救措施有限(与基于云端的软件相比)。我们在第4节中描述了许多在Facebook中用于移动端代码的测试工具和流程。我们在5.5节中展示了Facebook移动端软件的质量要高于Facebook中所有软件的平均质量。我们发现,移动端软件代码的质量并没有随着开发团队的规模增长、产品的成熟和复杂、发布周期的缩短而恶化。事实上,一些度量指标表明质量会随着时间的推移而提高。

最后,我们在第5节展示了经过分析的调查结果。例如,我们提出在发布分支被切分出来的当天,软件更新的平均质量较低。我们还表明,在同一代码文件上工作的开发人员的数量越多,软件质量就越低。

我们研究的一个重要方面是,我们的分析基于大量的数据 (第3节)。从2009年1月至2016年5月,包括来自版本控制系统的所有提交日志、所有应用程序崩溃记录、Facebook员工和客户报告的所有问题以及发布过程中确定的所有关键问题。在2012年以前的数据中,有意义的结论相对较少,因为那时处于移动端软件的早期阶段,专门从事移动端软件开发的人员相对较少。2012年,Facebook首席执行官在旧金山的TechCrunch Disrupt大会上向公众宣布了公司的“移动端优先”战略。从那时起,移动端开发团队显著增长,收集的数据变得更加完整和有意义。因此,我们提供的大部分数据都是针那段时间的。

综上所述,本文的具体贡献如下:

  • 据我们所知,我们第一个描述了移动端软件的持续部署流程。具体来说,是指Facebook的移动端软件持续部署流程。

  • 这是首次对Facebook的移动端软件测试策略进行描述和评估。

  • 我们基于7年间搜集的与移动端软件相关的数据,对生产效率和软件质量进行了全面分析。我们能够证明快速的发布周期不会对开发人员的生产效率或软件质量产生负面影响。

我们相信我们第一个提出了以下两个引人注目的发现:

  • (i) 修改同一个代码文件的开发人员数量与该代码文件对应的软件质量成反比;

  • (ii) 在从Master分支中切分出发布分支的当天提交的代码质量,要低于其他日期提交的代码质量。

在下一节中,我们将介绍Facebook中Android和iOS端软件的发布周期。第3节展示我们搜集的用于分析的数据。第4节描述使用的测试策略。在第5节中我们提供分析结果。在第6节介绍其他相关的工作。最后,我们会用一篇结束语来结束。

二、移动应用的发布周期

在本节中,我们将详细描述Facebook针对移动应用开发部署的流程和活动。整体架构如图1所示。有两类活动:开发活动和部署活动。

2.1 开发活动

首先,我们描述一下开发活动。在Facebook,移动端软件和基于云端的软件开发活动实际上没有区别。开发人员从主分支拉出一个local revision control system分支。开发时基于本地分支频繁提交。在经过适当的测试后,当开发人员认为软件更新已经准备好可以部署时,将更新的代码提交到主分支。正如我们在§5中所展示的,每个开发人员每周会向主分支提交3-5次,这个频率与Facebook基于云端的软件等同。

2.2 部署活动

现在,我们描述一下图1的下半部分,部署活动。Facebook有一个发布工程团队(RelEng)负责这些活动。团队中包括负责对应平台的项目经理,他们会对阻塞问题做出判断。

iOS和Android都是以流水线的方式做周期性部署,每个周期天数相同。我们首先描述iOS的具体流程,然后再描述Android的流程的不同之处。 

图1:iOS发布周期

整个两周的过程中,每个阶段都是在流水线中(iOS移动代码):基于发布分支的稳定性测试、性能测试、代码评审和部署需要两周时间,而在这两周里,新的软件代码会不断被提交到主分支,直到从主分支中拉出下一个发布分支。

对于iOS来说,发布工程团队会以两周为周期,在第二个周日的下午6点,从Master分支中拉出一个Release分支。Release分支首先要稳定运行5天,在此期间对问题进行修复,并做一些优化和稳定性方面的更新。那些被发布工程团队归类为影响最终用户使用的阻塞性Bug必须在部署之前修复。最后,发布工程团队可以通过将部分代码恢复到以前的版本来绕过一些问题。

开发人员负责解决发布工程团队提出的任何问题,比如已确定的bug。开发人员在解决问题所做的任何更新(包括Bug修复、优化和稳定性更新),都需要提交合并到Master分支。然后,开发人员必须请求发布工程团队将主分支的更新合并到发布分支中,并解释为什么需要合并。

接下来,发布工程团队根据自身判断,将更新的代码合并到Release分支。他们会考虑各种风险因素进行谨慎的分析判断,合并代码的请求可能因为各种原因被发布工程团队拒绝。举两个因为合并风险过高而被拒绝的例子:有太多依赖(比如超过5个)的更新和对核心组件(如网络和显示)做出重大更改的更新。最终,发布工程团队会权衡风险和影响做出判断。例如,一个影响较小的优化类更新,在前2-3天是可以接受的,之后就会被拒绝合并。

在上述的稳定阶段,通过Release分支构建的App会像“狗粮”一样提供给Facebook内部用户使用,每天会提供三次。经过5天的稳定期,代码会被冻结,开始进行为期3天的性能测试。在性能测试期间,只接受阻塞性问题的修复。

最后,在创建Release分支后的第二个周一,会提交软件到苹果公司审核,并在那周的晚些时候发布。

在整个过程中,如图1所示,在当前Release分支稳定的同时,新的更新代码被提交到Master分支。这些更新只有一部分会被发布工程团队合并到Release分支中。不论出于什么原因,如果图右半部分所示的两周不能安全的完成,就会停止部署,所有的代码更新都会被推迟到下一次的定期部署。

Android的发布周期和iOS基本一样,只是拉Release分支的周期由2周被压缩至1周。周四冻结代码,只接受阻塞性问题的修改。

在周一早晨(拉出Release分支后的那周),App通过应用商店分批逐步分发给用户,通常是在接下来的三天内,分别推送20%、50%和100%的用户。每增加一次推送用户比例,都需要定期进行稳定性检查。

对于Android来说,Facebook也会发布Alpha和Bate测试版App。Alpha版本每天从Master分支构建,通过Google Play Store分发给一小部分外部用户(通常小于10000用户)。Bate版本每天从Release分支构建,并提供给更多的外部用户(大约300万)。

发布工程团队

发布工程团队在上述过程中扮演着关键的角色。尽管它很重要,这个团队可能比人们想象中要小——只有不到10个成员。

高级别的产品开发人员不断被借调到发布工程团队临时工作,每次大约2个月时间。这种安排的一个核心优势是,在发布工程团队和开发团队间建立了合作伙伴关系。开发人员开始了解发布工程团队在做什么,流程是什么,有哪些问题和痛点等等。开发人员在发布工程团队工作期间积累的知识,会在回到团队后传授给其他成员。

这种安排的另一个好处是,开发人员在发现发布过程效率低下之后,在某些情况下会为发布工程团队开发工具,从而使发布过程进一步简化和自动化。

三、数据搜集

Facebook收集与每个版本和每个部署相关的大量数据。它保留所有这些数据。在本节中,我们将描述在§5中用于分析的数据集。

3.1 修订控制系统记录

该数据集记录了每次提交和推送、日期、要提交的差异的大小(以LoC度量)、发布差异的开发人员等。

3.2 崩溃(Crash)数据库

FB应用程序崩溃时,崩溃报告会自动发送到FB。崩溃率是应用程序质量的直接指标,这就是为什么要仔细监控这些崩溃报告并用来确定发行版本的运行状况的原因。机器人(Bots)程序会自动将可靠性问题分类为崩溃、软错误、挂起的系统等。每当给定的崩溃率指标高于指定的阈值时,崩溃就会作为启动阻止程序自动提交给任务数据库(如下所述 )。

此外,会自动将崩溃的应用程序的堆栈跟踪与版本控制系统中记录的最新更改进行比较,如果堆栈跟踪上的任何指令接近已更改的代码,则将以自动方式通知进行更改的开发人员办法。我们按日期和应用程序版本汇总崩溃报告。

3.3 捕蝇器(Flytrap)数据库

该数据库包含(内部或外部)用户提交的问题报告。用户可以从应用程序上的“报告问题”组件提交问题,该问题可以从下拉菜单或通过摇动设备获得。或者,他们可以在FB网站上填写帮助中心“联系表”。员工生成的捕蝇器会自动输入到任务数据库中(如下所述)。用户生成的捕蝇器不会自动输入到任务数据库中,因为许多用户提交了不重要的问题、新功能请求、各种改进建议,有时只是垃圾。

总体而言,Flytrap数据库非常嘈杂。因此,只有当机器人能够识别足够数量的用户超过给定阈值报告的问题时,用户生成的捕蝇器才会自动输入到任务数据库中。我们按日期和应用程序版本汇总了Flytrap问题。

3.4 任务(Task)数据库

该数据库是发布工程管理系统的核心组件。它记录了将要执行的每个任务以及需要解决的每个问题。任务由人类和机器人输入;机器人创建的任务数量正在迅速增加。与移动版本相关的任务包括:

  • 阻碍启动(launch-blocking)问题以RelEng标记的关键问题,需要在部署之前解决。

  • 崩溃机器人(crashbot)问题:当崩溃影响超过阈值数量的用户时,bot所创建的任务。

  • 捕蝇器(flytrap)问题:由漫游器为员工报告的问题创建的任务,以及超过阈值数量的捕蝇器报告识别出同一问题的任务。

  • 测试失败:为失败的自动测试创建的任务(请参见第4节)。

3.5 精选(Cherry-pick)数据库

记录所有精选请求,并标记RelEng接受的请求。我们使用“精选点”的数量作为软件质量的代理指标。

3.6 生产问题数据库

生产代码中标识的所有错误都记录在一个单独的数据库中,并且每个错误都按照严重性进行分类:严重、中优先级和低优先级。当人们认为需要修复生产错误(即使优先级较低)时,记录的错误就会被人输入。我们使用该数据库中的问题数量作为部署到生产中的软件质量的一种度量。

3.7 日活人数(DAP)

该数据库记录使用FB应用程序的用户数。我们按数据和应用程序版本汇总了数字。在某些情况下,我们使用此数据来规范崩溃和捕蝇器质量指标。

3.8 锅炉房

该数据库包含有关每个移动部署的信息,包括部署日期、部署状态、从中进行构建的版本分支、所部署的版本的截止日期、alpha / beta /生产版本等。

3.9 员工数据库

该数据可确定每天有多少开发人员在做移动软件开发。该信息是从提交的日志中提取的:如果开发人员在前两周提交了移动代码,则认为她一直在从事移动软件的开发。

3.10 源代码和配置代码

我们使用来自该来源的信息来确定自动化作业的计划方式和时间、以及机器人用来确定何时创建任务的阈值等。

四、测试

测试对于移动应用来说尤其重要,原因如下:

  • 每周对移动软件进行成千上万次更新; 

  • 必须进行数百种设备和操作版本组合;

  • 在部署后出现严重问题时可采取的补救措施很有限。

正如人们可能期望的那样,FB应用了多种类型的测试,包括单元测试、静态分析测试、集成测试、屏幕布局测试、性能测试、构建测试以及手动测试。

工具和自动化起着关键的作用,数百名工具开发人员给我们提供了支持。大多数测试以自动化方式运行。当检测到回归时,会尝试将其自动绑定到最近进行的特定代码更改,然后自动将电子邮件发送给负责该特定更改的开发人员。

在我们描述一些测试之前以及何时进行测试,简要介绍了可用的测试基础架构FB以及指导FB测试的原则策略。

4.1 测试基础架构

数千个计算节点专用于测试移动软件。通过在模拟和仿真环境中运行测试,可以应用白盒和黑盒测试策略。

为了在真实硬件上进行测试,FB运行着真实的移动设备。位置在Prineville数据中心的实验室[9]。移动实验室主要用于测试性能下降,主要关注应用速度,内存使用情况和电池效率。

移动实验室包含电磁隔离的机架。每个机架放置多个测试设备iOS 和Android。节点将安装、测试和卸载目标软件。Chef,是一种配置管理工具[10],用于配置-设备。机架中的无线接入点支持设备Wi-Fi通信。设备放置在机架上,以便它们的屏幕可以被摄像机捕获。工程师可以远程访问摄像机以观察每个设备都会对代码更改做出反应。因此,实验室有效提供测试基础架构即服务。

4.2 Testing Principles at FB

FB的测试原理

FB的测试策略包括以下原则:

  • 测试范围。测试范围尽可能的全面,所有已编写还在运行的都应该测试。尽可能合理地开展测试工作。

  • 快速响应。捕获回归的速度越快,处理起来就越容易;快速捕获的问题更容易被开发人员解决,因为代码和代码结构仍然是最重要的。例如,使用并行构建以便能够更快地提供反馈。目标是能够在开发完成后10分钟内向其提供冒烟测试的结果。

  • 质量。测试应辨认出首要问题。精确,误报和错报需要被最小化。这很重要,不仅能最大程度地减少开发人员花费在追踪错误警报上的时间,并且还能防止测试时间超时。

  • 自动化。测试尽可能地自动化。这使得它们可重复使用,并确保测试能够定期运行。自动化的另一个方面已经被证明是有用的: 自动识别导致代码变更的开发人员,以便他能够立即被告知关于检测到的问题和可能导致问题的代码的具体细节。这是通过比较代码中可能导致检测到的问题的位置与最近应用的代码更改来实现的。由于这种能力只有在质量高的时候才有效,因此人们已经投入了大量的精力来发展这种能力。

  • 优先次序。测试需要大量的计算资源,如果它是详尽的,并在同一时间响应。由于资源总是有限,一个优化过的测试策略是必须的。例如,当一个更改被推送到主分支时,集成测试只在应用程序中那些可能被推送的更改影响的部分进行,而不是运行整个测试套件。这使得更快地向开发人员提供关键测试结果成为可能。完整的集成测试每隔几个小时在主分支和发布分支上运行一次。

表1: 对移动软件进行的测试范围

  • 测试,当他们运行表1列出了一些类型的测试进行了移动软件。这些测试在开发和部署周期的所有阶段运行。

1)预推试验

开发人员在开发代码时,经常会在自己的 pc / 笔记本电脑上运行单元测试。考虑到应用程序的规模以及 pc 和笔记本电脑的开发能力有限,更广泛的单元测试将在模拟环境中的服务器上运行。开发人员还可以手动调用表中列出的任何其他测试,最常调用的是静态分析和一些集成测试。最后,还有一点,虽然没有单独的测试团队,但在将任何代码推送到主分支之前,都需要对代码进行审查。

2)推送

当开发人员认为他的更改已经完成并且工作正常时,他开始将他的更改推送到 master 分支。在实际的推送发生之前,会自动运行许多测试,以确定是否应该阻塞推送。这些测试包括标准的单元测试以及一些冒烟测试,这些测试可以验证大量使用的特性及其关键流是否正常工作。此外,还运行测试以确保带有更改的构建能够正确工作。但是,由于完整的构建需要大量的时间和资源,这里的构建测试只测试几个级别的依赖性。

如果所有测试都通过,则将更改推送到主分支。合并过程可能会识别冲突,在这种情况下,会通知开发人员,以便他能够处理冲突。

在Master和Release分支上进行连续测试。所有测试都在Master和Release分支上连续运行(每隔几个小时)。其中最重要的是移动设备实验室中的完整构建测试、集成回归测试和性能测试。

正如在2中提到的,Alpha 版本是从 master 分支构建的(ios 每天两次,android 每天一次) ,beta 版本是从 release 分支构建的,每天三次。如果某个百分比的测试失败,Alpha 版软件的发布就会被阻止。这种情况很少发生。

3)人工试验

一个约有100人的手工测试小组用来测试移动应用程序。他们做了各种冒烟测试和边缘情况测试,以确保应用程序按预期运行。测试团队主要用于测试尚未创建自动化测试的新特性。最后,在添加了语言翻译之后,他们负责 UI测试,以评估外观和质量。

五、分析

5.1 方法

我们对脸书移动软件工程的定量分析是基于$3的数据描述。从这些数据集中提取的数据被清洗、解释、交叉检查,得出的结论被提交给脸书内部的主题专家进行确认。我们描述了数据集是如何在相关的图标题中被清理的。

一些数据集是从 2009 年 1 月开始的。一直持续到 2016 年。2009 年至 2012 年期间收集的指标相当嘈杂,以至于很难推断出有用的见解。本节的前几张图描述的是 2009 年以后的数据,后面几张图描述的是 2012 年到 2016 年的数据。在 2012 年,开发移动端代码的开发人员不足 100 人,而到 2016 年,开发移动端代码的开发人员已超过 1500 人。每天有超过十亿的用户使用这个软件。

图2:每个开发人员每天平均推送的代码行数。插入图显示了 2012 年中期以后的相同数据。(来自机器的推送被从数据集中删除,为了避免包含第三方软件包、移动或删除目录而修改了 2000 多行代码的推送也是如此。)

图3:每个开发人员平均每天的推送量。(从数据集中删除了来自机器的推送。)  

5.2 开发人员的生产力

图2描述了开发人员的生产力,这是通过代码行(LOC)来度量的,最终平均每个开发人员和每天推送和部署代码行。该图显示,对于Android和iOS,开发人员平均每天生成70个LoC。这与全公司范围内所有软件中每个开发人员每天产生的 64.5 LoC 是一致的(5)。(后台服务的代码生成速度比平均速度慢。)

图3描述了Android 和 iOS 每天的平均推送量。在过去两年中,每个开发者平均每天的推送量分别为 0.7 和 0.8。在全公司范围内的软件中,平均每个开发者每天的工作量是 0.7,因此,iOS 的推送更加频繁。虽然 Android 每天每个开发者的推送量少于 iOS,但它每天每个开发者生成的 LoC 数量与 iOS 相同,这意味着 Android 的推送量略大于 iOS。

比绝对数字更有趣的是,开发人员为移动平台编写代码的数量是如何随时间变化的——图4描述了这些开发人员的数量是如何随时间变化的:

图4:Android和iOs开发团队的规模增长。y轴被故意省略,以免泄露专有信息。 

发现1:即使在代码基础上工作的工程师数量增加了15倍,生产力仍然保持不变。这是Android和iOS开发者的情况,无论是通过LoC推送还是推送的数量来衡量。

对于这种情况的一种假设是,更大的开发组和更复杂的代码库所导致的效率低下,可以通过(i)工具和随时间的推移而进行的自动化改进,以及(ii)所使用的敏捷开发、持续发布和部署过程来抵消。然而,我们可以得出明确的结论:

发现2:脸书移动软件的持续部署过程不会对生产效率产生负面影响,即使开发组织的规模显著扩大。 

5.3 质量

在脸书,每个需要处理的产品环境代码问题都要在产品环境问题数据库中注册,并按严重程度进行分类:

  • (i)危急的,“需要立即在高优先级处理的问题;

  • (ii)中等优先级处理的问题;

  • (iii)低优先级处理的问题”。

我们使用在生产代码中发现的问题的数量作为生产软件质量的一个保证。

图5描述了每个严重级别的问题数量,作为Android和iOS每月推送量的函数。(红色)三角形代表关键的错误,自2012年以来,它们几乎保持不变,每个版本都有0个或1个关键问题。 

发现3:无论决策数量多少,由决策产生的关键问题的数量几乎是不变的。

我们推测,关键问题的数量较少有两个原因:

首先,在测试中更容易发现关键错误;

其次,公司非常重视关键问题,所以每次发生问题后,都会召开一次常务审查会议,以了解问题的根本原因,并确定在未来的部署中如何避免类似的问题。

不出所料,中优先级和低优先级问题的数量与推送量呈线性增长,尽管斜率非常低:对于中优先级问题,斜率分别为0.0003和0.00026,分别适用于Android和iOS。

图5:2011年3月至2016年5月期间,Android和iOS产品代码的问题记录数量与每月推送量的函数关系。

最上面的图表是Android的;iOS的底部。注意,x轴和y轴的比例非常不同:所有的线性趋势线的斜率都小于0.0012。

对于低优先级问题,Android和iOS的斜率分别为0.0012和0.00097。中、低优先级问题的倾斜度在Android上都高于iOS;相对大量的Android硬件平台可能是一个潜在的解释。

有趣的是,在整个公司范围内,所有的软件,这两个相应的斜坡分别是0.0061和0.0013,这两个斜坡都比移动代码更陡。

总的来说,我们认为这些数据证明了应用于移动软件的测试策略是有效的。

图6显示了针对Android和iOS的每个部署的启动阻塞问题的数量和挑选的数量。为了便于直接比较,这些数字是根据发布周期的长度进行规范化的,这是基于这样一个假设:一个长两倍的发布周期将有两倍的push和两倍的LoC修改。也就是说,图中的每个数据点描述了平均年龄每天记录的精选和发射阻滞剂的每个释放周期数。

总的来说,启动阻滞剂的数量和挑选的数量似乎会随着时间的推移而有所波动,但没有特别的趋势。挑选的数量似乎主要停留在Android的5-25和iOS的5-15之间。 

发现4:部署周期的长度不会显著影响挑选和启动阻滞剂的相对数量,因为它从4周减少到2周(然后是Android的1周)。

由此我们得出结论,使用所描述的持续部署过程,部署周期的长度不会直接影响所生成软件的质量。特别是,在部署频率变化的点上,曲线没有不连续。

图6:每个Android(顶部)和iOS(底部)部署的启动阻塞问题的数量(蓝色实线)和挑选的数量(橙色虚线),根据发布周期的长度进行标准化。

图中的每个数据点描述了每个发布周期中每天平均记录的精选和启动拦截器的数量。垂直的直线显示了发布周期的缩短,先是从4周的节奏减少到2周的节奏,然后是Android的减少到1周的节奏。

我们应该注意到,阻塞启动的数量受到至少两方面的影响。

首先,一个问题是否被宣布为启动阻塞是主观的。RelEng认为,随着时间的推移,他们在决定什么是启动阻滞剂方面已经变得更加严格。这有点直观:随着越来越多的人使用移动应用程序,标准往往会提高。

其次,在2015年和2016年开发了大量的测试工具。这些工具可以提高代码质量,从而减少启动阻塞问题。

图7显示了终端用户每天所经历的崩溃率,为了隐藏ab溶质值,将其标准化为常数。条形图的不同颜色代表不同的版本:每减少一次部署周期,色域就会变得更窄(但在节假日期间可能会更宽)。

发现5:缩短发布周期似乎不影响崩溃率。

2015年上半年,安卓系统的崩溃数量有所增加,这有两个原因。

第一,范围,什么被认为是崩溃扩展到也包括Java崩溃时运行的FB应用程序和应用程序不再回应。

第二,引入了一套第三方软件库,提高了系统的crashrate。今年下半年,一些违规软件被移除。

Facebook内部员工在帮助通过“吃自己的狗粮”来测试移动软件方面发挥了关键作用。iOS平台在内部获得了更好的狗粮覆盖,因为雇员倾向于iOS(而不是Android)。这是一个相当严重的问题,因为Android运行的硬件种类繁多。由于这个原因,Android更多地依赖于其软件的测试版和测试版。

图8显示了alpha版本的有效性。

图7:Android顶部图和iOS(底部图)的标准化日崩溃率:经历崩溃的最终用户与被标准化为常数的活动用户总数的比例。

垂直的直线显示了发布周期缩短的地方,首先从4周缩短为2周,然后是Android缩短为1周。为了隐藏绝对值而允许比较,曲线被归一化为相同的常数。 

关于崩溃

从alpha到beta的崩溃率明显下降;在软件的beta版本中偶尔出现的崩溃率峰值不再出现在软件的生产版本中。软件的alpha版本的崩溃率大约比产品版本高10倍。 

5.4 最后期限的影响

在释放分支被切断的那一天,向主分支推送的次数明显增加。这可能表明开发人员急于在截止日期前提交他们的代码,这就引出了一个问题:在发布日提交的代码质量是否下降了?

图9描述了每一次推送选择的数量,作为发布分支被削减当天推送比例的函数。挑选的数量被用作软件质量的代理。在发布日所做的推送的百分比和每天所选的樱桃数量之间存在相关性:随着发布日所做的推送的数量的增加,所需要的樱桃数量也随之增加。

从绝对意义上讲,Android在“剪切日”的推送比例更高。这主要是因为许多数据点表示以一周为周期的发布,而所有iOS数据点表示以两周为周期的发布。也就是说,如果所有的Android推送都均匀地分布在七天里,那么每天会有14%的推送;另一方面,如果iOS推送在14天内均匀分布,那么每天的推送量应该占总推送量的7%。 

发现6:在最后期限当天推出的软件质量较低。

我们的假设是,在削减日推出的软件很可能是匆忙的,匆忙的软件将有较低的质量。

图8:Android 脸书应用程序的alpha(顶部图)、beta(中间图)和production (bot tom图)版本的正常每日崩溃率:经历崩溃的最终用户与正常为常数的活跃用户总数的比例。

注意,下面的图和上面的图是一样的:图7的图形,只是y轴的比例不同。这些图显示了让用户测试软件的alpha和beta版本以提高软件质量的重要性。

在正常情况下,Android在裁员日的推送比例更低,因此专业人士的选择比例也更小。对此,一个直观的解释是:如果一个开发人员认为他的更新不符合要求,他们只需等待一周,因此不会强制执行。然而,如果下一个削减的幅度更大,那么一些开发人员宁愿强行推进而不是等待更长的时间才能更新部署。

另一个有趣的发现是,将截短日期移到周末可以提高质量,部分原因是当截短日期是周末时,匆忙推送更新的倾向较低。2015年8月安卓和2016年2月iOS的截屏时间从周四改到了周日。而推的平均次数iOS的周末推送量从每天0.3次增加到每天0.5次,Android的周末推送量从每天0.175次增加到每天0.5次(图中未显示),(6)周末推送量仍明显低于工作日推送量。如图9所示,推动周末削减日的次数越少,与那些发布的樱桃选择的次数越少相关,这是质量提高的标志。 

5.5 影响软件质量的因素

一个有趣的问题,什么因素影响软件质量?上面我们展示了在截止日期推出的软件将会有较低的质量。但我们也证明了把削减日期改到星期天总体上没有影响。开发人员的生产力、发布周期的长度、工程团队的规模、推的数量似乎不会直接影响软件质量。我们找到和软件质量相关的两个因素:

  • 每个push变化的大小(以修改后的LoC度量) ;

  • 正在更改的文件的大小。

图9:每一次推送的选择与发布截止日期的推送比例的函数。

周四的截线显示为红色的圆圈;星期天的时候切成三角形。对于Android来说,只能在2014年6月之后发布——包括在内。也就是发行周期转变为两周节奏的时候。对于iOS来说,只有在2014年9月之后的版本才会被包括在内,也就是在那个时候发布周期才会切换到两周的节奏。截至2016年5月底的版本同时适用于Android和iOS。

然而,我们确实发现了两个影响软件质量的因素,尽管这两个因素高度相关。首先,我们发现随着将mit代码添加到发布文件的开发人员数量的增加,文件被挑选出来的概率也随之增加。如图10所示。 

发现7:越多的开发人员参与修改一个版本的文件,这个文件的软件质量就越低。

有些文件的修改量大得惊人。这种情况自然发生的一个示例场景是非常大的switch语句,其中与各个case语句相关的代码由不同的开发人员修改。

图10:n个开发人员修改时选中文件的比例,n=1..40。

图11:在n=1.40的情况下提交n次时选中的文件的比例。

上述发现表明文件需要修改-由多个开发商可能应该分裂,以改善质量。

我们发现影响软件质量的第二个因素是一个文件在剪切之间被推送的次数。推的数量越多,文件被挑选的可能性就越大(图11)。但是,请注意,大量开发人员修改文件意味着大量的文件推送。

六、相关工作

持续部署是从敏捷软件开发[16,17,18,19]到持续集成[20,21,22]到持续交付[7,23]的自然延伸。敏捷开发,软件迭代开发,周期短至半天,开始于20世纪90年代后期,现在在许多组织以不同形式使用着。持续集成是在每个软件周期结束时集成软件更新的做法;这样可以通过自动构建和自动测试来验证集成,以尽快发现集成错误。持续交付可以使公司更进一步,确保可以以随时将其发布到生产环境的方式来构建和测试软件。持续部署在每个软件更改准备就绪后立即将其部署到生产环境中。

相关的开发包括精益软件开发[24],kanban[25]和kaizan [26]。Devops 是将开发和运营两方面的角色和工具结合起来的行动[27,28]。

在最近的一项研究中,mcilroy 等人指出,在 google play 商店中的10713个移动应用程序(2013年初 google play 商店30个类别中的前400个免费应用程序)中,1% 的应用程序部署频率超过一周一次,14% 的应用程序至少每两周部署一次。虽然这项研究基于一个相对较小的时间范围,但它表明许多组织正在积极进行持续部署。

然而,文献中只有有限的明确提到了移动软件的持续部署。Klepper 等人扩展了他们的敏捷过程模型,以适应移动应用[30]。Etsy 是持续集成的负责人,在会谈中介绍了他们如何对移动应用程序进行持续集成; 很高效,他们每天将更新下发到每个员工移动终端

关于测试,Kamei等。评估即时质量保证[33],类似于第4节中描述的策略。高Gao et al. 讲解移动测试作为移动软件开发的一个基础服务[34]。亚马逊的Appthwack为此提供了一个移动设备平台[35]。

七、结束语

本文描述了 Facebook 移动应用程序的持续部署。更短的发布周期有许多优点,包括更快的上线时间和更好的响应用户反馈的能力等等。在四年的时间里,Android 的发布周期从8周缩短为1周。我们描述了这段时间学到的东西。

缩短发布周期迫使组织改进工具、自动化测试和过程。我们观察到,在 Android 发布周期从8周减少到1周的四年时间里,这些改进工具和提高自动化程度的努力代表了使持续部署成功的大部分工作。所收集的数据表明,工具和流程的改进提高了质量,并允许更快的发布周期。然而,持续部署本身并没有提供任何生产力或质量改进。

发布用于移动平台的软件更加困难,因为在出现问题的情况下不可能像云软件那样回滚/前进。功能标记用于远程启用或禁用功能,以便有故障的功能不需要新版本。如果自动报告此类问题,则Alpha和Beta程序在提供可减少问题的错误报告方面非常有效。

分析显示出几种导致软件质量降低的模式:

  • 一个人在分支日期忙于发布,发现发布分支被切断的当天提交的软件质量较低。缩短发布周期改善了这一点,因为知道即将发布另一个版本,开发人员不太可能匆忙进行软件开发。

  • 导致软件质量降低的另一种模式是,有太多的开发人员同时在同一个文件上工作,发现每个文件的问题数量与修改文件的开发人员数量成比例地增加。

八、致谢

我们衷心感谢Laurent Charignon,Scott Chou,Amanda Donohue,Ben Holcomb,David Mortenson,Bryan O’Sullivan,James Pearce,Anne Ruggirello,Damien Sereni和Chip Turner所做的宝贵贡献,建议和反馈。他们的意见极大地改善了本文。

参考

[1] T. Savor, M. Douglas, M. Gentili, L. Williams, K. Beck, and M. Stumm, “Continuous deployment at Facebook and OANDA,” in Proc. 38th Intl. Conf. on Software Engineering, (ICSE16), May 2016, pp. 21–30.

[2] C. Parnin, E. Helms, C. Atlee, H. Bought, M. Ghattas, A. Glover, J. Holman, J. Micco, B. Murphy, T. Savor, M. Stumm, S. Whitaker, , and L. Williams, “The top 10 adages in continuous deployment,” IEEE Software, accepted for publication, 2016. 

[3] J. Allspaw and P. Hammond, “10 deploys per day — Dev and Ops cooperation at Flickr,” 2009, slides. [Online]. Available: http://www.slideshare.net/jallspaw/ 10-deploys-per-day-dev-and-ops-cooperation-at-flickr 

[4] M. Brittain, “Continuous deployment: The dirty details,” Jan. 2013. [Online]. Available: http://www.slideshare.net/mikebrittain/ mbrittain-continuous-deploymentalm3public 

[5] T. Schneider, “In praise of continuous deployment: The Wordpress.com story,” 2012, 16 deployments a day. [Online]. Available: http://toni.org/2010/05/19/ in-praise-of-continuous-deployment-the--word\ -press--com--story/ 

[6] G. Gruver, M. Young, and P. Fulgham, A Practical Approach to Large-scale Agile Development — How HP Transformed LaserJet FutureSmart Firmware. Addison-Wesley, 2013. 

[7] J. Humble and D. Farley, Continuous Delivery: Reliable Software Releases through Build, Test, and Deployment Automation. Addison-Wesley, 2010. 

[8] D. Feitelson, E. Frachtenberg, and K. Beck, “Development and deployment at Facebook,” IEEE Internet Computing, vol. 17, no. 4, pp. 8–17, 2013. 

[9] A. Reversat, “The mobile device lab at the Prineville data center,” https://code.facebook.com/posts/300815046928882/ the-mobile-device-lab-at-the-prineville-data-center, Jul. 2016. 

[10] https://www.chef.io/chef/. 

[11] https://developer.apple.com/reference/xctest. 

[12] http://junit.org/. 

[13] http://robolectric.org. 

[14] P. Steinberger, “Running UI tests on iOS with ludicrous speed,” https://pspdfkit.com/blog/2016/ running-ui-tests-with-ludicrous-speed/, Apr. 2016.

[15] https://github.com/facebook/ios-snapshot-test-case/. 

[16] K. Beck, Extreme Programming Explained: Embrace Change. Addison-Wesley, 2000. 

[17] K. Beck, M. Beedle, A. van Bennekum, A. Cockburn, W. Cunningham, M. Fowler, J. Grenning, J. Highsmith, A. Hunt, R. Jeffries, J. Kern, B. Marick, R. C. Martin, S. Mellor, K. Schwaber, J. Sutherland, and D. Thomas, “Manifesto for agile software 22 development,” 2001. [Online]. Available: http://www.agilemanifesto.org/ 

[18] A. Cockburn, Agile Software Development. Addison Wesley Longman, 2002. 

[19] A. Cockburn and L. Williams, “Agile software development: It’s about feedback and change,” Computer, vol. 36, no. 6, pp. 39–43, 2003. 

[20] L. Williams, “Agile software development methedologies and practices,” in Advances in Computers, vol. 80, 2010, pp. 1–44.

[21] M. Fowler and M. Foemmel, “Continuous integration,” Thought-Works) http://www.thoughtworks.com/Continuous Integration.pdf, p. 122, 2006. 

[22] P. M. Duvall, Continuous Integration. Pearson Education India, 2007. 

[23] L. Chen, “Continuous delivery: Huge benefits, but challenges too,” IEEE Software, vol. 32, no. 2, pp. 50–54, 2015. 

[24] M. Poppendieck and M. A. Cusumano, “Lean software development: A tutorial,” IEEE software, vol. 29, no. 5, pp. 26–32, 2012. 

[25] D. J. Anderson, Kanban: Successful Evolutionary Change for Your Technology Business. Blue Hole Press, 2010. 

[26] M. Poppendeick and T. Poppendeick, Lean Software Development. Addison Wesley, 2002. 

[27] M. Httermann, DevOps for developers. Apress, 2012. 

[28] J. Roche, “Adopting DevOps practices in quality assurance,” Communications of the ACM, vol. 56, no. 11, pp. 38–43, 2013. 

[29] S. McIlroy, N. Ali, and A. E. Hassan, “Fresh apps: an empirical study of frequently-updated mobile apps in the google play store,” Empirical Software Engineering, vol. 21, no. 3, pp. 1346–1370, 2016. 

[30] S. Klepper, S. Krusche, S. Peters, B. Bruegge, and L. Alperowitz, “Introducing continuous delivery of mobile apps in a corporate environment: A case study,” in Proceedings of the Second International Workshop on Rapid Continuous Software Engineering, ser. RCoSE ’15, 2015, pp. 5–11. [Online]. Available: http://dl.acm.org/citation.cfm?id=2820678.2820681 

[31] J. Miranda, “How Etsy does continuous integration for mobile apps,” https://www.infoq.com/news/2014/11/ continuous-integration-mobile/, Nov. 2014. 

[32] K. Nassim, “Etsy’s journey to continuous integration for mobile apps,” https://codeascraft.com/2014/02/28/ etsys-journey-to-continuous-integration-for-mobile-apps/, Nov. 2014. 

[33] Y. Kamei, E. Shihab, B. Adams, A. E. Hassan, A. Mockus, A. Sinha, and N. Ubayashi, “A large-scale empirical study of just-in-time quality assurance,” IEEE Transactions on Software Engineering, vol. 39, no. 6, pp. 757–773, 2013. 

[34] J. Gao, W.-T. Tsai, R. Paul, X. Bai, and T. Uehara, “Mobile Testing-as-a-Service (MTaaS) — Infrastructures, issues, solutions and needs,” in 2014 IEEE 15th International Symposium on High-Assurance Systems Engineering, 2014, pp. 158–167. 

[35] https://aws.amazon.com/device-farm.

译者:IDCF社区翻译组

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/310333.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构与算法--二叉树的深度问题

二叉树的深度 题目:输入一颗二叉树的根,求该树的深度。从根节点到叶子节点一次进过的节点形成的一条路径,最长的路径的长度为树的深度。如下图中二叉树的额深度4,因为从根节点A到叶子节点的路径中有4个节点A B E J 问题中定义了一…

进击谷歌:多线程下程序执行顺序怎么稳定不乱?

点击上方蓝字 关注我们面试官您好,我是来面试的您好,我是这次的面试官,先介绍一下自己把我是女孩,blala ....那问一个多线程的问题吧,在一个多线程的环境中,怎么能保证一系列方法的执行顺序呢?…

[Java基础]Set集合概述和特点

练习代码如下: package test21;import java.util.HashSet; import java.util.Set;public class SetDemo {public static void main(String[] args){Set<String> set new HashSet<String>();set.add("hello");set.add("world");set.add("…

深圳本次核酸检普筛怎么将个人信息和结果对应上??

前言 最近深圳疫情比较严重&#xff0c;好在上午新闻公布本次普筛都是阴性&#xff0c;期间我检查了三次&#xff0c;基本上每周测一次的样子&#xff0c;基本的检测非常快&#xff0c;只是需要筛查的人数太多&#xff0c;因此才有几公里的排队出现&#xff0c;期间也发现了一…

借助Redis完成延时任务

背景 相信我们或多或少的会遇到类似下面这样的需求&#xff1a;第三方给了一批数据给我们处理&#xff0c;我们处理好之后就通知他们处理结果。大概就是下面这个图说的。本来在处理完数据之后&#xff0c;我们就会马上把处理结果返回给对方&#xff0c;但是对方要求我们处理速度…

[Java基础]HashSet集合概述和特点

HashSet集合概述和特点: 练习代码如下: package HashSetPackage;import java.util.HashSet;public class HashSetDemo {public static void main(String[] args){HashSet<String> hs new HashSet<String>();hs.add("hello");hs.add("world")…

多亏我缓存技术过硬!疫情防控项目上线,我只用了5天!

先介绍下背景&#xff0c;我是武汉某O2O电商公司开发组长&#xff0c;疫情震中的我被老板要求7天之内上线《疫情防控热点图》项目&#xff0c;几个组员回老家断网&#xff0c;最终就2个人完成开发上线&#xff0c;满足了10w用户的高频访问。时间和人力都紧张&#xff0c;不能按…

数据结构与算法--有序数组中找出和为s的两个数字

有序数组中找和为s的两个数字 题目&#xff1a;输入一个递增排序的数组array&#xff0c; 和一个数字s&#xff0c; 在数组中找出两个数&#xff0c;使得这两个数的和是s&#xff0c;如果有多对&#xff0c;输出一对即可。 最简单方案 双循环&#xff0c;每次获取一个数据&a…

ABP框架使用拦截器动态配置租户过滤器

前言最近项目要求在ABP框架中根据TenantId是否为空来配置是否禁用租户过滤器。ABP自身给我我们禁用租户过滤器的两种方法官方文档https://aspnetboilerplate.com/Pages/Documents/Data-Filters方法一&#xff1a;使用工作单元using (_unitOfWorkManager.Current.DisableFilter(…

[Java基础]LinkedHashSet集合概述和特点

练习代码如下: package LinkedHashSetPack;import java.util.LinkedHashSet;public class LinkedHashSetDemo {public static void main(String[] args){LinkedHashSet<String> linkedHashSet new LinkedHashSet<String>();linkedHashSet.add("hello")…

数据结构与算法--翻转单词顺序

翻转单词顺序 题目&#xff1a;输入一个英文句子&#xff0c;翻转句子中的单词顺序&#xff0c;但是单词内的字符顺序不变&#xff0c;例如&#xff1a;I am a software engineer -> engineer software a am I 方案一&#xff1a;空间换时间 空间换时间方法&#xff0c;还…

在.NET Core中用最原生的方式读取Nacos的配置

背景 之前老黄写过一篇《ASP.NET Core结合Nacos来完成配置管理和服务发现》简单介绍了如何让.NET Core程序接入Nacos&#xff0c;之前的SDK里面更多的是对Nacos的Open API进行了封装以及对服务注册和发现的封装。配置这一块当时并没有过多的处理&#xff0c;用起来有时感觉不会…

[Java基础]TreeSet集合概述和特点

练习代码如下: package TreeSetPack;import java.util.TreeSet;public class TreeSetDemo {public static void main(String[] args){TreeSet<Integer> ts new TreeSet<Integer>();ts.add(10);ts.add(40);ts.add(30);ts.add(50);ts.add(20);ts.add(30);for (Inte…

.NET Core下的开源分布式任务调度系统ScheduleMaster-v2.0低调发布

从1月份首次公开介绍这个项目到现在也快4个月了&#xff0c;期间做了一些修修补补整体没什么大的改动。2.0算是发布之后第一个大的版本更新&#xff0c;带来了许多新功能新特性&#xff0c;也修复了一些已知的bug&#xff0c;在此感谢在博客、Issue和QQ群中提出各种意见的朋友&…

[Java基础]自然排序Comparable的使用

代码如下: package ComparablePack;public class Student implements Comparable<Student>{private String name;private int age;public Student() {}public Student(String name, int age) {this.name name;this.age age;}public String getName() {return name;}pu…

数据结构与算法--我们来玩丢手绢(约瑟夫环问题)

我们来玩丢手绢 昨天我们打扑克&#xff0c;今天我们丢手绢丢手绢我们都知道这个游戏&#xff0c;他的由来由约瑟夫 &#xff08;Josephus&#xff09;提出来的 据说著名犹太历史学家Josephus有过以下的故事&#xff1a;在罗马人占领乔塔帕特后&#xff0c;39 个犹太人与Jose…

后端开发都应该了解点接口的压力测试(Apache Bench版)

背景 小A&#xff1a;小B&#xff0c;最近调你的接口老是超时呀&#xff0c;8秒都还没返回结果&#xff0c;是不是有性能问题呀&#xff01;小B &#xff1a;我看看~~类似这样的对话&#xff0c;在现实中是时有发生的&#xff0c;不是特别严重的话&#xff0c;往往大家也不会去…

数据结构与算法--这个需求很简单怎么实现我不管(发散思维)

发散思维 程序员是一个高危职业&#xff0c;最近动不动就听到谁谁谁猝死&#xff0c;谁谁谁过劳晕倒&#xff0c;所以面对奇葩问题&#xff0c;我们要淡定&#xff0c; 开发中被产品虐&#xff0c;说的最多的一句话就是这个需求很简单&#xff0c;怎么实现我不管 找工作被面试…

[Java基础]比较器排序Comparator的使用

代码如下: package ComparablePack;public class Student {private String name;private int age;public Student() {}public Student(String name, int age) {this.name name;this.age age;}public String getName() {return name;}public void setName(String name) {this…