前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【翻译】monorepos 的优点

【翻译】monorepos 的优点

作者头像
玖柒的小窝
修改2021-11-04 09:11:08
1.5K0
修改2021-11-04 09:11:08
举报
文章被收录于专栏:各类技术文章~各类技术文章~

本文对 Dan Luu 的 Advantages of monorepos 进行翻译

这是我一直在进行的对话:

某人:你听说 Facebook/Google 使用了一个巨大的 monorepo 吗?卧槽! 我:是啊!真的很方便,你不觉得吗? 某人:这是我听过的最可笑的事情。难道 FB 和 Google 不知道将所有代码放在一个存储库中是多么糟糕的主意吗? 我:我认为 FB 和谷歌的工程师可能熟悉使用较小的存储库(Junio Hamano 不是在谷歌工作吗?),而且出于 [某些原因],他们仍然更喜欢单个大型存储库。 某人:哦,听起来确实不错。我仍然认为这很奇怪,但我可以理解为什么有人会想要那样做。

“[某些原因]”很长,所以我把它写下来是为了避免一遍又一遍地重复同样的对话。

原因1: 简化组织

使用多个代码仓库的情况,最典型的情况要不是每个存储库有一个项目,要不就是每个存储库有一组相关项目,但这会迫使您定义特定团队或公司的“项目”,并且有时因为某些原因会迫使您拆分和合并仓库,这个成本是相当大的。例如,对于 VCS(版本控制系统(version control system),是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统) 而言,由于项目太大或历史记录过多而不得不拆分项目并不是最佳选择。

使用 monorepo,项目可以以任何您认为逻辑上最一致的方式组织和分组在一起,而不仅仅是因为您的版本控制系统迫使您以特定方式组织事物。使用单个 repo 还可以减少管理依赖项的开销。

简化组织的带来的一个好处是更容易浏览项目。我使用的 monorepos 让您基本上可以像在网络文件系统上一样导航,重新使用用于在项目中导航的语句。多仓库设置通常有两个单独的导航级别——项目内部使用的文件系统习惯用法,然后是用于在项目之间导航的元级别。

简化组织的带来的另一个好处很容易建立一个开发环境来运行构建和测试。如果您希望能够使用相当于 cd 的命令行指令在项目之间跳转,那么您还希望能够执行 cd 操作。由于它不起作用似乎很奇怪,因此它通常可以工作,并且任何使其工作所需的工具已经具备了(在我工作的一家硬件公司中,这甚至是正确的,该公司通过在 NFS 上的 RCS 中对事物进行版本控制来创建一个 monorepo。 当然,您不能让人们在中央存储库中实时编辑文件,因此有人编写了许多脚本,基本上将其变成了 perforce。 我不推荐这个系统,但即使有一个令人难以置信的 hacktastic monorepo,你仍然可以获得 monorepo 的很多好处。)。虽然在多个存储库中想建立一个开发环境在技术上是可能的,但这并不自然,这意味着必要的工作不会经常完成。

原因2: 简化依赖

这可能不言而喻,但是对于多个存储库,您需要有某种方法来指定它们之间的依赖关系并对其进行版本控制。 这听起来应该很简单,但在实践中,大多数解决方案都很麻烦并且涉及大量开销。

使用 monorepo,很容易为所有项目拥有一个通用版本号。 由于原子跨项目提交是可能的,因此存储库可以始终处于一致状态——在提交 #X 时,所有项目构建都应该工作。 依赖项仍然需要在构建系统中指定,但无论是 make Makefiles 还是 bazel BUILD 文件,它们都可以像其他任何东西一样被签入版本控制。 由于只有一个版本号,Makefiles 或 BUILD 文件或您选择的任何文件都不需要指定版本号。

原因3: 工具

导航和依赖的简化使得编写工具变得更加容易。与必须了解存储库之间关系以及存储库中文件性质的工具不同,工具基本上只需要能够读取文件(包括某些指定存储库内单元之间依赖关系的文件格式)。

这听起来像是一件微不足道的事情,但是,以 Christopher Van Arsdale 的这个例子来说明构建变得多么容易:

Google 内部的构建系统让使用大型模块化代码块构建软件变得非常简单。你想要一个爬虫?在这里添加几行。您需要 RSS 解析器吗?再添加几行。大型分布式容错数据存储?当然,再添加几行。这些是许多项目共享的构建块和服务,并且易于集成。 ... 这种类似乐高的开发过程在开源世界中并没有那么干净。 ......由于这种情况(更多猜测),开源中存在一个复杂性障碍,在过去几年中没有显着变化。这在像谷歌这样的公司容易获得的东西与 [n] 开源项目之间造成了差距。

Arsdale 所指的系统非常方便,以至于在开源之前,FacebookTwitter 的前 Google 工程师编写了他们自己的 bazel 版本以获得相同的好处。

从理论上讲,创建一个构建系统是可能的,它可以在没有 monorepo 的情况下轻松构建任何具有任何依赖关系的东西,但它需要更多的努力,足够的努力,我从未见过一个系统可以无缝地做到这一点。在某种程度上,Maven 和 sbt 非常好,但花费大量时间跟踪和修复版本依赖问题并不少见。像 rbenv 和 virtualenv 这样的系统试图回避这个问题,但它们导致了开发环境的激增。使用 HEAD 始终指向一致且有效版本的 monorepo 可以消除完全跟踪多个 repo 版本的问题(至少只要你有一些机制来供应上游依赖。虽然这对谷歌很有效,因为谷歌编写了它所依赖的大部分代码,并且有足够的员工将所有外部依赖项投入到 monorepo 中,在所有员工中摊销的成本很低,但是可想而知对于小公司而言这种优势太昂贵了。)。

构建系统并不是在单存储库上运行的唯一好处。例如,静态分析可以跨项目边界运行,无需任何额外工作。许多其他事情,如跨项目集成测试和代码搜索也大大简化。

原因4: 跨项目变更

对于多个代码库而言,跨代码库的代码变更是相当痛苦的。它通常涉及在每个 repo 或 hack-y 脚本之间进行繁琐的手动协调。即使脚本有效,也存在正确更新跨存储库版本依赖项的开销。重构一个在数十个活跃的内部项目中使用的 API 可能需要一天的大量时间。重构在数千个活跃的内部项目中使用的 API 是非常艰难的。

使用 monorepo,您只需在一次提交中重构 API 及其所有调用者。这并不总是微不足道的,但它比使用大量小型存储库要容易得多。我已经看到在数百个项目中具有数千种用途的 API 被重构,并且使用 monorepo 设置非常简单,以至于没有人会三思而后行。

大多数人现在认为使用 CVS、RCS 或 ClearCase 等版本控制系统是荒谬的,因为在这些系统中不可能跨多个文件进行一次原子提交,这迫使人们要么手动查看时间戳并提交消息,要么将元信息保留在确定某些特定的跨文件更改集是否“真正”是原子的。 SVN、hg、git等解决原子跨文件更改问题; monorepos 解决了跨项目的相同问题。

这不仅对大规模 API 重构有用。大卫·特纳 (David Turner) 曾负责 twitter 从多个 repos 到 monorepo 的迁移,他给出了一个小的跨领域更改以及必须为这些更改发布的开销的示例:

我需要更新 [Project A],但要做到这一点,我需要我的同事修复它的一个依赖项 [Project B]。反过来,这位同事需要修复 [Project C]。如果我不得不等待 C 发布,然后是 B,然后我才能修复和部署 A,我可能还在等待。但由于所有内容都在一个 repo 中,我的同事可以进行更改并提交,然后我可以立即进行更改。

如果一切都由 git 版本链接,我想我可以做到这一点,但我的同事仍然必须进行两次提交。并且总是有选择一个版本并修复冲突的时候。如果您只有一个项目,那很好,但是当您拥有一个相互依赖的项目网络时,情况就不那么好了。

[在另一个方向,] 强制依赖者更新实际上是 monorepo 的另一个好处。

不仅使跨项目更改更容易,跟踪它们也更容易。要在多个存储库中执行相当于 git bisect 的操作,您必须遵守使用其他工具来跟踪元信息的纪律,而大多数项目根本不这样做。即使他们这样做了,您现在也有两种完全不同的工具,一个就足够了。

原因5: Mercurial 和 git 很棒

对于这些问题,我得到的最常见的回应是,从 CVS 或 SVN 切换到 git 或 hg 是一个巨大的生产力胜利。确实如此。但其中很大一部分是因为 git 和 hg 在多个方面(例如,更好的合并)更胜一筹,而不是因为拥有小的 repos 本身就更好。

事实上,Twitter 一直在修补 git,而 Facebook 一直在修补 Mercurial,以支持巨型 monorepos。

缺点

当然,使用 monorepo 也有缺点。我不打算讨论它们,因为它们的缺点已经被广泛讨论过。 Monorepos 并不严格优于 manyrepos。他们也不是严格意义上的更糟。我的观点并不是你一定要切换到 monorepo;只是使用 monorepo 并非完全不合理,谷歌、Facebook、Twitter、Digital Ocean 和 Etsy 等地方的人们可能有充分的理由更喜欢 monorepo,而不是数百、数千或数万个较小的 repos。

其他讨论

Gregory Szorc. Facebook. Benjamin Pollack (Kiln 的共同创造者之一). Benjamin Eberlei. Simon Stewart. Digital Ocean. Google. Twitter. thedufer. Paul Hammant.

感谢 Kamal Marhubi、David Turner 和 Leah Hanson 对这个主题的广泛讨论。这里至少有一半的想法来自他们。此外,感谢 Leah Hanson、Mindy Preston、Chris Ball、Daniel Espeset、Joe Wilder、Nicolas Grilly、Giovanni Gherdovich、Paul Hammant 和 Simon Thulbourn 在这篇文章中发现错别字和其他错误。

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 原因1: 简化组织
  • 原因2: 简化依赖
  • 原因3: 工具
  • 原因4: 跨项目变更
  • 原因5: Mercurial 和 git 很棒
  • 缺点
  • 其他讨论
相关产品与服务
数据保险箱
数据保险箱(Cloud Data Coffer Service,CDCS)为您提供更高安全系数的企业核心数据存储服务。您可以通过自定义过期天数的方法删除数据,避免误删带来的损害,还可以将数据跨地域存储,防止一些不可抗因素导致的数据丢失。数据保险箱支持通过控制台、API 等多样化方式快速简单接入,实现海量数据的存储管理。您可以使用数据保险箱对文件数据进行上传、下载,最终实现数据的安全存储和提取。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档