BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

单体代码仓库:Uber的Android代码仓库演化史

| 作者 薛命灯 关注 24 他的粉丝 发布于 2017年5月22日. 估计阅读时间: 10 分钟 | QCon上海2018 关注大数据平台技术选型、搭建、系统迁移和优化的经验。

Uber技术日开幕式上,软件工程师Aimee Lucido呈现了一个有关Uber Android代码库历史的演讲。在这篇文章里,她继续展开说明Uber为什么要构建一个单体仓库来支持Uber的Android开发。

今天,你们要开始构建一个全新的Android应用,对于你们来说,开头部分总是最困难的。那么要如何开始呢?

如果你们跟我一样,那你们一定也是先在Android Studio里创建一个新的项目,然后创建一个主Activity,配置Gradle,或者再创建一个git仓库,这样其他人就可以与你一起合作开发这个应用。那么恭喜!你的代码结构就组成了第一个版本的Uber搭车应用。

我们使用一个大纸箱表示Uber的第一个Android代码基库:一个装着代码的大箱子。

我们在2010年启动了我们的第一个Android打车应用,那时我们还是一个小公司。Uber的工程团队只有寥寥数人。我们有一个合同工负责Android平台的开发,而且(如果你能够想象得到)我们甚至还没有Android的司机应用。我们的光杆Android工程师基于一个单独的代码库开发了打车应用的第一个版本:一个装着代码的大箱子。

在早期,使用单独的代码仓库来创建一个新的应用有几个好处:

  • 开箱即用的Android:Eclipse(开发第一个版本打车应用所使用的IDE)提供的代码结构就是一个单独的代码库。在2017年,构建一个单独的代码仓库比在2010年要容易得多,因为我们现在有Android Studio,可以使用更多的Android类库。不过,不管你使用的是哪一种IDE,这些IDE都会为你提供一个默认的仓库结构和一些基本工具,比如构建脚本和git集成。
  • 加快小型团队的开发:因为所有的依赖都集中在一个地方,对于一个小型的开发团队来说,使用单独的代码仓库可以提升他们的效率,共享代码和重构也会变得更简单。

几年之后,Uber的Android开发有了小规模的扩张。到了2013年,我们聘请了第一个全职Android工程师,在这一时期,我们的工程团队已经比之前翻了一翻。也就是从那个时候,我们才开始开发第一个司机应用。

开发司机应用让我们有机会对我们的代码基库结构进行改进。打车应用仍然放在单独的代码基库里,不过我们将一些可重用的组件抽取出来,因为我们已经拥有了必要的资源和工具来做这件事情。核心的代码仍然放在它自己的仓库里,不过我们构建了一个类库,包含了两个应用都要用到的公共组件。

到了2014年,我们的增长规模要求我们去寻找其他不同的解决方案。Uber的工程师已经超过一百个。Android工程团队的工程师也从一个变成了八个。随着工程师数量的增长,我们的代码基库规模也在增长。

我们看着前行的方向,我们意识到,如果我们不做出一些改变,我们将会碰到如下几个问题:

  • 长时间的构建:我们最初的Eclipse项目使用Ant作为默认的构建工具,而使用Ant构建大型的代码库会越来越慢。
  • 功能耦合:共享代码很容易导致过度共享。随着Android应用功能不断的增加,我们担心功能会无机地耦合在一起。
  • 破坏Master分支:将变更rebase到最新的Master分支上之后发生构建错误,然后需要花很多时间进行调试,这种事情经常发生。而你会发现,构建错误与你的代码并没有关系,而是之前有人在没有运行测试的情况下将代码rebase到Master分支上。如果你跟我一样,那么也已经处在一个两难的境地。多个工程师在同一个代码基库上贡献代码,却不使用持续集成工具(见后面的Submit Queue),那么就存在产生冲突的风险。这会对Master分支造成破坏,而且会浪费时间。

所以,在2013年到2014年期间,为了解决这些问题,我们做出了一系列改变,我们迁移到了多仓库的代码基库。2013年,我们使用IntelliJ和Maven代替了Eclipse和Ant,这样我们就可以从服务器上拉取依赖包,并将我们的包仓库拆分成20多个更小的独立仓库。(例如,网络相关的包被移到自己的仓库里,然后应用程序在编译时通过Maven将它们拉取到本地。)同时,我们改用Gradle构建脚本,迈出了向多仓库侵袭的第一步。

我们使用几个纸箱表示多库代码仓库,Uber在2013年将代码基库转成这种结构,以便满足不断增长的用户需求。

Uber的多库代码基库由一些小代码基库组成,每个小代码基库代表了一个单独的离散想法,包含了一些类库,打车应用和司机应用在编译时拉取这些类库。每个代码库就像是一小箱子的代码,包含了自己的IDE项目文件、git仓库和构建脚本。多库代码仓库是一种稳固的具有前瞻性的架构,解决了构建时间长、功能特性耦合和Master分支遭到破坏的问题。

现在的问题变成:为什么我们不是一开始就使用多库代码仓库?一句话:成本。将功能特性拆分到独立的仓库需要大量的时间,而且需要很多专家来完成。它需要很多领域的知识,比如Maven、Gradle、VPN和类库管理。这种知识的投入也只有在公司的规模增长到一定程度的时候才是值得的。

在将近三年的时间里,我们伴随着多库代码仓库结构一起成长。但到了2016年,我们的多库代码仓库开始出现瓶颈,我们的开发人员开始面临新的问题:

  • 架构孤岛:因为功能特性的强去耦,开始出现架构孤岛。我们早期构建了一个统一的lint系统,但它并不能防止不同的团队使用各种各样的ActivityFragment,以及MVC架构和我们自己的架构。从某种程度上说,架构孤岛是被允许的,甚至还有好处:工程师可以选择适合他们的架构。但随着规模的增长,我们的团队需要使用越来越多的类库。这意味着开发人员需要经常性地学习新的架构,而且学习曲线非常陡峭。因此,一个类库的架构如果没有被正确实现,将导致与消费者应用或其他功能特性的集成变得很困难,或者需要重度的代码重构。
  • 依赖地狱(Dependency Hell):这个方案确实能够减小依赖地狱问题所带来的影响,不过这也取决于你的变更涉及到多少类库,即使是在代码基库上运行这个工具就需要很长的时间。另外,修复问题可能需要好几天的时间:识别问题的依赖情况,修复代码,然后在受影响的代码库上拉出新的版本。
  • 长时间的构建:我们的代码基库规模已经达到Gradle能够进行快速构建的上限。一个新应用需要超过15分钟的时间来构建,对一些XML小文件的调整可能会占用数个小时的开发时间。

那么我们是怎么解决这些问题的?

我们的解决方案:使用单体仓库,一个包含了多个独立项目的代码仓库。一个代码基库包含一个单体仓库,就像我们最初的打车应用那样。不过与打车应用不同的是,这个箱子里包含了多个逻辑组件,它们是相互独立的。现在,我们可以在工具和架构上投入时间和资源,来修正大型单体仓库的缺点:

  • IDE支持: Android Studio被作为默认的轻量级的Android开发者平台,不过并不是唯一的选择。我们发现,在一个大型的单体仓库里,IntelliJ更适合我们目前的规模。
  • 长时间的构建: Uber目前已经从Gradle转向Buck,Buck是一个模块化的构建系统。我们的代码已经被拆分成离散的组件,所以很容易与Buck集成起来。我们自己开发的Gradle插件OkBuck将15分钟多的构建时间降到了5分钟以下,而对于增量构建,只需要不到一分钟的时间。
  • 破坏Master分支:我们最近引入了一个叫作Submit Queue的系统,用于将变更rebase到Master分支上,并且在合并之前运行一系列测试。这样可以防止工程师在提交代码时破坏构建过程,保持Master分支的整洁。

这看起来花费了不少功夫,事实确实如此。目前还没有开箱即用的单体仓库解决方案,因为很少有公司可以达到需要使用单体仓库的规模。我们现在有了时间、专家和资源来构建工具,防止那些在2013年出现过的痛点再次对我们的生产力造成破坏。

Uber花了数年的时间才达到了目前的开发状态。当我们还是一个由几个工程师组成的团队时,我们没有时间和资源来创建Submit Queue或者搭建Buck。不过,我们早期的洞见促进了架构决策,让我们可以快速地伸缩。现在,我们有了更进一步的发展,我们可以在开发上投入更多,确保未来的服务增长是无缝和高效的。

提升开发者的生产力是块难啃的骨头,但却非常重要。随着每一次小步跑的进步,我们不仅让Uber变得更好,也让整个Android社区变得更好。

查看英文原文: THE JOURNEY TO ANDROID MONOREPO: THE HISTORY OF UBER ENGINEERING’S ANDROID CODEBASE ORGANIZATION

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我
社区评论

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

讨论

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT