第5部分:提升你的游戏水平所带来的挑战。
当你的目标不仅仅是建立一个足够好的移动应用,而是一个一流的体验时,你的移动工程方法就会发生变化。这种方法的改变可能是由于
你的应用程序为数以百万计的客户提供服务,也可能是因为你想从第一天起就把世界级的移动体验作为你的应用程序的DNA的一部分。
这一部分涵盖了 "世界级 "应用从早期就开始解决的问题。我们将涵盖非功能方面,如代码质量、合规性、隐私、合规性。我们还将通过实验和功能标志的方法,这些都是创新的应用程序的赌注,以及其他你需要注意的领域,如性能,应用程序的大小,或强制升级的方法。
让我们开始吧!
30. 实验
任何拥有推动合理收入的移动应用程序的公司都会进行A/B测试,即使是小的变化。这种方法既可以测量变化的影响,又可以确保没有对客户--和收入--产生负面影响的重大退步。
功能标志只是实验系统的第一个必要工具。 通过暂存和用户分组来控制推出,分析结果,检测和应对回归,以及实验后的分析,这些都构成了一个先进和强大的实验系统。
当你很小的时候,实验是很容易的,主要是因为你很少有超过几个实验在进行。与一个Uber规模的应用相比,在任何时候都可能有超过1000个实验在运行,每个实验针对不同的城市和目标群体,有些实验会相互影响。
工具是问题的一部分。 有很多相当成熟的实验系统--有些是为原生移动端建立的--从头开始。
内部实验系统在大公司中很常见,原因有几个。
- 新颖的系统。 许多这些系统是新颖的,随着公司内部数据科学和工程的发展而发展。市场上往往没有数据科学团队想要的那么先进的东西。
- 数据源可以来自很多地方,其中有几个是内部的。例如,你可以直接将一个实验与产生的收入联系起来,并将其与治疗组的收入进行比较。
- 以有效的方式支持许多团队,这不是大多数第三方实验平台所擅长的。
- 数据所有权是明确的:所有实验数据都留在内部。
- 科技公司的核心能力很少被 "外包"。从今天起,快速实验并根据数据做出决定的能力有足够大的优势,希望将其保留在内部。即使这意味着花更多的钱,内部解决方案可以让公司在竞争中保持领先。
即使有一个公司可以购买的替代解决方案,也意味着昂贵的迁移,而且一些内部功能可能工作方式不同,甚至不存在。例如,Uber对某些城市和地区有独特的监管要求,这些要求必须体现在如何在某一地区推出或不推出实验。这种监管要求是针对临时工经济和特定城市的。市场上的任何实验平台都不太可能了解这种情况,从而能够支持这种用例。
选择在内部进行实验的公司包括Uber、亚马逊、谷歌、Netflix、Twitter、Airbnb、Facebook、Doordash、LinkedIn、Dropbox、Spotify、Adobe、Oracle、Pinterest、Skyscanner、Prezi以及其他许多公司。Skyscanner是一个例子,该公司在决定将实验转移到内部之前,先从一个供应商--Optimizely--开始。
从内部解决方案转向供应商的动机通常是基于成本的(与使用供应商相比,操作和维护当前系统的成本更高),以及标准化(拥有一个统一的平台而不是几个团队)。
有一个统一的平台,而不是由几个团队建立和维护自定义工具,并在孤岛上进行实验)。GoDaddy就是一个例子,他们将部分实验转移到供应商的解决方案中,以努力实现各部门的标准化,同时保持内部的功能标志实施。
现成的实验和特征标志系统很多,中小型公司和团队通常会选择其中之一。在这一点上,建立、运行和维护一个内部系统可能比选择一个供应商更昂贵,而且功能更少。
流行的供应商选择包括Firebase Remote Config, LauchDarkly, Optimizely, Split.io和其他。在功能标记系统之上,许多公司使用产品分析框架进行更高级的分析,Amplitude是一个普遍引用的框架。
另一个困难是过程;保持对实验的跟踪,并确保它们不会相互影响。对于一个小团队来说,这不是一个大问题。但是当你有一打以上的团队在做实验的时候,你就会遇到实验之间相互影响的情况。
流程和工具都可以帮助保持对实验的跟踪。广播即将进行的实验,数据科学家或产品经理的同步,以及一个可以轻松定位和监控活动实验的工具,都可以在这方面有所帮助。不过,这些大部分都是你需要在公司内部定制的东西。
对每一个变化进行实验是拥有大型应用的公司的常见做法,在这种情况下,一个变化出错的商业影响可能是糟糕的。Uber就是一个很好的例子,每一个移动的改变都需要是可逆的,而且是在一个功能标志后面。即使是在修复错误的情况下,修复也会被放在一个功能标志后面,并作为A/B测试推出。我们将监测关键的业务指标,如注册完成率、旅行率或支付成功率,并跟踪任何退步。应用程序中的所有变化都需要不减少关键的业务指标。
这种方法是不是有点矫枉过正?对于一个小的应用程序来说,是的。然而,在Uber,这种方法帮助我们抓住了导致人们减少出行的问题。即使出行次数减少1%,每年也会以亿计,所以我们有理由关注这个问题。
我记得我们修复了一个错误,以解决在给数字钱包充值时,用户在试图充值超过允许的限额(例如50美元)时看到一个错误。我们做了一个修复,这样当你输入的金额大于这个数字时,文本框会自动修正为最大金额50美元。我们测试了这个修正,然后开始推广。
在推广过程中,我们看到在统计学上,充值的情况明显减少,所以我们回退了。事实证明,当人们输入大于50美元的金额时,他们对发生的情况感到困惑,于是他们放弃了充值。如果不是因为实验,我们可能会忽略这个事实,即这个修复实际上造成了一个退步。
谁拥有实验,以及协调实验的问题,是应该在团队层面澄清的。最常见的设置是由数据科学家或项目管理人员负责实验,与工程部门合作,确保实验的正确实施。然而,工程师们很少拥有控制/治疗组的推出,或者决定如何对用户进行扣减。
关于实验的进一步阅读,其中许多内容不仅适用于移动领域。
- 构建智能实验平台,分析实验结果和Uber的自带指标平台
- 来自Doordash的实验分析平台
- 来自Spotify的我们的新实验平台
- 来自LinkedIn的我们的实验引擎
- 我们的实验平台,第一部分 来自Zalando
- 扩大我们的实验平台 来自Airbnb
- 这是关于A/B测试:我们的实验平台 来自Netflix
- 可扩展的功能切换和A/B测试 来自Grab
- Wasabi:一个开源的A/B测试平台 from Intuit
- 建立我们的A/B测试平台 来自Pinterest
- 实验:技术概述 来自Twitter
- 在iOS上进行A/B测试移动应用程序 来自Farfetch
- 建立实验文化 来自《哈佛商业评论》。
31. 特色旗帜地狱
每个使用过特征标志的人都会告诉你,它们很好。我同意使用这些会给你带来更多的信心--和数据。然而,随着时间的推移,特征标志的缺点变得明显。
使用一个典型的特征标记在代码库中通常看起来类似于这样。
if (featureFlagActive) {
// New functionality
} else {
// Original functionality
}
用功能标志添加新的功能,对一些事情有帮助。
- A/B测试和实验。 在构建新功能时,团队假设它将比以前的功能做得更好。使用功能标志允许你对这种方法进行A/B测试,收集数据并确认这种假设。在A/B测试完成后,你将全面推出该功能标志。
- 逐步推出。即使在你测试出实验效果符合预期之后,你往往也不想一下子推出这个变化。逐步推出功能对于拥有大量用户的应用程序来说是很常见的。团队通常会监测指标是否符合预期,并且与新功能相关的用户问题没有意外增加。
- 区域性推出。有些功能只能在某些地区或特定用户群中推广。功能标志使这些推广工作易于管理。
随着应用程序中活跃的功能标志的数量增加,功能问题变得更加普遍。这通常与开发团队和应用程序的复杂性平行,增加。
互相依赖的特征标志是一个有趣的边缘案例,可能发生在复杂的推出中。以在MainFeature中构建SubFeature为例。构建SubFeature的团队可能想对待用户群中50%的用户,并相应地推出标志。然而,只有被MainFeature对待的用户才会看到SubFeature,如果MainFeature没有被100%的用户推出,SubFeature被看到的用户会比团队预期的少很多。作为推广计划的一部分,绘制出功能标志的依赖性是大多数团队解决这个问题的方法。虽然这个问题看起来并不复杂,但我观察到从事复杂应用程序的团队一次又一次地遇到了同样的问题。
随着开发团队的壮大,冲突的功能标志成为一个问题。以两个团队为例;TeamA和TeamB在FlagA和FlagB后面构建各自的功能。他们都测试了当他们的旗帜打开时,这个功能是有效的。然而,他们不知道另一个团队正在开发他们的功能,所以没有在旗帜打开的情况下测试它。在推出过程中,当FlagA和FlagB都被打开时,应用程序的一个部分被破坏。
移动应用程序中冲突的功能标志
功能标志在代码库中越来越陈旧, 一段时间后会成为一个严重的问题。这些陈旧的功能标志要么被处理,要么从未被推出。无论哪种情况,现在的应用程序中都有死的代码。
我相信,陈旧的功能标志比死代码更糟糕。在后端或网络上有了死代码,你可以很快确认代码是死的。如果你不小心删除了活着的代码并进行了部署,你可以通过重新添加代码并再次部署来撤销这个错误。
对于移动设备,有一个非常现实的危险,那就是在功能标志后面删除非死的代码。因此,移动代码库最终会充斥着引用特性标记的if-else表达式。许多这样的表达式无限期地留在代码库中,影响了可读性、可维护性,以及--在很小的程度上--二进制大小。
清理标志的最好方法是尽可能地将这项工作自动化。在一个特性标志被完全推出后,创建一个自动拉动请求,删除死的执行路径和标志。这就是在Uber建立并开源的Piranha工具背后的想法。一旦这个工具到位,我们就开始以更大的信心和更快的速度删除旧的功能标志。
对Piranha这样的工具的批评是,这个工具只有在代码库允许的情况下才是好的。Piranha在那些围绕特征标记的编码风格不一致的代码库中无法正常工作。当遇到以不同风格编写的代码时,它也会提出可能导致中断的建议。当功能标志遵循由interter强制执行的一致的编码模式,或使用共享的、有意见的功能标志库时,引入Piranha这样的工具效果更好。
是否要建立你的自定义功能标记系统是每个团队需要自己回答的问题。市场上有很多成熟的供应商解决方案,可以很好地与iOS和Android集成,并允许对功能标志进行细化定位。
建立你自己的功能标记系统是一项庞大的工程,而移动组件是其中较小的部分。旗帜推出系统和设置它以支持实验,是工作的较大部分。在Uber,我们把自己的系统建立在我们的实验平台上,并与多个内部解决方案集成。我不会推荐这种方法,除非你有一个坚实的商业案例,而且你已经确认使用供应商没有意义。
然而,在供应商的功能旗帜解决方案之上建立一个门面可能是一个聪明的解决方案。这就是JustEat在iOS上使用开源的JustTweak组件的做法。这个接口允许他们切换和回退到各种功能标志供应商。
进一步阅读。
- Piranha:一个自动删除陈旧代码的开源工具 来自Uber
- iOS的智能功能标记系统 来自Just Eat
- VMWare的在移动应用中使用功能标志
- 我们的功能标记开发之旅 来自LINE
- 远程功能标志并不总是免费的 from ProAndroidDev
32. 性能
移动应用程序的性能是你很少需要担心的问题,而随着你的应用程序--以及从事该应用程序的移动团队--的发展,这个问题变得越来越重要。谷歌会对性能指标不佳的应用程序进行惩罚,在谷歌商店的排名中降低。根据2015年Techbeacon研究,用户最终会放弃有问题的应用程序。自该研究以来,人们对 "快速 "应用的期望可能只会增加。
现实世界中常见的性能瓶颈与大型应用程序。
-
应用程序的启动时间膨胀,在几个团队添加了需要在启动时完成的 "仅仅一件小事 "之后。这可能是一个网络请求,或一个阻塞CPU的小操作。在Uber,移动平台团队负责应用程序的启动时间。这意味着调试为什么应用程序需要这么长时间,并解决这些问题,例如,通过合并网络请求。该团队还建立了应用启动测量,以检测应用启动的任何倒退,并调查何时发生这种情况。
-
太多并行的网络调用。 几个组件可能同时发出独立的网络请求,影响了网络性能。随着消耗网络的团队数量的增加,一个常见的解决方案是让一个平台团队拥有网络层。这个团队通常开始测量并行资源的影响,并可能为调用设置一个优先级系统,他们限制并行请求的数量。优化网络在很大程度上取决于应用程序的功能,以及低延迟网络的重要性。
-
网络性能,特别是在低带宽或高延迟的情况下。对于有数千万或数亿用户使用的应用程序,这些用户中越来越多的人将在连接不佳的情况下使用该应用程序。在某些情况下,使用不同于HTTP/2的协议可能是一个答案。这就是Uber想出的办法,使用QUIC,这是一个在UDP上的协议。你也可以参考其他协议;医疗保健应用Halodoc使用MQTT作为其网络层。
-
电池消耗率。在应用上工作的团队越多,不必要的CPU使用空间就越大,无论是在运行应用时,还是在后台时。早期的Skype应用程序因耗尽电池而臭名昭著,这一特点导致了更高的用户流失率。对CPU性能进行剖析,并取样查看最严重的违规者,这些都是减少资源使用的好策略。一个专门负责电池消耗的移动平台团队通常比每个团队自己优化他们的堆栈部分更有助于推动工作。应用无响应(ANR)发生在UI线程在一个应用中被阻塞太久的时候。用户注意到应用程序没有响应,将不得不杀死该应用程序,或者在Android上,操作系统将提供杀死该进程。你既要避免应用进入这种状态,又要在它进入这种状态时进行检测和修复。
-
冻结的框架和缓慢的渲染框架表明应用程序的速度很慢,而且似乎没有反应。慢速渲染帧指的是超过0.1%的帧需要700ms的渲染,而冻结帧指的是50%或更多的帧需要超过16ms的渲染的UI框架。这些或类似的指标有助于衡量应用程序是否会让一些用户感到 "非常慢",或让其他用户感到 "生硬"。
-
动画和用户界面的渲染性能是另一个明显的问题,特别是在旧设备上的自定义动画和用户界面元素。追踪和分析是调试问题的通常方法,同时也要注意缓慢的渲染帧或冻结帧。帮助调试UI的工具包括Reveal for iOS 和Layout Inspector for Android。剖析的问题之一是iOS和Android的追踪仪器如何增加开销,导致动画和按键转换在这些条件下运行得更慢,并使调查更难。Uber建立并开源了Nanoscope,以便以更少的开销进行追踪,并更准确地调试动画问题。
在构建大多数应用程序时,在每个屏幕的基础上测量和改进性能是一种常见的方法。Wayfair对他们的方法做了一个很好的总结,有一个前后的视频。一个页面变慢的根本原因往往不是一个单纯的移动问题,而是移动应用和后端如何共同工作的组合。
一旦你看到一个可见的性能问题,例如屏幕 "慢",调试性能问题的最简单的方法就是从移动客户端开始。通过剖析或追踪来测量每个函数所需的时间,然后再分而治之。看看哪些调用在移动客户端上是多余的,看看你需要在哪里提高后端终端的性能。
通过使用iOS的Instruments和Android studio的Android Profiler,你可以很容易地开始对你的应用程序进行手动分析。虽然这是一个很好的开始方式,但不幸的是,手动剖析应用程序的规模并不大。你将很难获得 "真实的数据",特别是当你的应用程序
被大量的用户在各种设备上使用时,你将很难获得 "真实的数据"。在这种情况下,硬件种类和使用模式都可能是你无法用手动剖析来模拟的。
理论上,自动分析应用程序是测量性能特征和发现性能退步的一个好步骤。不幸的是,性能测量过程的自动化是很复杂的。要做到这一点,你需要编写和维护大量的自动化UI或端到端测试。一旦你做到这一点,你就需要将性能分析自动化。自动化工具是一项具有挑战性的任务;PSPDFkit团队找不到这样做的变通方法。
即使你能够自动进行这些测试的性能分析,你仍然只能得到 "真实世界 "数据的一小部分。你的结果可能显示,应用程序在模拟器或你的测试设备上运行得足够快,但那些拥有旧设备或操作系统版本的用户呢?
对真实世界的应用性能测量进行抽样调查是一个更可靠和可扩展的解决方案,以保持你的应用的性能特征。在Uber,我们建立了一个内部解决方案来测量屏幕、网络和应用程序内的功能的延迟,并将其报告给后端。我们根据较新和较旧的设备来划分数据,并提醒那些代码和功能表现不佳的团队。下面是一个报告仪表板的样子。
通过采样数据可视化Uber的真实世界的应用程序性能。
做任何形式的采样或追踪都会对代码的性能产生影响,所以将其运送给大多数生产用户是不明智的。一个更好的方法是为测试版用户启用这种抽样,并选择测量生产用户的小规模样本。
网络性能是一个可能会变得很棘手的领域,要保持在最高水平。你希望你的应用程序在网络条件差的情况下也能保持良好的工作状态。关于如何保持良好的 "网络卫生 "的一些想法,是广大团队关注的一个领域。
-
人为降低网络速度是我们在Uber做的事情。几个月来,每周四,测试版应用程序中的网络层将为员工放慢流量,以尝试模拟低带宽条件,并提高对低带宽使用情况的认识。这个实验是成功的,工程师们做出了一些改进,如果没有这种推动,这些改进可能不会发生。
-
减少一些网络请求并注入延迟是Wave团队提高对真实世界网络场景的认识的方式。他们在开发构建中减少了10%的网络请求,并在网络层增加了延迟。这种方法提醒人们尽量减少往返次数,建立良好的 "加载 "用户界面,并使每一个突变都是空闲的。
值得测量的性能特征,可以是手动运行的配置文件,也可以是自动运行的配置文件,还可以对真实世界的使用情况进行采样。
- 应用程序的启动时间和跟踪应用程序的启动如何变化,随着应用程序的增长。
- 加载屏幕的延迟,确定最慢的屏幕,以及对这种延迟贡献最大的代码。
- 网络性能: 以客户端发生的延迟和并行请求,以及端点的错误率来衡量。
- 内存消耗: 以应用程序使用的内存来衡量,或者简单地以设备的可用内存来衡量。
- 本地存储大小,如果应用程序使用本地存储。例如,在本地缓存时,确保缓存驱逐策略正常工作。
- UI性能,例如,通过测量掉帧、慢帧或冻结帧。
- 自动测量性能特征,尽你所能。自动剖析、对现实世界的性能数据进行采样,或者监测类似于Halodoc所做的的功能指标,都是不错的方法。
使用p95测量点是移动端的明智选择,因为这将给你提供大多数人经历的数字,而不是计算最慢的5%,这可能包括使用慢速设备或连接性远低于平均水平的人。当你的应用发展到为数亿人服务时,你可以考虑将这个数字提高到p99,以确保几乎所有使用该应用的人都有良好的体验,即使是在旧设备和连接不佳的情况下。
性能监测工具。
- Nanoscope:一个极其精确的Android方法追踪工具,来自Uber。工具概述。
- Profilo:了解Android应用在野外的性能,来自Facebook。工具概述
- Firebase性能:远程监控Android和iOS应用程序。
- perf.dev:来自Nanoscope的创造者的应用性能测试。
供进一步阅读的资源。
- 谷歌的应用程序启动时间指南
- 构建速度惊人的安卓应用 来自LinkedIn。
- Halodoc的监测非功能指标。
- 实现更快的日常超级应用程序的旅程 来自Grab
- 采用QUIC协议来优化应用程序性能 来自Uber
- 优化Netflix的安卓应用 来自Netflix
- 构建流畅的Android动画和流畅的iOS动画 来自Netflix
- MobileLab: preventing mobile performance regressions from Facebook
- Skyscanner的改善我们的iOS应用性能
- 我们监控iOS应用性能的方法 来自Mercari engineering
33. 分析、监测和警报。
对出错的事情进行监控和报警是后端和网络团队的普遍做法。5xx响应的激增,或异常的增加,往往会引起警报,使团队和工程师减轻根本原因。
对于移动应用程序,崩溃报告是一个类似的方法。应用程序崩溃是最明显和最有影响的出错事件。移动团队通常已经建立了崩溃报告和警报解决方案,要么使用像Bugsnag这样的供应商,要么建立自制的工具。
然而,根据我的经验,业务监控和业务事件警报在应用程序的开发周期中往往是一个遥远的第二想法。监控移动应用程序可以而且应该比监控崩溃更深入。成熟的团队会在关键流程出现倒退时进行检测,获得警报,并开始调查可能的根本原因是什么。
移动分析
监测业务事件的第一步是决定我们要测量什么。对于一个给定的移动功能,哪些流量和指标是重要的?
分析工具记录和分析数据,你可以选择供应商的解决方案,或在内部进行。
- Google Analytics与Firebase Analytics SDK的结合是一种流行的入门方式:它是免费的,而且对大多数团队来说是一个很好的开始。
- 其他供应商的产品,如Amplitude、Flurry、Mixpanel、Fullstory、Appsee和其他公司都提供了各种功能。在这一组中,Amplitude作为市场上最先进的产品分析套件之一脱颖而出。
- 内部分析是拥有可用资源的大型组织所承担的工作。成本是最大的缺点,而定制、建立供应商不提供的功能、与内部数据源整合和数据所有权是公司有时会采取这种方式的原因。在Uber,由于数据的规模,我们使用了内部分析,而且我们能够使用这种方式的内部工具。
iOS和Android的事件和流程不同是任何分析方法的主要痛点。理想情况下,你希望将iOS和Android的流量可视化。然而,在实践中,这往往意味着需要大量的工作来手动 "匹配 "两个平台上的事件,尤其是在iOS和Android团队各自为政的时候。
认真对待分析的团队通常会在计划阶段考虑事件,与另一个平台协调,并与产品和数据科学合作,以确保他们发出足够的数据进行有效跟踪。
业务事件监测
获得原始的移动分析数据,如显示的屏幕或用户做出的动作,是监测旅程的第一步。绘制企业真正关心的事件是下一步。
首先,你需要定义应用程序中的关键业务事件和路径。在Uber,我们与产品经理和数据科学家一起做这件事。例如,在支付方面,我们想出了以下关键业务事件。
- 一个新用户在注册时添加了他们的第一个支付工具
- 一个现有的用户添加了一个新的支付工具
- 一个用户更新了他们的付款
- 用户在应用程序中为钱包充值
- 一个用户删除了一个支付方式
- 试图使用一个支付方式时发生错误
下一步是实现对业务事件的跨平台监控。 在Uber,这意味着要创建实时图表,记录所有这些跨平台的业务事件。我们必须对iOS和Android的事件分别进行映射,因为这两个代码库是分开的,然后确保分析的更新不会破坏映射。
能够深入到区域或子功能是大型应用的一个典型需求。在Uber,我们需要能够将监测范围一直缩小到城市一级,因为我们经常从一个城市或国家开始启动实验。
指标是错误的,但公司里没有人在几个月或几年内注意到是一个比大多数团队或公司意识到的更普遍的问题。正如Pinterest移动工程经理Ryan Cooke在2018年Droidcon SF的演讲When Metrics Lie中解释的那样,在iOS、Android和移动网络上错误地测量日活跃用户就是一个很好的例子。
我观察到一些公司高估了原生网络,低估了原生移动的保留率或用户活动。然后这些公司错误地将数百万美元的营销预算分配给一个渠道,而实际上,这个渠道的表现并不像数字显示的那样好。这总是归结于一个问题,即分析方法在iOS、Android和移动网络上的实施略有不同。
认证指标是Pinterest多年来一直在做的一个过程,并取得了良好的效果。经过认证的指标需要一个明确的产品规格(spec),确保一致的实施。产品规格意味着一致的定义,考虑了边缘案例,有助于理解利益相关者的需求。Pinterest团队发现不一致的实施方式弊大于利,于是引入了这个认证过程。
Pinterest的度量衡认证过程。请看完整的谈话。
在认证指标之上的数据验证是Pinterest最成功的地方。他们使用三个步骤。
- 异常检测,例如在看到一周比一周的怪异情况时发出警报。这种方法是最容易实现的,它可以捕捉到一些倒退的情况。
- 深入研究数据,并与其他数据点进行比较。 例如,在比较活跃用户和正在看内容的用户时。如果某些用户看到了内容,但不被认为是活跃用户,就需要找出问题所在。这就是揭开了一大块问题的方法。
- 1.用自动化的UI测试来验证指标的正确记录,以确认服务器收到的记录是按预期工作的。这些测试的编写和维护成本很高。然而,如果没有这些测试,就没有办法可靠地检测到指标的回归。Pinterest发现,这些测试可以在大多数指标问题进入生产之前捕捉到它们。
你需要监测你的指标的正确行为,而不仅仅是最初的实施。指标出错的常见方式之一是在对之前正确的实施进行改变之后,而没有监控来检测这种退化。
移动警报
你如何检测与移动应用相关的某个业务事件是否有可疑的变化?要做到这一点,你需要把自动警报放在适当的位置。
如果移动业务事件有可疑之处,是否应该呼唤移动工程师?每个团队都必须想出自己的答案。如果没有注意到关键业务指标的下降,会有什么影响?
实时的移动警报并不是行业的常态。在一项不具代表性的Twitter民意调查中,有168个回答,四分之一的移动工程师说他们有实时移动警报。
大多数移动工程团队可能没有实时的移动警报(来源)
崩溃报告警报是团队中最常见的警报类型。一些供应商的解决方案可以很容易地配置崩溃高峰来触发PagerDuty或其他集成。例如,Bugsnag用他们的警报和工作流引擎提供可配置的崩溃警报。
崩溃警报的内部实施通常是为了支持捕捉发布版和测试版上的回归。但要注意的是,分组崩溃和检测模式(例如只发生在某些设备上的崩溃)会比许多人预期的更具挑战性。
当你有足够好的业务事件监测时,你可以在健康指标上进行滚动警报。然后,你可以监测关键业务指标的任何倒退。在Uber,我们不能降低的指标是与人们的出行有关的。在每一个构建火车的步骤中,我们都会对相关事件的回归进行监测、可视化和报警,在区域层面上进行监测。
在Uber的关键健康指标上推出监测和警报,在区域层面上(来源)。
对业务事件的变化发出警报是很少有移动团队做的事情,即使在建立大型和广泛使用的应用程序时也是如此。做到这一点的团队往往是建立在并非专门针对移动的警报工具之上的。例如,Uber将移动事件发送到内部的异常检测服务,并在该服务确定有奇怪的事情发生时收到警报。Twitch团队在他们的Kinesis事件流之上使用Cloudwatch异常检测来处理移动事件。
如果你开始对这些事件发出警报,移动业务事件的噪音将是你面临的最大问题。应用程序有周期性的使用,而这些周期在不同的地区会有所不同。现实世界的事件会导致移动应用的使用量激增或减少,然后会触发异常检测。在Uber,早期的时候,移动团队在音乐会和当地促销活动后经常被呼唤,导致应用程序的使用量异常激增,直到我们放宽了这些警报的阈值,故意让它们不那么敏感。
如果你想在移动端做到这一点, 一些应用功能的区域警报就成为一个更具挑战性的问题。在Uber,我们支持近60个国家的10多种支付方式,并希望在任何国家的支付方式出现异常时得到通知。我们需要这种细化的原因是,我们花了好几个月才发现PayPal在日本无法使用。
对于这种类型的警报,你几乎肯定需要在内部建立这样的程序。在Uber,我们建立这种警报的第一个挑战是数据的重要性,即我们需要存储和警报的多维数据。一旦我们设法存储和分析数据,稀疏的数据集就成了问题;在一些国家,某些支付方式几乎不被使用。我们花了几个月的时间进行调整,使我们的警报达到我们想要的水平。然而,一旦我们做到了这一点,我们检测到区域性支付提供商的故障的速度就和支付提供商本身一样快,有时甚至比他们更快。
进一步阅读。
- 移动分析指南来自Amplitude
- M3:Prometheus的开源、大规模度量平台 来自Uber
- Uber提供的实时异常检测
- When Metrics Lie 来自Pinterest工程经理Ryan Cooke
- 使用ThirdEye智能警报监测业务绩效数据 来自LinkedIn
- 开始使用行为分析 来自Amplitude
- Android中的非功能指标监控 来自Halodoc
- 提供准确的iOS分析数据 来自Tokopedia engineering
- 推动数据驱动的决策 来自 Spotify
- App Store中增长最快的游戏是如何留住用户的 来自QuizUp
34. 流动待命
一旦你有了移动警报,即使这些警报只是为了报告事故,有一个移动待命的轮换将成为一个敏感的话题。当警报响起时,它需要呼唤一个知道如何缓解这种中断的人。明显的选择是一个拥有所有必要背景的移动工程师。
如果你有一个足够大的移动团队,有一个只负责移动的待命人员可能不是一个问题。在Uber,我们在支付团队中沿用了几年的这种设置。主要和次要的值班人员总是一对iOS和Android工程师,或熟悉这两个代码库的工程师。
保持一个(非常)小的手机轮流值班是许多团队的最终结果。这是因为,除了一些崩溃报告之外,移动端待命几乎总是很安静。因此,即使是小规模的轮换,被轮换也不应该意味着有太大的压力。不过,我对任何少于五名工程师的轮值工作始终保持警惕。如果事情发生了,但待命的人不在身边,会发生什么?
轮流值班只是处理故障的第一步。还需要有一个明确的事件响应程序,待命的工程师需要接受相关的培训,这样他们就知道在接到呼叫时应该怎么做。
常见的事件响应首先是由待命的工程师评估问题的严重性和受影响的客户数量。接下来,他们决定是否需要将事件升级。
如果是这样,他们可能会让其他人参与进来,并决定由谁来领导响应。对于较大的事件,他们可能需要分工合作,谁来领导与其他人的电话会议,谁来处理与利益相关者的沟通,谁来调查问题的某些部分。在一个待命团队中建立良好的事件响应能力需要时间和实践。如果你想增加你的响应时间,最大限度地减少缓解时间和对客户的影响,这是你需要做出的投资。
组织需要从事件中学习,以确保应用程序不会因为相同的根本原因而出现两次故障。拥有一个事后总结的过程是这些学习的关键。
事后总结是一个捕捉事件细节的工具,例如事件的背景、时间线、业务影响、根本原因和纠正措施。事后总结应该包括改进系统和流程的后续行动,这样就可以防止类似的故障发生,或者至少在下次更快发现和缓解。阅读其他团队的事后总结是在整个公司内分享经验的好方法。
在产品团队中,如果你没有足够的移动工程师来保证仅有一个移动端待命,那么合并后端和移动端待命将变得很有吸引力。然而,你可能会发现,后端工程师可能不会对这个想法感到兴奋,而移动工程师则更不会。原因是什么?他们都不确定当警报出现时该怎么做。
一个好的随叫随到是指工程师不需要过多地考虑当警报出现时该怎么做。应该有几个简单的步骤,最好这些步骤是值班运行手册的一部分。
你的值班人员是否有针对大多数警报的运行手册?它们是否简单到可以遵循?
如果答案是肯定的,那么恭喜你!你已经准备好将移动电话和电话合并。你已经准备好合并移动和后端待命。随着时间的推移,人们将减少待命的频率,移动和后端工程师都将更好地理解产品。
如果你没有足够的运行手册,或者它们不够好;为什么不呢?没有好的运行手册意味着团队更依赖有经验的工程师来帮助待命,因为他们被认为是 "脑子里都有东西"。新加入的人需要更长的时间来进行待命。同样重要的是,移动工程师不能为后端警报待命,反之亦然。那么,该怎么办呢?是继续保持紧张的待命状态,还是雇佣更多的人,还是把运行簿整理好?
作为进一步的阅读,我建议通过谷歌的网站可靠性工作手册中的待命章节。
35. 先进的代码质量检查
检测代码问题的反馈周期越短,工程师和团队的工作效率就越高。虽然在代码审查时获得对你的代码的反馈是很好的,但如果能获得即时反馈,甚至在你将代码提交给代码审查之前就获得反馈,岂不是更好?
有效率的团队在早期就把先进的代码检查基础设施放在,正是为了帮助对容易发现的代码质量问题进行快速反馈。提示和静态分析是两种最常见的方法,而且经常一起使用。
代码格式化是代码质量检查的最常见的使用案例之一。代码格式化器将在创建拉动请求之前运行,确保所有供审查的代码都遵循团队同意并在格式化器中定义的风格指南。流行的代码格式化器包括SwiftFormat或Google-java-format。
提示是静态分析的一个特例;扫描代码的潜在错误,不仅仅是代码格式化。这可以是琐碎的检查,如确保缩进正确,通过强制执行命名模式,一直到更高级的规则,如按字母顺序声明的变量。流行的提示工具包括。
iOS:Clang分析器--与Xcode一起发货--和SwiftLint。
Android:lint工具--与Android Studio一起发货--和用于Kotlin的ktlint。
随着团队的成长,开始在整个代码库中执行更复杂的规则是有意义的。这些规则可以是强制执行整个团队的编码模式,比如限制强制值,或者强制执行架构 "规则",比如视图不允许直接调用交互器。
在Uber,我们看到了将架构定义作为 "可强制执行 "的规则的很多价值。为此,团队建立并开源了NEAL(Not Exactly A Linter),用于更高级的模式检测,在iOS和Android中使用。
林特疲劳(Lint fatigue) 是一个在大型项目中开始出现的问题,或者说是一个有很多林特规则的项目。随着
错误或警告堆积如山,工程师们往往开始忽视它们。一个很好的例子是,当不清楚如何迁移到一个新的API实现时,就会忽略废弃的警告。
处理lint疲劳的一个常见方法是让linting错误破坏构建,除了修复它们别无选择。这有点烦人,但很有效。另一种方法是建立工具来自动修复linting错误。这是Instagram采取的方法;他们使用自动重构来教育工程师关于编码的最佳实践。
静态分析是对代码进行自动检查,寻找潜在问题和错误的更通用的短语。移动静态分析工具通常有助于检测比简单的lint规则所能捕获的更复杂的用例。
大多数静态分析工具是为一种语言编写的--Swift、Kotlin、Objective C或Java--并检测常见的编程问题,如未使用的变量、空的catch块、可能的空值,以及其他。在上面列出的提示工具的基础上,你可以考虑的静态分析工具有。
- Swift、Kotlin、Objective-C和Java。SonarQube和SonarCloud(高级静态分析),NEAL,Infer(Java,Objective-C)
- Swift。Clang analyzer (与Xcode一起提供), SwiftLint, SwiftInfo, Tailor, SwiftFormat
- Kotlin。ktlint (一个 "无决定权 "的linter), detekt (代码气味和复杂性报告)
- Objective-C。Clang analyzer (与Xcode一起提供), OCLint
- Java。lint(与Android Studio一起发布),NullAway(基于注释的无效检查),FlowDroid(数据流分析),CogniCrypt(安全密码学集成检查)PMD(编程错误检测器),Checkstyle
- 也请看这个每种语言的静态分析工具库
使用提示和静态分析工具的好处是可以得到更快速的反馈,代码审查员不需要检查常见的代码问题。有了这些工具的强制执行,代码质量通常会保持得更高。当使用先进的工具时,静态分析可以通过提前检测边缘情况而使应用程序更加稳定和安全。一个增加稳定性的好例子是使用一个工具来防止由于空对象而导致的运行时崩溃,并通过分析代码,在编译时做到这一点。
这些工具的缺点是整合它们所需的时间和它们带来的额外维护。你需要决定使用哪种工具,并将它们添加到你的构建设置中,包括本地构建和CI/CD设置。一旦到位,你可能需要保持规则的更新,每隔一段时间,更新工具的版本以支持你可能需要的新功能。
你选择的工具越复杂,这种维护可能就越多。在Uber,我们设置了广泛的linting和静态分析检查。在我看来,这样的结果是值得增加努力的。然而,我对建立我们所做的那种定制工具感到犹豫不决,而会使用一个足够好的工具来完成这个工作,它可以用很少的精力来设置。
代码覆盖率--检查你的代码中哪些部分通过单元测试或其他自动化测试进行了测试--是另一个帮助提高质量的工具。对于iOS,Xcode有内置的代码覆盖率报告。对于Android,Jacoco是一个常用的Java和Kotlin的覆盖率报告工具。一些供应商也提供了代码覆盖解决方案。通过将代码覆盖率与您的开发工作流程和CI设置相结合,您可以。
- 可视化每个变化的覆盖率。这可以使工程师和代码审查员很容易验证新的业务逻辑是否已被测试。
- 如果团队同意这样的方法,可以帮助执行最低代码覆盖率政策。
- 显示代码覆盖率随时间变化的趋势。代码覆盖率的变化是否与应用程序的中断或其他问题有任何关联?你将有数据来回答这个问题。
- 识别覆盖率低的区域,以及在哪些地方增加测试可以帮助提高正确性和可维护性,并使在这些领域进行修改的工程师更有信心。
进一步阅读。
- 静态分析的规模 来自Instagram
- Kotlin linting with ktlint from Pinterest
- iOS 贷款工具 来自 Pinterest
- iOS。使用SwiftLint的持续代码检查 & SwiftLint的使用
- Android。Android lint overview & Android lint framework - an introduction
36. 合规性、隐私和安全
你的应用程序和你的开发过程很有可能需要遵守某些合规和隐私准则。合规要求对每个应用程序来说都是独一无二的。在本章中,我们将介绍常见的要求。
大多数大型移动工程团队与合规团队合作,确定他们需要遵守哪些法规、流程和准则。一些公司有内部的合规性、隐私和安全团队,而其他公司则雇用外部顾问。违反法规的代价是很高的,无论是在声誉上还是在经济上,你要确保你的公司认真对待这个领域。
PII(个人身份信息) 不应该被任何人接触到,除了那些应该接触这些细节的人。任何移动工程师、客户支持人员或在公司工作的人都不应该能够访问这些信息。
GDPR(通用数据保护条例) 是欧盟的一项重要法规,它进一步扩大了PII的范围。PII数据只有在有合法目的的情况下才能被存储和处理。
特定行业的合规准则可能适用于你在某些行业的应用程序。一个非详尽的清单包括。
- 在处理信用卡信息时,PCI DSS(支付卡行业数据安全标准)合规。
- HIPAA(健康保险可携性和责任法案)和/或ISO/IEC 27001,当处理与医疗保健有关的数据信息时。
- FERPA(家庭教育权利和隐私法),用于处理美国的学生或教育信息。
- FCRA(公平信用报告法),适用于与消费者报告机构有关的应用,如信用公司、医疗信息公司或租户筛选。
- 在与美国联邦机构合作时,第508条合规性测试,确保残疾人可以访问他们的电子信息技术(EIT)。
- 当为欧盟国家的政府开发时,应遵循欧洲无障碍法准则。
- 可能适用于你的应用程序的个别国家的隐私法。
对于移动工程,有几个领域将影响几乎所有的组织,除了那些在欧盟没有用户的组织。
在手机上记录数据并将其发送到后端,是你应该更仔细考虑的一个领域。
- 在没有端到端加密的情况下记录PII数据可能会招致数据泄露。
- 争取不记录PII数据,或者在日志中匿名化这些信息,将其变成非PII数据。
- 为记录什么、何时和如何记录提供指导,包括关于PII数据的部分。
- 审计日志,以确保它们符合你需要遵守的法规。
- 错误报告的截图不应包含PII数据。你可能需要做额外的步骤来确保这一点,诸如信用卡号码和其他PII信息不会在票务系统中,或在客户支持代理处流通。
- 定期审查哪些数据被记录以及如何记录,以确保没有PII信息以非安全的方式被存储。
审计你的应用程序的各个部分是否符合GDPR和PII。
- 第三方SDK。 这些SDK的默认配置往往可能不符合GDPR的要求。你可能需要与他们的供应商合作,在某些情况下,停止使用其中的一些,以保持合规。
- 移动应用程序的工作流程可能需要更新,以确保应用程序保持符合GDPR的要求。这可能包括要求活动许可的额外步骤,并可能意味着添加额外的信息屏幕。
- 移动网络流量值得使用mitmproxy、Charles或类似的其他工具进行监控,以查看应用程序通过网络发送的数据。你可能会发现从你的代码或SDK代码中发送的PII数据,你需要解决这个问题。
培训一些工程师了解隐私法对编码和运营的影响可能是一项明智的投资。这样一来,你就能在内部带来一些这方面的知识,而不是依赖外部顾问。如果你的组织足够大,有内部专家,你可能仍然要考虑提名合规/隐私/安全冠军,以更好地扩展这些知识。这就是我们在Uber所做的,它有助于在开发过程中更早地发现潜在的问题。
拥有一个合规的开发流程和数据存储设置不在本书的范围之内。为了确保你的开发过程,以及你的应用程序和存储的数据都是合规的,你要依靠安全、法律和合规专家。
为了让大家了解这样一个过程需要多少努力,在Uber,我们花了几个月的时间来绘制流程,进行流程和工具的改变,然后在我们准备启动GDPR时对这些进行审计。我们必须做的大量工作和我们所做的变化的规模,使这个项目成为公司最大的任务之一。
你越早执行彻底的隐私和合规性审查,就越好。一旦你有了正确的流程,保持合规性就会少走很多弯路。
安全的移动开发是一个不断发展的话题。 虽然原生的iOS和Android移动应用程序需要担心的安全挑战较少,但绘制潜在的漏洞并对工程师进行安全移动应用程序开发的培训是一个好主意。
在CI/CD层面上运行安全检查意味着你可以扫描代码中的硬编码凭证或危险功能的使用。你可以通过SonarCloud等工具来获得这种方法的开箱即用。Skyscanner在SonarQube和他们的Whispers静态代码分析工具的基础上建立了SonarSecrets插件,采取了类似的方法。还有其他供应商的解决方案可以帮助进行安全或渗透测试。
在Uber,我们有一个单独的移动安全培训课程,包括OWASP移动安全风险和MASVS(移动应用安全验证标准)。
关于合规性和隐私的进一步阅读。
- 欧盟网络安全机构的移动应用的隐私和数据保护
- 移动应用开发的隐私设计指南 来自IAPP
- 关于GDPR,软件工程师应该知道些什么 来自InfoQ
- 开发符合GDPR的应用程序的15个步骤 来自TechBeacon
- 美国国土安全局的DHS 508条款合规性测试
为了安全。
- 移动应用安全验证标准 来自OWASP
- Whispers:高级秘密检测 来自Skyscanner
- Sonar Secrets: secrets detection on top of SonarQube from Skyscanner
- 通过采用移动安全分析推动安全的软件开发生命周期 来自Halodoc
- iOS和Android移动应用安全最佳实践 来自Quickbird Studios
- OWASP移动10大安全风险 来自OWASP
- 安卓隐私和安全 来自谷歌
37. 客户端数据迁移。
对于在本地存储数据的移动应用程序,应用程序中的数据模式变化带来了一系列新的迁移挑战。
这是一个处理数据库的后端和厚客户端工程师都会非常熟悉的领域。同时,这个问题的空间很少存在于Web应用中,因为Web应用在浏览器中几乎不存储离线数据,它们通常也不被设计为支持离线场景。
需要将设备上的数据从一种格式迁移到另一种格式,是很困难的。 数据模式变化越大,这样的迁移就越费劲。编写一个迁移函数是这个挑战中较小的部分。其他的挑战包括。
- 用真实的生产数据测试迁移,这些数据最好是代表所谓的大用户,他们在设备上有一些最复杂的数据存储类型。
- 测试从各种旧版本到新版本的升级。你不能假设人们会从上一个版本更新应用程序。假设这不是第一次这样的数据迁移,你可能需要支持少量的用户,他们甚至落后于一次这样的迁移。
- 客户端的日志/警报数据迁移的细节,因为后台日志对设备上的数据迁移可能没有什么用处。
- 在数据迁移可能失败的情况下为客户提供支持**,并制定备份计划,以防这些用户遇到重大的功能退步。
模式迁移的一个主要挑战是,如果新版本的应用程序有一个错误,破坏了新的模式,会发生什么?应用程序的用户可能会被困在一个无效的状态中,他们唯一可以恢复的选择是擦除应用程序,从一个干净的状态开始,因为在客户端没有回滚选项。
仔细考虑在数据模式改变的情况下,你是否可以让后端成为真相的来源。与其建立一个容易出错、难以调试、难以支持的设备上模式迁移,你是否可以建立对从后端重新下载数据的支持--或者将其作为未来的一个选项?
38. 强制升级
在2015年,很少有应用程序设置了强制升级机制。在2021年,大多数成熟的应用程序都已将其落实到位,认识到需要强制退掉应用程序的旧版本。
实施强制升级的理由是很多的。
- 退役后端API版本。 如果没有到位的强制升级,后端API就不能退役。
- 测试的成本。旧的应用程序版本仍然需要测试,特别是针对后端变化。
- 客户支持成本。 一个应用程序的版本越多,客户支持就越复杂--成本也越高。即使修复了一个已知的错误,用户仍然可以向客户支持报告同样的问题,因为他们使用的是旧版本。
- 向后兼容的成本。后台团队将不得不更谨慎地行动,最终,更缓慢地确保旧版应用程序的向后兼容性。
- 需要修复的严重错误。可能会有一些需要立即修复的bug,并立即推出修复方案。如果没有一个强制升级的解决方案,就不可能确保所有客户都得到修复。
- 漏洞。旧的应用程序版本可能暴露在安全或其他业务漏洞中。如果没有办法强迫用户停止使用这些版本,就无法修补漏洞。
强制升级实施的例子包括。
- Snapchat、Facebook Messenger和Whatsapp都有一个滚动窗口,不允许用户在使用太落后的版本。
- 游戏经常采用这种策略。当一个新的升级版本推出时,玩家通常不允许在不升级的情况下继续使用。
- 银行应用程序通常采用这种方法。Monzo既支持强制升级,也支持推荐升级。
- Just Eat(英国的一个食品配送服务)同时支持可跳过和强制升级。他们的目标是按需或用滚动窗口。滚动窗口可以被远程配置。该公司从2013年起就开始实施强制升级。
- ITV Hub(英国顶级应用之一)有一个 "软 "杀毒开关(要求用户升级)和一个 "硬 "杀毒开关,即强制升级。杀死开关可以根据操作系统版本、应用程序版本、手机制造商和其他目标机制来推出。
- Skyscanner(航空旅行)使用滚动窗口升级方法。
- Tresorit(加密的在线存储)从应用程序的第一个公开版本开始就建立了强制升级。在密码学中,能够切换到更强的算法,并且不允许在宽限期后出现弱的回退,这一点至关重要。
- Halodoc(医疗保健)实现了灵活和即时的应用程序更新的混合。
可以说,所有成熟的移动应用确实都有一些强制升级的概念,而且许多应用从第一天起就有这种概念。
强制升级的缺陷是你需要比你计划使用它时更早地建立它。如果没有强制升级的信息传递机制,你就不能安全地退掉应用程序的版本。
这张图显示了第一次开发应用程序所面临的问题。
强制升级的挑战:你应该在需要它之前就建立好它。
一旦强制升级解决方案到位,你确实需要在生产中测试它,以确保它的工作。一些公司犯了这样的错误:建立了强制升级支持,但后来几年都没有使用它。当到了强制升级的时候,他们对它是否真的能工作没有信心。
在安卓系统上,谷歌提供应用内更新从安卓5.0开始,有一个易于使用的API。然而,对于旧的安卓版本或iOS,你目前只能采用自制的解决方案。
如何支持旧的手机型号是你在使用强制升级时遇到的一个痛点。虽然许多企业可以决定不支持旧手机,但情况并非总是如此。一个例子是货运应用Convoy,一些运营商的手机,使用JS Core的较新应用版本甚至无法使用。
如何支持这些旧机型的决定是你需要根据你的业务使用情况来决定的。一些应用程序最终会支持旧的应用程序版本多年,以保持这些客户。其他应用程序在计算了他们从一个子集的用户那里得到的商业价值后,划定了一条界限,然后沟通停止对这些客户的某些操作系统版本的支持。
强制升级不仅仅是一种工具:它是一种策略。当你构建工具时,确保与企业合作--产品经理和企业利益相关者--将强制升级战略落实到位。如果你围绕着何时和如何强制升级的边缘案例,这个过程将从一个挑战变成一个常规工作。
39. 应用程序的大小
应用程序的大小有多重要?应用程序越大,用户就越不可能下载它,当他们的手机存储空间填满时,他们就越有可能删除它。
二进制大小很重要,因为它影响下载。二进制大小越小,用户就越有可能下载该应用。2017年,谷歌在文章中报告了一些有趣的发现缩小APK,增加安装量:
- APK的大小每增加6MB,安装转换率就会减少1%。
- 10MB大小的APK的下载完成率比100MB的高30%。
- 新兴市场中70%的人在下载应用前会考虑应用的大小。
对于iOS来说,没有类似的全面报告,--但应用大小和安装率之间肯定有一些关联。例如,Segment团队在2016年将应用的大小从3MB人为地夸大到150MB时,观察到应用安装率下降了66%。
对于安卓来说,保持二进制文件尽可能的小是特别重要的。一些设备的存储空间很小,在某些市场上,人们根据一个应用程序所占用的空间来决定是否下载它。
减少安卓应用程序大小的最直接的方法之一是将它们打包成应用程序捆绑。这个选项从2018年底开始就有了。根据谷歌的数据,与通用APK打包相比,平均应用程序的大小减少了35%。
对于iOS,最重要的尺寸相关限制是空中下载限制为200MB。大于此的应用程序只能通过wifi连接下载或更新。在Uber,我们人为地增加了一个发布周期的应用程序的大小,以衡量超过OTA限制的影响。Uber发现安装量大幅下降,可能会对业务产生重大影响。前Uber工程经理Chris Brauchli在Uber应用的二进制大小问题一文中进行了深入探讨。
创建一个单独的、尺寸非常小的 "精简版 "应用程序是Uber、Facebook和谷歌等公司在新兴市场的安卓系统中采取的策略。在Uber,研究表明,在几个市场上,潜在客户没有下载相对较大的应用程序。这导致了建立和推出Uber Lite:一个更有限的Uber应用,但它的体积只有5MB,为低带宽使用而优化。Facebook Lite和Google Go是其他以类似目标建立的应用。
为了使应用程序保持在5MB以下并减少数据使用,该团队进行了一些优化。
- 默认关闭地图,以减少数据使用。
- 删除增加了过大开销的框架。例如,Uber Lite不使用RIBs。
- 使用矢量图像格式,而不是PNG的资源。
- 服务器驱动的客户端,后端做了很多协调工作,以减少网络有效载荷。
- 通过将请求和响应大小保持在1个MTU(最大传输单位),使用单个TCP连接。
请注意,应用程序的大小和带宽使用的减少经常是有代价的。在Uber Lite的案例中,这些权衡是。
- 更多的工程努力来维护一个小版本的应用程序。必须建立一个新的团队来建立和维护这个应用程序。
- 后台团队需要付出更多努力,以支持低带宽的使用情况。网络调用必须进行优化,以适应1个MTU的要求,并对一些流量进行彻底的重新思考。
- 为客户提供的功能减少,这可能导致较低的转换率或每个客户的收入减少。
应用程序二进制大小的所有权往往是成长中的组织要解决的最棘手的问题。随着多个团队在应用程序上工作,每个人都倾向于专注于构建自己的功能。一旦有了一个移动平台团队,这个团队通常会负责监控应用程序的大小,并想出合理的方法来减少它。
静态资产悄悄进入二进制文件是许多团队参与的大规模应用中经常出现的问题。你会惊讶于有多少应用程序嵌入了一个6MB的原始JPEG文件,这个文件是为A/B实验而添加的,然后工程师们在实验后忘记了删除它。有了应用程序大小的监控,可以帮助你抓住这些类型的疏忽。应用程序大小监控可以防止这些不必要的资产进入生产,并在大量的设备上浪费空间。
如果你的公司不注意二进制大小,可能是时候改变这种做法了。即使它不可见,大的应用程序大小也会对安装和使用指标产生一些影响。这取决于你是否能发现这种影响有多大,以及你想花多少时间和精力来优化应用程序的大小。
安装的大小也很重要,但很少有团队注意跟踪它。虽然一个应用程序可能有一个足够小的二进制大小,但这个大小可以通过缓存图片、文件和其他数据等东西开始增加。如果应用程序增长过大,用户可能会卸载它并流失。
Google Play支持开发者通过Google Play控制台查看安装尺寸,你应该定期监测这一数据。苹果不支持这样做,这意味着对于iOS,你将不得不手动检查你的缓存方式和时间,并在本地测试你的应用程序的大小如何变化。
进一步阅读。
- 在iOS上通过应用瘦身减少你的应用大小 来自苹果公司
- 谷歌提供的缩小、混淆和优化你的安卓应用
- 安卓应用包是打包你的应用的一种更好的方式 来自谷歌
- 二进制大小的困扰 来自Uber
- 设计一个低于5兆字节的Uber应用 来自Uber
- 应用程序的大小问题 来自Farfetch
- 移动应用程序的大小对下载的影响 来自Twilio Segment
- 你的APK大小如何影响安装转换率 来自谷歌
- 将Messenger的iOS代码库从170万行减少到36万行 from Facebook
- 将我们的安卓应用尺寸缩小30% 来自卫报
- 将安卓应用的大小减少65% 来自PregBuddy
- 应用瘦身、比特码、切片: 一个iOS教程
章节摘要
由Bitrise的Moataz Nabil撰写,作为本书的补充。
这一章涵盖了世界一流的应用程序为数百万客户建立最佳质量的应用程序所要解决的大部分问题。如果团队正计划试验变化或添加新功能,我们首先应该考虑的是功能标志和推出A/B测试版本来控制变化。为了能够分析实验结果,我们可以实施内部工具或整合第三方工具,如Firebase Remote Config、LaunchDarkly等,同时要记得跟踪实验,确保它们不会相互影响。
功能旗帜是很好的。作为一个团队,我们可以决定建立自己的自定义功能标志系统或使用供应商的系统,但随着时间的推移,功能标志的缺点会变得很明显,因为有时它们是相互依赖的。为了解决这个问题,团队需要绘制出功能标志的依赖关系,作为其推广计划的一部分。另一个需要避免的问题是功能标志在代码库中越来越陈旧。在一个特性标志被完全推出后,我们可以创建一个自动拉动请求,删除死的执行路径和标志。
这些并不是构建世界级应用程序时可能出现的唯一问题。性能问题也可能是大型应用的常见瓶颈,原因有很多,比如膨胀的应用启动时间。
太多的并行网络调用,网络性能问题,电池消耗率,应用程序没有响应,动画等等。为了解决这些问题,团队应该开始考虑性能监测工具,以便能够在早期阶段解决这些问题。
此外,对移动应用程序的监测和警报应该比仅仅监测崩溃更深入。成熟的团队可以检测到关键流程中出现的倒退,获得警报,并在记录和分析数据的内部或第三方分析工具的帮助下开始调查根本原因。监控对于管理我们应用程序内部的业务事件也很有用,首先定义关键事件和路径,然后用移动警报解决方案实施跨平台监控,以获得崩溃报告和业务事件变化。
大多数大型团队一旦有了移动警报,就会有待命流程和轮换,即使这些警报只是为了崩溃报告。当警报响起时,它需要呼唤一个知道如何缓解这种中断的人:通常,一个拥有所有必要背景的移动工程师。为了确保应用程序不会因为同样的错误而中断两次,先进的团队也有一个事后总结的过程来讨论经验教训。
我们也不应该忽视代码质量检查。这是大规模团队的常见做法之一:他们检查代码格式,提示问题,并对代码进行静态分析以发现任何潜在的问题和错误。使用linting和静态分析工具的主要优点是获得更快速的反馈,所以代码审查员不需要检查常见的代码问题。代码覆盖率,检查代码的哪些部分通过单元测试进行了测试,以及其他自动化测试,对于提高质量至关重要。
由于违反合规性的成本很高,而且会损害公司的声誉,所以移动团队必须认真对待这一领域。大多数较大的移动工程团队与合规团队合作,确定他们需要遵守哪些法规、流程和准则。加密所有个人数据并告知用户,通过HTTPS强制执行安全通信,确保会话和cookies过期并在注销后被销毁,将日志存储在安全的地方,最好是加密的,这些也是至关重要的。为了确保你满足所需的规定,创建明确的条款和条件,确保用户阅读它们,并在你的CI/CD管道中添加安全检查。
由于退役的后端API版本、测试成本、客户支持成本、向后兼容的成本、需要修复的严重错误以及其他漏洞,强制升级对于移动团队来说总是一个问题。不仅要决定使用哪种工具,而且要决定遵循哪种策略。当你构建工具时,确保与产品经理和利益相关者合作,将强制升级策略落实到位。如果你已经围绕何时和如何强制升级的边缘案例,这个过程将从一个挑战变成一个常规的工作。
最后,应用程序的大小也会成为一个问题:应用程序越大,用户就越不可能下载它,当他们的手机存储空间填满时,就越有可能删除它。出于这个原因,大多数大公司,如Uber、Facebook和谷歌,都会创建一个较小的、"精简 "版的应用程序。监测已安装的应用程序有助于团队看到二进制大小的增加,由于缓存了图像、文件和其他数据等东西,避免应用程序增长过大,导致更高的流失率。