详细解释Google如何构建web框架

我们都知道,Google使用一个单一的代码库分享全部二十亿行代码,并且采用的是主干开发模式。

毫无疑问,这是世界上最大的单一代码库之一。

虽然这让人吃惊,也觉得有悖于常理,但对公司之外的众多开发者来说,它确实运行得不错。(以上文章提供了一个很好的例子,我在此不再重复。)

Google的代码库为全世界几十家办事处和超过25,000名Google软件开发者提供了共享服务。他们可以在正常工作日内对代码库进行16,000次修改。

只有单一的版本

如果您在单一代码基中使用主干开发模式,那么所有东西都是单一版本。这一点非常明显,但是仍然需要特别指出,它意味着Google的FooBar不会有AngularDart2.2.1和2.3.0两个版本。

Google的员工有时会说,他们所有的软件都在行业的前沿,并且采用最新的技术。

假如你突然想喊出“危险!”也可以理解。的确,仅仅依赖于产品代码库中的主干(git中的“master”),这听起来确实很危险。但是不要着急,前面有个情节转折点。

每每个提交前的7.4万次测试

分析目标定义了1601个测试。不过,当您在Google代码库中修改AngularDart代码时,还可以对使用这个框架的Google雇员进行测试。现在一次提交大约要做74000个测试(这要看修改的程度,而系统会自动跳过不受影响的测试)。

考试时间越长越好。

举例来说,我做了一个小更动(在这个if语句中添加了&&random.lxtDouble()>.05),让它显示的时间只有5%,以便在算法中模拟变更检测和验证竞态条件。在运行之后,它没有开始1601个测试,而是开始了客户机测试。

其真正价值在于对实际应用程序进行测试。他们不仅数量巨大,而且反映了开发人员是如何使用框架的(不仅仅限于框架作者)。要点:框架作者并非总能正确评估框架的使用情况。

它还可以帮助生产中的应用获得每月数十亿美元的资金。构架开发人员在空闲时间完成的演示应用程序,以及几十、几百人从事多年开发的实际应用程序之间仍存在很大的差别。若未来网络是紧密相连的,我们需要更好的支持后者的发展。

因此,如果框架破坏了某些应用程序,会发生什么呢?

谁破坏,谁修复

假如AngularDart的框架作者引入了一个破坏性的变化,那么他们就得为用户来修正。因为Google使用一个单一的代码库,很容易找到破坏程序,并且能够立即修复。

对于AngularDart,以及所有依赖Google的应用程序的修改,都是破坏性的。所以,在通过相关人员检查代码之后,破坏和修复将同时进入代码库。

举个具体的例子:当AngularDart团队中有人对AdWords应用程序的代码做了一些更改,他们会检查这个应用程序的源代码,然后对其进行修复。在修复期间,他们可以运行AdWords现有的测试,也可以添加新的测试。随后,他们将所有这些都放入变更列表,并要求代码评审。因为更改列表与AngularDart和AdWords的代码有关,所以系统会自动要求这两个团队进行代码审查。只能通过双方同时提交更改。

显然,它可以阻止框架开发过程中,不需要任何激励就可以自由地执行。开发AngularDart框架的人可以访问他们自己平台上构建的数以百万计的代码,并且因为他们经常接触到这些代码,所以他们不需要想象其他人如何使用他们的框架。(值得注意的是,他们只看到了Google内部使用这个框架者的代码,并没有看到世界上所有人都在使用它。)

更新用户的代码还会降低开发速度,并没有您想象的那么大(你可以看看AngularDart十月份以来的进展),但是总而言之,开发进度会有所下降。最后是好是坏是坏是坏是坏。我们待会再谈谈这个问题。

所以,下一次,你会明白为什么Google会有人说,某个库的Alpha版本是稳定的,并且可以应用于产品。

大规模改动

假如AngularDart需要做一个大的改变(假设版本从2.x升级到3.0),会不会影响74,000次测试?小组是否解决了所有问题?难道他们要修改成千上万的源文件吗?甚至大部分源文件都没有?

回答是Yes。

“类安全系统”(soundtypesystem)可以使一切变得更高效、更简单。举例来说,在Dart类安全系统中,工具可以是某个变量的特定类型。修改这些变量之一,可以自动应用到所有相同的类型,而不需要开发者手工改变。

如果Foo上的一种方法从bar()更改为baz(),您可以创建一个工具,遍历整个Google代码库,查找Foo类及其子类的所有实例,并将所有bar()更改为baz()。在Dart类安全系统的帮助下,你不会影响到其他部分。如果没有类安全系统,一个简单的修改就会带来很多麻烦。

只要按一次键,你的代码就可以按照Dart的风格设置。实际上,指南中提到:“正式的Dart空白处理规则是由dart_style执行的。”

Dart_style(用于Dart的默认格式化程序)是另一个可以帮助进行大规模修改的利器,Google所有的Dart代码都通过这个工具格式化。在您的代码被提交给审查者时,它已自动将dart_style应用于格式设置,因此再也没有“新行不需要放在这里”这样的问题了。它同样适用于大规模代码重构。

性能指标

正如上面提到的,AngularDart能够从子产品的测试中获益,而不仅仅是测试。Google对其应用程序的性能进行了严格的评估,所以大多数(可能是所有)产品的应用都有基准测试套件。

更改发布之前,Google内部已经知道AngularDart团队引入了一个新的修改,使得AdWords的载入速度降低了1%。十月份,研究小组称,AngularDart应用程序的规模从八月份开始下降了40%,但是速度提高了10%。它们并不在谈论像TodoMVC这样的小应用,而是在现实世界中处理关键任务、拥有数百万用户群和上兆字节的业务逻辑代码。

旁注:封闭的构建工具

您如何知道在AngularDart引入这个脆弱的Bug之后,您应该在这个庞大的内部存储库中做哪些测试呢?无法人工选择74万个测试,也无法在Google内部运行所有测试,这是肯定的。这个问题的答案叫Bazel。

以此代码规模,您无法构造出用于编译的shell脚本来序列。第一是易受攻击,第二是非常缓慢。您需要一个封闭的构建工具。

"pure"一词很类似于函数中的"pure"。构建步骤不能有副作用(如临时文件、改变PATH路径等等),它们必须是确定的(也就是说,相同的输入必须是相同的输出)。这样,您可以在任何时候,在任何机器上运行构建和测试,以确保输出的一致性。您不必使用makeclean。所以,您可以发送编译/测试来构建服务器,并使其并行运行。

Goolgood花了几年时间来开发这个构建工具,并在去年以Bazel的形式开源。

通过这个基础设施,内部测试工具可以自己决定构建/测试的影响范围,并在适当的时候运行。

这一切意味着什么?

在开发大型Web应用程序时,AngularDart的目标很明确,即获得最佳的生产率、性能和可靠性。这篇文章只讨论最后一部分——可靠性,以及为什么像AdWords和AdSense这样的重量级应用程序会使用这个框架。团队并非夸耀自己的用户,正如上面所提到的,拥有大量的内部用户使得AngularDart不太可能引入一些使框架更可靠的表面改变。

如果这些听起来太过商业化,你可以看看我的AngularDart非商业化项目,比如AutomaticDonaldTrump(Markovto)或者PriyFinder。

如果您正在寻找的框架需要在几个月内进行重大修改或功能升级,AngularDart绝对不适合您。即便团队想要以这种方式构建一个框架,本文也清楚地告诉您这是不可能的。但是我们真诚地相信,一个不合乎潮流,却又特别可靠的构架,还有它的存在空间。

依我看,一个开放源码技术组合能否获得长期维护和支持,最好的预测方法是看它是否是主要维护者公司业务的重要组成部分。比如Android,dagger,MySQL或者git。因此,我很高兴Dart最终拥有了一个首选的Web框架(AngularDart)、一个首选组件库(AngularDartComponents)和一个首选的移动框架(Flutter),所有这些都被用来构建Google在商业上的关键应用。

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据