Slack的移动开发经验谈:如何让开发者随时顺畅工作

译者|核子可乐

策划|丁晓昀

在 Slack,移动开发者体验团队(DevXp)的目标是让开发者能够自信发布代码,同时享受愉快且高效的工程体验。我们使用指标和多种调查来衡量生产力 / 开发者体验,包括开发者情绪、持续集成(CI)稳定性、合并时间(TTM)和测试失败率等。

一切的起点

部分移动工程师早就意识到,受雇编写本机移动代码的工程师可能并不一定具备特定技术领域内的专业知识。他们意识到,如果能够为所有移动工程师提供更好的开发体验,不仅将有助于提高工作效率、同时也能加快代码发布速度、提升代码质量、改善客户满意度。为此,他们组建了一支临时团队以解决最常见的开发痛点。如今,这支移动开发者体验团队已经由 2017 年时的三人扩大到八人。在这五年的探索历程中,我们主要关注以下领域:

本地开发体验和 IDE 可用性。

持续扩大的代码库规模。确保代码库中需要关注的问题始终可见。

持续集成的可用性和可扩展性。

对基础设施和脆弱性的自动化测试。

保持主干活力——确保最新的 main 始终可构建且可交付。

缺少移动开发者体验团队的负面影响

移动工程师们通常会在本地计算机上创建分支,并将代码提交至 GitHuyb 以启动功能。在准备就绪之后,他们会创建 pull request 并将其提交至审查员。当 pull request 开启或后续提交被添加至分支后,将启动以下 CI 作业:

用于构建工件的作业;

运行测试的作业;

运行静态分析的作业。

在审查员核准了 pull reuqest 并完成所有 CI 检查之后,工程师就可以在主分支中合并 pull request。下图所示,为开发者流程及各具体环节的可视化示意。

下表整理的是开发者常见痛点的粗略成本估算,以及随着团队成长,企业因未解决这些痛点而付出的代价:

虽然开发者也能通过学习解决其中部分问题,但随着团队规模的扩大,耗费的时间和产生的成本将逐渐失控。如果能有一支专注于解决这些问题、探索开发高效方法的专项团队,将确保开发者能够始终将注意力集中在核心项目身上。

具体方法

我们的团队与移动工程团队合作,使用以下方法梳理了开发者面临的痛点。

听取客户意见,与他们携手工作。我们与移动工程师合作,参与功能研究并观察他们遇到的挑战。

调查开发者感受。我们每个季度会对移动工程师进行一次调查,跟踪移动开发的总净推荐值(NPS)。

总结开发者痛点。我们对反馈意见加以提炼,整理成可供团队集中解决的具体任务。

收集指标。在着手解决痛点之前,先要设计出一套衡量指标,以确保所部署的解决方案能够实际解决问题、特别是方案部署后到底产生了怎样的影响。我们提出的指标能够跟踪开发者遇到的具体问题,并将其呈现在仪表板之上。如此一来,我们就能关注指标随时间推移的变化情况。

针对开发者痛点建立改善性实验。我们会咨询其他规模相仿的企业,或者提出独特的解决方案来思考问题的解决办法。

考虑使用第三方工具。我们会通过评估确定,到底该使用现成解决方案、还是自行构建原研解决方案。

重复上述过程。在发布解决方案之后,我们会持续查看指标以确保其朝着正确方向前进;一切无误后,我们才会进入下一个问题领域。

开发者痛点

我们下面按严重程度具体探讨部分开发者痛点,并分享移动开发者体验团队如何解决这些问题。对于每个痛点,我们将从开发者的亲口表述切入,之后概括我们采取的处理步骤。

CI 测试作业耗时过长

当开发者需要等待很长时间才能对 pull request 进行测试时,他们往往会转而处理其他的任务,这样很容易忘记之前 pull request 的编写目的、场景等上下文。这样当测试结果返回时,他们又得再次放下手里的活回到之前的工作。这种上下文切换会严重影响开发者的工作效率。下面是我们 2018 年季度移动工程调查中收得的两段反馈。

能不能让 CI 更快点!我觉得大家都有这个想法,要是能实现就太棒了!

Jenkins 的构建速度太慢,如果能把时间缩短点就太好了。

从最早的 1 名开发者到后来的 10 名,再到如今成百上千的测试需求,面向 iOS 和 Xcodebuild 和面向 Android 的 Firebase Test Lab 也纷纷上马,令整个测试体系越来越复杂。

经过多年发展,我们的测试时长开始朝着一个小时逼近。这样的结果当然不可接受,我们考虑的解决方案之一就是向测试套件引入并行化机制。我们可以将测试作业拆分开、并行运行,而不像过去那样串行执行。下面我们分 iOS 和 Android 两个平台探讨这个问题的解决办法。

iOS

我们考虑过自行编写工具,但后来发现了一款名叫 Bluepill 的工具。作为 LinkedIn 的开源成果,Bluepill 的底层用的是 Xcodebuild,只是增加了分片和并行测试的能力。通过将 Bluepill 集成进入,我们的总测试执行时间被缩短到了 20 分钟左右。

但在用了几年 Bluepill 之后,我们的单元测试作业再次延长到近 50 分钟。很明显,我们已经没法单靠并行化来降低 TTM 了,Slack iOS 工程师们引入的更多测试套件需要更精巧的瘦身思路。

转向现代构建系统,缩短 CI 作业时长

我们的下一项策略,是为测试套件编写一个缓存层,目标就是只运行特定 pull request 上必须运行的测试,并从缓存中返回其余测试结果。问题是,Xcodebuild 本身并不支持缓存。为了解决问题,我们需要转向其他构建系统,答案就是 Bazel。我们在 CI 设备上使用 Bazel 的磁盘缓存,这样来自不同 pull request 的构建就都能重用来自其他用户的构建输出,而不必在本地反复构建每个新输出。

除了 Bazel 磁盘缓存之外,我们还用到了 bazel-diff 工具。该工具使我们能够确定两个 Git 修订版之间受目标影响的确切范围集。我们会对主分支提示和开发者分支上的最新提交进行比较。在获得影响目标列表之后,接下来就是具体执行目标测试。

借助 Bazel 构建系统和 bazel-diff,我们成功将 TTM 缩短至平均 9 分钟,最短 TTM 仅为 4.5 分钟。如此一来,开发人员就能快速获得关于其 pull request 的反馈、加快协作速度并调试自己的功能。

Android

最初,Android 这边的 TTM 在 50 分钟左右,主要原因是 Firebase Test Lab(FTL)不支持测试分片。我们在 FTL 上构建了名为 Fuel 的内部测试分片程序,能够将测试拆分成多个分片,再调用 FTL API 并行运行各个分片。这种方式让 TTM 从原本的 50 多分钟缩短到 20 分钟以内。下图为相关流程概要:

之后的两年半里,我们一直在使用 Fuel,随后又转向名为 Flank 的开源测试分片程序。直到今天,我们仍在使用 Flank 处理 Android 功能和端到端 UI 测试。

测试相关故障

每当有稳定性或其他测试故障发生时,pull request 检查都有可能受到影响。这时候,开发者只能暂时放下手头的工作,这种感觉绝对不爽。下面,我们来看看导致不相关 pull request 检查失败的几种常见原因,还有我们的解决思路。

自动化框架不稳定

在 2015 年到 2017 年初期间,我们用过名叫 Calabash 的 UI 交互测试框架,并将其逻辑打包进了 Cucumber 中以降低查看难度。Calabash 是一套“黑盒”式测试自动化框架,需要专门的自动化团队来编写和管理测试。我们发现,添加的测试越多、其运行稳定性就越差。当 pull request 测试失败时,开发者会联系自动化工程师、想了解为什么会出故障,尝试加以修复,然后祈祷下次运行的时候不会再因测试跑不通而引发构建失败。长此以往,反馈循环越来越长、TTM 也居高不下。

随着团队规模的增长,我们决定从 Calabash 转移至 Espresso,因为 Espresso 与 Android 操作系统紧密契合,而且同样是用本机语言(Java 或 Kotlin)编写而成。Espresso 之所以强大,是因为其能理解 Android 操作系统的内部工作原理,并可轻松与之交互。这样 Android 开发者也能用自己最熟悉的语言,轻松编写和修改测试。其具体优势包括:

有助于将测试责任从自动化专项团队转移给开发人员,允许他们根据需求修改代码的测试逻辑。

当我们从 Calabash 转向 Espresso 和 FTL 时,测试时长从最初的 350 分钟减少到了约 60 分钟。

测试稳定性差

2018 年初,开发者对测试的效果颇不满。下面来看当时开发者调查中的几条反馈:

测试稳定性影响很大。我们应该有更好的办法来跟踪问题,再不修复恐怕会惹出更大的麻烦。

测试稳定性太差,总是打断我的工作——应该有更精简的流程保证 PR 继续进行,而不是像现在这样直接打断合并。

有一段时间,我们主分支中高达 57% 的测试失败源自测试不稳定,而在开发 PR 中占的百分比还更高。近年来,我们花了一些时间分析测试的稳定性问题,并高潮构建了自动检测及抑制系统进行控制,以确保开发者体验及工作流程不受干扰。总之,现在我们已经将测试失败率从最高时的 57% 降低到了 4%。

CI 相关故障

多年以来,我们使用基于 Groovy 的.jenkinsfiles 为移动 CI 基础设施提供支持。虽然效果不错,但它也以自己的方式损害着开发者体验。下面来看影响最大的几个问题:

频繁停机

系统性能下降

无法获取 Git webhook,因此无法启动 PR CI 作业

作业失败时,无法更新 PR

难以调试因体验不佳引发的故障

在克服了测试稳定性差这一难题后,CI 停机时间成了对移动生产力影响最大的又一瓶颈。下面来看开发人员对 Jenkins 提出的抱怨:

应当在 jenkins CI 和 GitHub 间建立更可靠的桥梁。现在出了问题,GitHub 有时没有可以转到正确位置的链接。另外,有时 CI 虽然正常通过、但却未向 GH 告,所以 PR 还是会卡住,必须手动重建才能继续。

Jenkins 真让人头痛,能不能把烦人的 Blue Ocean Jenkins UI 给删喽?

Jenkins 太让人难受了。里面全是链接,我只关心哪里有问题,要点击什么按钮 / 链接来重试。除此之外的一切都是噪音。

在使用 Jenkins 六年多之后,我们决定转向 BuildKite,到目前其正常运行时间已经达到 99.96%。与 Webhook 相关的问题已经完全消失,用户体验非常简单,开发者无需引导即可灵活导航。这不仅改善了开发者体验,同时也减少了我们团队的负担。

迁移之后,CI 的稳定性提高 了 8%,从 87% 左右提升至 95%;此外合并时间则从约 34 分钟缩短至约 20 分钟,降低了 41%。

合并冲突

向 iOS Xcode 项目

添加新模块或文件时发生冲突

随着 Slack 的 iOS 工程师数量超过 20 人,Xcode 项目文件的签入开始成为新的难题。Xcode 项目以 XML 文件的形式存在,它直接定义了项目的所有目标、构建配置、预处理宏、scheme 等等。对于小团队来说,这个文件当然不难修改,直接提交至主分支也不会引起任何问题。但随着工程师数量的增加,文件修改引发冲突的可能性也在同步提升。

“我觉得最让人担心的就是 xcode 项目文件,其冲突很难解决而且极易 错。我不确定有没有解决这个痛点的最佳办法,毕竟新的代码文件还在不断加入。”

“我只能手动处理项目文件中的十几个冲突。这本身倒不是大问题,但在合并 PR 的时候,结果真的完全不可预料。”

在采用 Bazel 之后,我们又更进一步,根据 Bazel 的构建描述动态创建这个 YAML 文件。

向 main 执行多个并发合并,

有可能导致 main 瘫痪

截至目前,我们已经讨论了开发者在本机编码和开启 PR 时可能遇到的各种问题。那么当有多个开发人员同时向主分支发送 PR 时,又会发生什么?对于 Slack 这样的庞大团队,一天内会多次进行 main 合并。所以开发者等待合并的时间越长,发生合并冲突的可能性就越大。

合并冲突的增加开始对开发者的工作效率产生负面影响。这是因为在解决合并冲突之前,主分支会保持中断状态,导致所有生产操作全部暂停。有一次,合并冲突一天之内多次破坏主分支,于是开发者们开始呼吁建立请求合并队列机制。

我们一向主分支提交就 错。赶紧上合并队列。

我们对不同解决方案进行了综合考量,最终决定选择 Aiator 这款第三方工具,并将其与内部工具 Mergebot 结合起来。我们认为,构建和维护合并队列对我们来说工作量太大,最好的解决方案是引入一家专业的技术服务公司。选择 Aviator,开发者可以直接把自己的 PR 添加到队列中,而不必直接合并至主分支。在进入队列后,Aviator 会将主分支反过来合并至开发者分支,同时运行一切必需的检查。如果发现有 PR 会导致 main 出错,则合并队列会将其拒绝,再通过 Slack 通知开发人员。这样一套系统就有效避免了合并冲突的发生。

有了 Aviator,现在的情况好多了。唯一的痛点就是我只能通过 Aviator 合并 PR,但整个过程往往需要好几个小时。我感觉有点焦虑。

在采用之初,Aviator 本身还不够成熟,好在早期合作让我们与 Aviator 团队建立了密切联系。他们很重视并在努力解决开发者痛点,例如缩短向主分支合并 PR 的时间,并在 PR 因冲突而退出队列时提供失败 告。

检查 PR 进度 / 状态

下面来看我们在 2017 的开发者调查中收到的反馈:

PR 在分配、评论、批准时能提供及时的通 ,这个确实不错。但能不能在构建成功时(而不只是失败时)也提供通知呢?最好能把跟 PR 批准相关的情况都做成通知。

Mergebot 缩短了审查流程,也让开发者的日常工作更为顺畅。如此一来,每个开发者每天节约下 5 分钟,一年内就能给 100 人的开发者团队节约下 24 万美元的人力成本。

最近,GitHub 也推出了类似的功能,名叫“github scheduled reminder”。在启用之后,它会通过 Slack 通知向开发者更新 PR 动态。虽然它的表现也不错,但我们还是更爱老朋友 Mergebot——因为它不需要额外启用,而且在 Slack 上直接提供 PR 合并按钮。

总结

我们希望让 Slack 成为全球最佳软件开发环境,而达成这项目标的一种重要方式,就是投资创造良好的移动开发者体验。我们团队的使命是让开发者拥有顺畅的工作流程,轻松、愉快、高效地处理事务。下面来看一番改进之后,移动开发者们给出的积极回应:

DevXp 太棒了。感谢你们随时听取移动开发团队的反馈!有你们真好。

我们已经享受到了现代开发实践。Bazel 相当好用,感谢 DevXp 团队的辛勤工作和热情支持。

这些工具运作良好,代码模块化转型非常成功。DevXp 的响应很快、乐于助人,也一直在不断迭代和改进。

2023年第一季度,ArchSummit全球架构师峰会将落地北京海航万豪酒店。来自百度、京东、华为、腾讯、斗鱼、中国信通院等企业与学术界的技术专家,将就数字化业务架构、低代码实践、国产化替代方案、分布式架构等主题展开分享讨论。

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2022年11月13日
下一篇 2022年11月13日

相关推荐