一文读懂字节跳动自研移动研发工具链 MBox(字节跳动 创新工具)
MBox 是由字节跳动抖音基础技术团队和 Client Infrastructure 团队根据移动端研发出现的现状与问题,结合移动端研发工具相关实践经验,自研的一款面向移动端开发者的研发工具链产品。目前,MBox CLI (Command Line Tool) 已经开源,后续将增加更多平台支持,欢迎试用。
现状与问题
随着公司的快速发展,移动端研发呈现出以下的现状与趋势:研发团队规模参差不齐,工程化与组件化方案不尽相同,跨端研发成为常态,中台业务不断扩大等,而这些现状使得移动端开发不得不面临下面的问题:日益复杂的研发环境与工程架构。
- 研发环境
在大前端背景下,移动端研发环境呈现出丰富的技术栈背景,这也导致了研发环境的复杂度提升。研发环境部署是编码的前置工作,这也是新人对团队研发体验的第一印象,因此研发环境的问题会给团队带来不少的麻烦。其实,并非仅有新人才遇到研发环境的问题,随着工程化推进,环境问题会持续困扰着团队所有成员,环境版本不一致、工程环境冲突、频繁更新文档,这些问题会使得研发人员将大量精力浪费在环境上,而不是核心的编码与测试阶段。
- 工程架构
很多移动端研发人员经常面对着的是超大型工程或者多个工程并行开发的场景,项目的工程架构往往十分复杂,这通常体现在多仓依赖管理困难、发布流程繁琐、多人协作难度变大,极大地影响研发效率。这里又引发了另一个思考,上述的部分问题其实是我们在工程化改造过程中所引入的,而这是否与工程化提高效率、保证质量的目的相违背呢?
渐渐地研发流程变得愈发繁琐,研发效率将不可避免地受到影响,可能在这之初研发人员会怨声载道,但长此以往便也习以为常了。
工具链面临的挑战
半自动化的流程
在移动端开发的场景下,研发人员尽管拥有看似丰富的研发工具来解决上面的环境与工程问题,但开发者们时常会有工具找不到、工具不会用与工具不好用的感受。理想状态下,工具链中每个工具的输出或者结果环境将成为下一个工具的输入或起始环境,但在移动研发的实践中,工具链之间的输出与输入转换时常需要研发人员手动完成,这种大量的重复性操作也成为研发人员吐槽的焦点。
维基百科:工具链是一组编程工具,通常是另一个计算机程序或一组相关程序。
被割裂的流水线
每一个研发团队都有着自己的研发流水线(评审、开发、构建、测试、修复、发布),在提升研发效能的实践中我们往往会提供丰富的研发工具供研发人员在这些流程节点中使用,但这些工具真的有合理地融入到我们的研发流程中,形成一条完整的工具链吗?
真实情况是,我们在实践中常常过多地关注单一指标,例如通过对工具链的改造提升项目的工程化程度,工程化确实能带来可维护性、工程质量等指标的提升,但是在其他环节中,如新人上手成本提升、依赖管理难度提高、代码合入时间拉长、Bug 复现困难等方面也带来了负面影响。
方案
我们对上述的现状与问题进行了分析,并结合在移动端研发工具相关实践经验,最终决定开发一款面向移动端开发者的研发工具链产品 MBox。
如上图所见,MBox 最终所呈现的产品形态是一款包含 GUI (Graphical User Interface) 与 CLI (Command-Line Interface) 的 Navtive App。
理念
全覆盖 All-in-one
我们期望开发一款能够对研发流程做到全场景覆盖的工具链产品,用户能够在 MBox 中获取所有需要的研发信息,并完成相应的研发工作,同时确保在整个研发链路中拥有一致的研发体验。
可视化 Visualized
在最初迭代 CLI 版本的过程中,我们渐渐发现可视化的交互方式可以解决一些在 CLI 交互中难以解决的问题,尽管 GUI 相比 CLI 在编程实现上会复杂很多,但我们坚信用户体验的重要性,因此 MBox 为用户提供了 GUI 与 CLI 两种可供选择的交互方式。
极简化 Simple
这里的 Simple 并不是指简单,而是交互设计上的简约,在这里本质上是可用性的体现。我们认为研发工具应该是为用户解决困难而不是制造困难的,任何无关的或是分散研发人员注意的信息都是不必要的,简单好用是对一款研发工具的最美称赞。
可扩展 Extensible
通常意义下 All-in-one 的工具链往往会导致可定制性变差,MBox 通过插件化技术在最大程度上满足了用户在横向与纵向上扩展性需求。
架构
上文中提到通常情况下我们的研发流程是一条流水线式的模型,多数研发工具都会从这条流水线中找到一个切入点来提供服务,协助用户完成某个节点的工作。而 MBox 在架构设计上则更多关注的是整个研发流程运转的效率,这不仅体现在单个节点的高效,同样体现在不同节点之间流转的高效。
MBox 在功能上并没有按照研发流程进行划分,而是将整条研发链路贯穿到所有的功能设计中,根据功能的种类分成四大板块:Environment、Workspace、Workflow、Tool。
核心功能
Environment
Environment 即研发环境,直觉告诉我们环境部署只是研发环节中较为前置的一个环节,但在实际开发实践中,Environment 要解决的不仅仅是部署(Deployment)的问题,其中还包含了环境统一(Consistency)、环境升级(Upgrade)和环境隔离(Isolation)这三个问题,而上述的四个问题却是贯穿于整个研发流程的。
我们认为在一个良好的研发体验中,研发人员无须关注绝大部分与环境相关的问题,应该把更多的关注度放在业务上,产生更多有效的价值。MBox 实现了整个过程的自动化,在任意时刻,无感知地为研发人员提前完成环境相关的部署、隔离与升级工作,同时还解决了项目研发环境一致性的问题。
上图展示了 GUI 下的环境功能模块,除了上文中提到的全自动化能力,MBox 同样支持用户手动控制。
Workspace
Workspace 是我们代码仓库存放的空间,也被认为是研发人员工作的核心。我们首先可以回顾一下,通常情况我们是如何管理代码的?在这过程中我们又遇到了哪些问题?
下文将阐述我们在实践过程中遇到的困难以及对应的解决方案。
挑战 1:跨项目开发 Multiple Projects
在一些研发团队中(常见于中台部门),常常需要在多个项目之间同时进行开发,每一个项目的代码仓库与研发环境往往是迥异的,研发在切换项目的过程中常常疲于解决各种仓库与环境问题,导致效率降低。MBox 采用沙盒化 Sandbox 技术,将不同项目的代码仓库与环境隔离开来,我们将这样的沙盒称之为 MBox Workspace(以下简称 Workspace),在这样的机制下,研发人员只需要明确当前自己需要开发哪个项目而无需关注这个项目背后的问题。
挑战 2:仓库繁多 Too Many Repos
随着团队增长,工程化、组件化不断深入,理想状态下每个业务团队只需要关注自己开发的组件,代码以仓库为级别进行隔离,这样做确实也会带来不少在缓存、二进制、安全风控等方面的优势,但这也可能会导致一个常见问题,即仓库数量庞大而变得难以维护。
在 MBox 中研发人员可以轻松地将远程或者本地的仓库添加到 Workspace 中进行统一管理,同时在同一 Workspace 中我们还利用缓存技术加速用户添加仓库的过程,让仓库的增删变得更加方便快捷。
除了仓库的增删,研发人员们最常用的还是 Git 仓库操作,MBox 参考了业内成熟的方案并结合自己的实践经验,以 CLI 与 GUI 两种方式为研发人员提供了多仓库批量操作的支持。
上面展示了 GUI 下多仓库提交的过程,在终端下用户可使用 mbox git xxx 命令来完成多仓批量操作。
挑战 3:需求多变 Change of Requirements
大多数研发人员常常面临需求变化的问题,比如同时开发多个需求或者临时的 Bug 修复,在 GitFlow 模型下,研发人员需要根据当前需求来回切换对应分支,尤其是在多仓开发中,频繁的需求变化会给研发人员增加大量成本。
MBox 通过简化 GitFlow 模型,提出 Feature Mode 概念,每一个需求的元数据(即仓库、分支、代码)被抽象成为了一个 Feature,每个 Feature 之间相互独立互不影响,允许研发人员可以在多个需求之间快速轮转。
从上图中可以看到,当前 Workspace 存在 3 个 Feature,分别是 feature1 feature2 bugfix,每个 Feature 拥有各自对应的同名分支。除此以外 MBox 还存在 Free Mode 的状态,在该状态下研发人员可以对仓库进行任意的操作,作为切换到 Feature Mode 的前置准备。
挑战 4:依赖复杂 Complex Dependency
在移动端的本地开发中,我们常常需要将某个组件依赖替换成本地仓库中的源码版本,同时还需要小心地维护着本地仓库的代码版本,以确保和集成版本一致。
MBox 具备一套完整的依赖管理方案,结合不同的包管理工具特点,利用多种技术实现了对依赖包的本地重定向,研发人员只需要一行命令或者点击几个按钮即可完成该操作,尽可能减少研发人员重复的机械性工作。
与此同时,通过一套抽象的依赖管理方案我们在一定程度上抹平了依赖管理工具之间的一些差异性,即便是在跨端开发中,研发人员依旧可以获得较为一致的研发体验。例如在组件化研发场景中,我们需要依赖本地的源码版本的组件 A,Flutter 和 iOS 平台上常用的包管理工具对应的 CLI 命令分别是
- Flutter
$ mbox add component_A$ mbox pub get
- iOS
$ mbox add component_A$ mbox pod install
挑战 5:协作困难 Collaboration
随着团队的扩大,团队成员之间的协作变得更加紧密,但与此同时项目的复杂程度同样会随着团队的增长而增长。如何将自己的研发进度及时且完整地同步给其他人,成为了提升团队协作效率所必须要解决的问题。
上文中已经提到 Feature Mode 的抽象过程,其实 Feature 不仅可以使得单个研发人员快速切换工作上下文,也允许不同研发人员共享自己当前状态下的所有代码仓库及其研发环境。
我们还可以发挥更多的想象力,如果将这一功能扩展至云平台,比如异常监控平台,由服务端构造出会发生某个崩溃 case 的 Feature ,研发人员将其导入本地,即可快速在本地复现出 Bug 出现的场景。
Workspace 的优势
结合上述的五个挑战中,我们分别提出了与之相对应的解决思路,即利用沙盒化技术解决跨项目开发问题,利用多仓管理技术解决仓库数量膨胀问题,提出 Feature 概念解决多需求并行问题,利用依赖管理技术解决依赖控制低效的问题,最后提出了同步 Feature 来解决多人协作困难的问题
Workflow
研发流程相关的云服务
在大型工程团队中,为了提升研发质量和效率,会推出很多与研发流程相关的云服务,这些服务的一般是通过前端页面或是命令脚本对外提供服务。但很多云服务都面临着同样的问题,无法及时地触达每个研发人员,落地往往都需要一定的时间,同时研发人员也需要付出一定的学习成本。我们一直在思考,如何帮助那些优秀的云服务发挥出最大的价值?
在实践中,我们发现云服务在结合了 MBox 的 Native 优势后,不仅大幅降低了用户的学习成本,同时也能够扩展云服务使用的场景。
上文中提及的 MBox 与异常监控平台的联动,就是一个很好的应用场景,监控平台通过 MBox 直接为研发人员创建了本地开发环境,将云服务的应用场景扩展至研发人员本地。云平台通过 MBox 可以实现与研发人员本地机器的联动,研发人员也能通过 MBox 直接使用线上的云服务,可以说 Native 解决了云服务工具“触达用户最后一公里”的问题,同时也为这些云服务带来了更大的想象空间。
智能错误诊断
在移动研发中,相当一部分的工具链是运行在研发人员本地机器上的,导致我们无法实时获取研发人员本地的运行状态,这也加大了排查问题的难度。另外,研发人员在研发流程中遇到报错或者疑问时,也缺少自我排查的方法,多数情况只能求助身边同事或者发起 Oncall。
MBox 借助自身作为一款 All-in-one 研发工具的优势,收集研发人员在各个流程中遇到的错误日志,进行分析和归类,在第一时间为研发人员推送问题的解决方案,尽可能地减少工具问题对研发效率的影响。作为工具链开发者,可以通过不断补充解决方案来优化错误诊断的流程 ,沉淀出通用问题的知识库来提升人工 Oncall 的前置拦截率。
Tools
MBox 不仅仅是一个研发工具,它更像是一个可以承载更多研发工具的平台 ,MBox 开放了所有的核心能力,所有开发者都可以通过插件的形式对它进行二次开发,将好用的工具分享给更多的开发者。
为什么是 Native App?
核心功能介绍完了,最后还是想谈谈为什么我们要做一款 Native App。
多数传统实践中我们常常利用“工具 平台 文档”三者的紧密配合来保障整个研发流程的运转,然而正是这种过于紧密的关系容易导致三者之间相互影响而阻塞开发。顺着这个思路,既然这三者存在着如此紧密的联系,那么是否可以存在这样一个载体将这三者统一成一个整体,满足研发人员在研发流程中的所有需求,确保研发这条流水线的高效运转。
既然作为 Native 开发者,为什么不为自己开发一款称手的研发工具来提升自己的工作效率?
这个很酷的想法就应运而生了,像做产品一样来做工具,核心围绕移动端本地研发。将产品思维应用到工具开发中,持续不断提升工具的可用性,我们坚信只有可用性高的研发工具产品才能真正起到提升研发效能的作用。同时在产品思维的驱动下,我们还可以利用 MBox 建立了效能度量数据指标,发现研发流程的关键问题,进行针对性开发和优化,形成使用产品 -> 收集数据 -> 改进产品的闭环。
尼尔森对产品可用性的认识:易用性、交互效率、易记性、容错性、用户满意度
开放性
开放性赋予了工具链强大生命力。
能力开放
MBox 在设计之初就使用了插件化的架构,自底向上完全遵循插件化开发的思路,尽可能地将所有能力开放出来,用户通过 MBox 提供的开发者套件来开发自定义插件,实现定制化能力。正因为有了如此开放的自定义能力,MBox 对研发流程支持的广度和深度将持续不断地进化。
平台开放
MBox 允许任何开发者可以将自定义插件上传至插件市场,同时团队技术负责人可以结合团队选择需要的插件集合,插件市场将负责同步团队内所有成员的插件及其对应版本。除此以外,所有用户也可以在插件市场这个平台上浏览和安装任何对自己研发效率提升有帮助的插件。通过这样一个开放的平台,在字节跳动内部已有来自多个不同的研发团队的数十个插件被发布至插件市场,功能涵盖了研发的各个流程,逐步建立起了一个开放的工具链生态。
如果说上面提到插件化架构很好地解决了插件“从哪里来”的问题,那么插件市场就很好地解决了插件“到哪里去”的问题。
思考
全链路与可定制
在选在研发工具链时,通常会有两种选择:
一种是全链路型的工具,即一套完整的解决方案覆盖研发的所有场景,在该方案下,所有研发数据流动会更加顺畅,用户体验更佳。
另一种是定制化工具,即结合当前团队的研发流程、人员结构、技术特点,自由选择最适合的工具链组合,将各个工具的长处发挥到极致。
从表面上看 MBox 似乎更像前者,即一款全链路的工具,但本质上 MBox 在做的是将后者的定制化工具组做一次整合,解决各个工具之间数据流转问题,提供一站式的工具链服务,打造研发体系的闭环。MBox 并不是要取代任何一个环节的工具,因此对于一般项目而言 MBox 的接入过程十分简单,我们的目的是将工具和开发者连接起来,最大程度地提升研发效能与用户体验。
再论研发流水线
上文提到研发流水线的概念,在传统实践过程中,围绕着这条流水线会孕育出各种工具平台,来协助研发人员完成这条流水线。然而,正如文章开头提到,工具链大多都专注于研发流程的某个节点,常常忽略了流水线节点流转的流畅性。
我们为什么如此关注生产节点之间流转的流畅性?
在提升研发效能实践中,提升生产节点流转的效率与提升单一节点效率一样重要。生产节点流转的流畅性其实最终体现在我们能够为用户提供一个灵活性强且易用性高的生产工具,因为实践中发现,前端研发人员们往往在一个多变的处境中,需求多变(同时开发多个需求或同时修复多个 bug)、环境多变(开发环境经常需要升级或切换版本)、工具多变(技术进展带来的工具变化)。研发人员时常直面这些变化却难以从容应对,尤其在面对流程切换所导致的效率损失时而倍感压力。
工具能够为研发人员提供足够的灵活性,是确保生产节点流转效率的关键。MBox 有意识地为用户提供了尽可能多的灵活性,支持了从需求到编码、需求到需求、实现到准入、编码到合码、线上问题到本地排查等多个流程的灵活流转。
结束语
自智能终端设备诞生起,移动端研发已蓬勃发展十余年,每个平台框架都已经发展出了一套独特的工具链体系,每个大型团队内部也已经建立起了一个个内部的工具体系,但正是这一个个独立而又成熟的工具体系将成为了束缚我们施展技术的牢笼。在大前端背景下,技术栈界限变得模糊,移动端开发者们如果能够打破这些限制,将我们的经验与技术应用到更广阔的未来之中,这是多么令人激动的事!最后希望 MBox 在这方面一些微不足道的思考和工作,能够重新唤起我们移动端开发者们改变世界的伟大愿望。
One More Thing
MBox CLI (Command Line Tool) 已经开源啦!现已支持 CocoaPods (iOS) 与 Bundler 项目,后续将增加更多平台支持。通过开源,我们希望更多的开发者能够加入到 MBox 的生态建设中来,为广大的移动端开发者带来一款出色的研发工具。
GitHub 地址:
- https://github.com/mboxplus/mbox
参考链接
- https://en.wikipedia.org/wiki/Toolchain
- https://github.com/nvie/gitflow
- https://www.atlassian.com/devops/devops-tools/choose-devops-tools
- https://flutter.dev/
- https://gradle.org/
- https://cocoapods.org/
加入我们
我们是负责抖音客户端基础能力研发和新技术探索的团队。我们在工程/业务架构,研发工具,编译系统等方向深耕,支撑业务快速迭代的同时,保证超大规模团队的研发效能和工程质量。在性能/稳定性等方面不断探索,努力为数亿用户提供最极致的基础体验。
如果你对技术充满热情,欢迎加入抖音基础技术团队,让我们共建亿级全民 App。目前我们在上海、北京、杭州、深圳均有招聘需求,内推可以联系邮箱:liyao.ryan@bytedance.com ,邮件标题:姓名 – 工作年限 – 抖音 – 基础技术 – iOS/Android 。