

字节跳动移动研发工具链 - MBox
source link: https://mp.weixin.qq.com/s/OD2lYfA9tkdgEp4QGRtdog
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

字节跳动移动研发工具链 - MBox
老司机技术周报与得物技术联合举办了今年 9 月底的一次线下沙龙活动。来自抖音基础技术团队的李尧受邀为大家分享【字节跳动移动研发工具链 - MBox】,夏天基于这次分享视频为大家整理此文,感谢二位!阅读原文,获取 PPT!
讲师简介:李尧,字节跳动-抖音基础技术-效能工具研发专家,MBox 核心开发者
编辑简介:夏天,摸鱼周报联合编辑。希望大家支持 iOS摸鱼周报和 iOS成长指北,一起交流学习。
本文是基于原视频进行再创作,可能与原视频内容存在部分差异,请配合视频一起使用。
大家好,我是来自抖音基础技术团队的李尧。今天来和大家分享一下我们最近开源的的 CLI (Command Line Tool) 产品——MBox。
MBox 是由字节跳动抖音基础技术团队和 Client Infrastructure 团队结合移动端研发的现状与问题,基于移动端研发工具的相关实践经验,自研的一款面向移动端开发者的研发工具链产品。
本次分享主要包括以下三个方面的的内容
- 什么是工具链?为什么需要工具链以及应该如何选择工具链
- MBox 移动研发⼯具链做了什么即 MBox 是如何勾连整个研发流程的流转
- MBox 移动研发⼯具链能为我们带来什么,如何提升移动研发效能
参照维基百科-工具链[2]的定义:
A toolchain is a set of programming tools that is used to perform a complex software development task or to create a software product.
In general, the tools forming a toolchain are executed consecutively so the output or resulting environment state of each tool becomes the input or starting environment for the next one.
译文如下:
工具链是一组编程工具,通常是另一个计算机程序或一组相关程序。
通常,形成工具链的工具是连续执行的,因此每个工具的输出或结果环境状态成为下一个工具的输入或起始环境
简单来概括就是工具链是⼀组⽤来完成软件研发的⼯具集,将每个⼯具的输出会被作为下个⼯具的输⼊从而形成的链。
其实我们的软件研发流程就像一条流水线,对应软件开发的各个阶段,下图是我们简化后的双流模型:上面一条是我们的需求工作流,下面的那条是我们研发所关注的研发工作流
梳理研发流程,在每个流程中都需要开发者去完成一些工作。
而完成这些工作往往离不开工具的帮助,例如:我们需要用仓库管理工具下载代码,用 IDE 来编写代码,需要构建工具来完成构建工作;在提交代码前,我们需要用调试工具来进行调试,用格式化工具来对代码风格进行统一,等等。
至此,我们就可以回答 为什么需要工作链?
——工具链支撑着研发工作流中的每个步骤
多数 iOS 开发者可能对如何选择工具链比较陌生。
在明确如何选择工具链之前,我们先简单将工具链分成两类:一类称之为:All-in-one,另一类称为:Customizable。
这两类工具链有何区别呢?应该如何选择呢?
从字面理解,就是提供一整套完整的工具链用于处理项目整个流程的各个工作,体系完整,步骤清晰,缺点就是一般难以定制。
而我们实际的开发过程更接近 Customizable 类的工具链,开发者基于其经验,对整个流程的各个阶段各个操作都有其对工具的偏好,但这种 Customizable 类的工具链,其缺点是松散的,内部之间相互独立,难以形成体系,并且多人开发不好统一。
下面基于我们抖音团队的实际情况,介绍一下在开发流程中,具体用到了那些工具。这其中有自研的也有业内常用的或者开源的工具。
这些工具一般只关注其本身在流程中的所需完成的任务,而与其他工具不存在任何联系。
例如,对构建来说,除了 xcodebuild 以外抖音还有自研的构建工具。它们都完成构建任务,但构建只是整个研发流程中的一部分工作。
我们今天所讲的 MBox 是就是一个 All-in-one 类型的工具链。接下来我将介绍它是如何在抖音的实际开发中勾连整个开发流程。
MBox 移动研发⼯具链
目前 MBox 开源的是 CLI 版版本,GUI 版本暂未开源。
首先,我将介绍在本地开发阶段,MBox 做了那些事情。
在使用 MBox 移动研发工具链进行开发之前,用户需要手动创建一个 workspace
。
使用 mbox init ios
创建一个 iOS workspace
,除了 iOS 以外还支持创建 Android、flutter 等 workspace
。 workspace
可以简单解释为一个被 MBox 管理的单独的 sandbox 环境,作为主工程的存在,用于基础配置等。
然后我们进行开发,在开发之前我们需要创建一个环境并配置其所需的脚本、工具等等。
MBox 通过简化 GitFlow 模型,提出 Feature Mode
概念,每一个需求的元数据(即仓库、分支、代码)被抽象成为了一个 Feature
,每个 Feature
之间相互独立互不影响。执行 mbox feature start feture_name
在当前 workspace
空间中创建一个单独的 Feature
sandbox 环境。
然后我们添加仓库,执行 mbox add store_patch
,这里的 store_patch
既可以是云上的也可以是本地的。
接下来我们组装我们的工程,通常情况下使用包管理工具,这里使用的是 cocoapods
,来完成这项工作,在当前 Feature
sandbox 环境执行 mbox pod install
后,组装出用于开发的子工程。
MBox 还做了另外一件事,对 iOS 项目来说,自动安装证书并且在主工程中配置对应的描述文件。此外,MBox 还收集了设备的信息,做了一个测试机共享的平台。mbox debug-ios
完成了这几项工作。
其次,就是本地准入阶段 MBox 做了些什么。
不同公司在本地准入阶段做的事情可能都不太一样,这里以抖音团队本地准入阶段做的事情举几个例子来进行说明。
一个是进行静态分析,这里的 mbox-zk
指代抖音自研的一套本地准入工具,类似于 OCLint
、SwiftLint
之类的静态分析工具,用户在完成代码编写后,在本地进行代码分析,帮助开发者提前发现在 CI 阶段可能会遇见的问题。
另一个是 uncrustify
,一个代码风格校验的工具,我们将 uncrustify
嵌入到 MBox 流程中,在代码提交前可以一键修复代码,统一团队内的代码风格。
MBox流程中还使用了 gitlab-runner
,开发者可以在本地运行 CI
流程,帮助开发者提前发现在 CI 阶段可能会遇见的问题。
最后,也就是代码合流,当我们开发完成以后,需要将代码合并到平台上,提交 Merge requests (MRs)
。
参照业内现有的部分功能以及在多仓方面的深入,在代码合流阶段,MBox 提供了 mbox git
命令简化已有的 GUI 或 CLI 工具,进行代码提交。
提交完代码之后,我们进入到 feature finish
流程,与本地开发阶段的 feature start
流程相呼应。MBox 会将生成的多仓合码的表单提交到对应的平台上。
mbox workflow
为我们提供了在代码提交完成之后,对 CI 的状态进行追踪,包括一些 code review
等消息。
至此,我们介绍了从本地研发到最终 CI 的完整流程,以及 MBox是如何进行勾连的。
这里额外提一个,当我们需要调试或排查某个历史 Merge requests (MRs)
时,我们可以使用 mbox feature import feture_name
来回溯到对应的 Feature
,帮助开发者进行联调回溯。
通过对整个研发流程的概述,我们可以意识到作为一款 All-in-one 的工具链,MBox对整个开发体验来说有何影响。
MBox 如何提升移动研发效能?
我们介绍了 MBox 在研发流程中做了什么,顺着研发流水线的做了简单的介绍。接下来我们将介绍 MBox 怎么来提升移动研发效能。
我们将从节点效率和流转效率两方面的优化来具体说明。
节点效率优化
节点效率优化就是提升某个研发流水线节点的效能,我们以 mbox add
为例,MBox解决了两个代码仓库存放的痛点。
首先,我们看 MBox 是如何解决仓库庞大的问题。
左边这部分是 Git 的数据存储的原理图。红色的 ref
部分存储仓库的分支信息、标签信息等,其他称成为 Object database
即对象数据库。ref
将分支和标签信息与具体的数据进行连接,指向了 Commit object
,也就是提交对象。而提交对象都对应某个 Tree object
,可以理解为提交当时的目录列表。树对象 则指向了具体变更的数据对象 Blob object
,当然也可以指向其他的 Tree object
。
MBox通过根据 feature
信息,对应具体某次提交对象 关联的所有 Blob object
的信息,当开发者check out
某个版本时,延迟其他数据对象的下载,从而减少⾸次 clone
时所需数据对象(Blob object
)的传输。这个能力是 Git 支持的。
效果是显著的,⾸次 clone
时对象大小从 1.1GB
减少到 128.7MB
。
接下来我们在看,MBox是如何解决多仓工程占用他大量磁盘空间的问题。
随着团队增长,工程化、组件化不断深入,代码往往以仓库为级别进行隔离。但是,大多数研发人员常常面临需求多变的问题,比如并行开发多个需求或者临时的 Bug 修复。
例如,我们并行开发两个 feature
,各自包含不完全相同的组件仓库,例如 RepoA
,这就会导致我们需要在本地磁盘中存放两个一模一样的组件仓库。一旦对接方多了,大量相同的代码被存放在不同的工程中。
为了解决这个问题,MBox 基于 worktree
实现了仓库缓存。
MBox会基于 workspace
创建一个 Sandbox
,为每个组件仓库构建了一个缓存池,当研发人员开发 feature
时,其需要用到的组件来自于这个缓存池。
我们将缓存池中的组件仓库称之为main repo
,将开发过程中使用的组件仓库称为linked repo
,我们所需要的组件其保存的真实位置是在缓存池中的,而不是开发人员所见的feature
目录中。
在实践过程中,我们发现,当研发人员每次切换 feature
时, worktree
会进行全量的检出(check out
),耗费大量时间。
为此,我们添加了一个 File Cache
缓存池,当研发人员每次切换 Feature
时,之前 Feature
的文件会被缓存下来,新 Feature
中会有部分文件是从 File Cache
中复制而来的,这样就能够减少这种全量检出(check out
)的耗时,从时间和空间上完成优化。
至此,我们介绍了以 mbox add
为例,MBox 是如何提升的节点效率的。
流转效率优化
研发人员需要根据当前需求来回切换对应分支,尤其是在多仓开发中,频繁的需求变化会给研发人员增加大量成本。
研发人员正在开发需求 A
,此时接到了线上崩溃 B
的任务,抖音内部的线上崩溃平台会自动为研发人员构造一个复现崩溃B
的 Feature
,研发人员仅需利用 MBox的 mbox feature import B
就可以切换到对应的场景。
还有个场景是当研发人员在开发过程中需要帮忙协助排查任务 C
,研发人员仅需利用 MBox的 mbox feature import C
就可以切换到对应的环境,Feature C
需要被导出或者已经上传。
当我们解决完其他任务之后,我们利用feature start
回到我们之前开发 A
任务的环境,继续开发。
由于Feature
之间是相互独立的,当我们在切换不同的 Feature
时,并不需要保存当前的代码,也不需要自己手动配置他人或已有的 Feature
环境。
这样就从节点间流转和需求间流转两个方面做到了开发过程中流转效率的优化。
可拓展的 MBox
我们知道,单一的节点优化和整个流程流转优化,在整个研发过程中即是相互成就同样也是相互影响的。对单一节点的极致优化可能会影响整体流程间的流转效率,导致整个流程的劣化。
作为一款 All-in-one 类型的工具链,MBox 做了什么去提升生产节点流转的效率与单一节点效率。
这里就需要提到我们的设计思路,MBox的整体设计是一个插件化的架构。
接下来我将从编程思想和具体实现两方面来进行阐述这种插件化架构。
首先,MBox是基于 AOP 的编程思想的。多数 iOS 应该很熟悉 AOP 这个概念,但这里我们并不是从具体实践上而是从编程思想上来谈论这部分。
我们从业务中找到核心部分,并且将其解耦,基于这些切面来进行代码编写。
下面以 mbox add
为例来帮助理解。
mobox add
实现了在一个空的 workspace
中获取具体仓库文件的能力,其核心就是在当前 workspace
中获取对应仓库的代码。目前 MBox 内置获取仓库代码的工具是 git clone
,但假如未来出现一个更高效的工具download
或者原仓库不在使用 Git
进行存储 ,我们就可以通过改造 mobox add
,替换原先 git clone
的相关逻辑,换成 download
对应的实现。但是我们还是保留了mobox add
获取仓库的核心能力。
实现这种编程思想的方法就是开发者套件。用户通过 MBox提供的开发者套件来开发自定义插件,实现定制化能力。
MBox 的 CLI 部分是使用 Swift 开发的,这点对 iOS 程序员来说很友好。
通过 hook
原有的downloadRemoteRepository
方法,添加新的逻辑,完成对现有插件方法的改造。
通过使用 Swift 的
@_dynamicReplacement
特性实现hook
,Swift 5.1 提供了该特性。
需要注意的是,必须需要保证该方法最终的输出不变,不会影响整体的流转。
MBox通过插件化来兼顾了工具的拓展特性,尽可能的解决用户对单节点效率的要求,提升节点效率,同时也保持了高效的流转效率。
此外,作为一款 All-in-one 类型的工具链,MBox还能改帮助我们洞察工具的问题以及对效能进行度量。
MBox可以聚合工具链中在整体流转的问题并进行分析。
MBox还可以记录研发人员在开发流程中具体工具使用所耗费的时间,进行收集分析。
一文读懂字节跳动自研移动研发工具链 MBox:https://juejin.cn/post/7002062499851796488
MBox - Toolchain for Mobile App Development:https://github.com/mboxplus/mbox
维基百科-工具链:https://en.wikipedia.org/wiki/Toolchain
Sandbox:https://en.wikipedia.org/wiki/Sandbox
cocoapods:http://cocoapods.org/
OCLint:https://oclint.org
SwiftLint:https://github.com/realm/SwiftLint
uncrustify:https://github.com/uncrustify/uncrustify
Git Objects:https://git-scm.com/book/en/v2/Git-Internals-Git-Objects
这次分享讲师李尧所在团队,是负责抖音客户端基础能力研发和新技术探索的团队。我们在工程/业务架构,研发工具,编译系统等方向深耕,支撑业务快速迭代的同时,保证超大规模团队的研发效能和工程质量。在性能/稳定性等方面不断探索,努力为全球数亿用户提供最极致的基础体验。同时也在推进 Swift/SwiftUI/端智能等新技术在复杂工程中的落地,为研发提供最前沿的开发体验。
如果你对技术充满热情,欢迎加入抖音基础技术团队,让我们共建亿级全球化App。目前我们在上海、北京、杭州、深圳均有招聘需求,内推可以联系邮箱:[email protected],邮件标题:姓名 - 工作年限 - 抖音 - 基础技术 - iOS/Android
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK