写点什么

谷歌是如何构建 Web 框架的

  • 2017-08-07
  • 本文字数:2177 字

    阅读完需:约 7 分钟

根据谷歌对外公布的数据,它的 20 亿行代码都部署在同一个代码仓库里,通过基于基线的方式进行开发工作中的代码共享。

从上面这张图可以看到,一共有文件 10 亿个,源文件数量达到 900 万个,源代码行数达到 20 亿行,提交代码的深度可以挖掘到 3500 万次提交,平均每个工作日提交 4 万次,数字真是恐怖。

从大众的眼光来看,特别是那些谷歌公司外部的人,他们会觉得这种单一代码仓库的管理方式,尤其是代码量这么恐怖的前提下,这种管理方式很不正常,但是它真的很有效,而这种有效是由管理方式决定的,而不是单纯让它自然生长。

Rachel Potvin 和 Josh Levenberg 编写的一篇文章里是这么描述的:

谷歌的代码库由全球数十个办公的超过 2.5 万名软件开发工程师所共享,平均每天他们会提交 1.6 万次代码修改请求,全文地址可以点击这里

只有一个版本

正如下面这张图所显示的,在谷歌,你看不到代码分支,拉代码分支是很多公司的习惯做法,在开发阶段这个很方便,相当于一个个独立的 Docker 镜像,但是等代码合并的时候就不是这么好玩了。

对于只有一个源码仓库的开发模式来说,你不可能出现应用程序 FooBar 使用 AngularDartV2.2.1 版本,而另一个应用程序 BarFoo 使用 2.3.0 版本的情况。两个应用程序必定需要使用同一个版本。这其实是将多版本之间的完全兼容性测试由出现问题转移到了代码提交环节。

每次提交 74000 个测试用例

我们这里以 AngularDart 框架为例,它目前有 1601 个测试用例。当你向谷歌的代码库提交一次 AngularDart 代码时,会自动为所有依赖于 AngularDart 框架的工程运行测试用例。也就是说,差不多有 74000 个测试用例(视依赖的工程数量而定,这里只是举一个例子,有些流行的框架可能测试用例会更多)。

我们举个例子,也许你修改代码的数量很少,例如“&& random.nextDouble() > .05”,你只是增加了这么一个判断条件,它并没有触发 1601 个测试用例里面的任何一条,但是因为你增加了这个判断,它可能会对框架的使用方造成问题。

真正的价值在于,提交代码时所作的测试时针对真实的应用程序的。不仅仅测试的量级很大,针对使用方的测试也可以反应你的框架是如何被开发者所使用的。这就好比我们自己写框架的人,写出来的测试用例都是符合我们思考方式的,但是你无法左右你的客户如何使用你。

对于生产环境下的应用程序,我们应该明白它们和测试环境的示例程序存在巨大的区别,你当前支撑得好,他们才会一直使用下去,这种做法也是为了更好地支持后续的开发活动。

你制造麻烦,你修复它

正如标题所说,如果 AngularDart 的作者引入了一个改变,哪怕只是一行代码的改变,他们都需要直接去为客户解决问题。也正是由于谷歌只有一个代码库,所以 AngularDart 作者可以直接修复问题。

所有的修改代码和针对客户的修复措施代码,它们都需要同时被提交带代码库,当然,还需要所有相关方的代码评审完成之后才能提交。

我们举个例子。当 AugularDart 团队的成员想要做代码修改,而这次的代码修改会影响 AdWords 这个应用程序的代码,那么 AugularDart 团队的成员需要直接进入 AdWords 的源代码,然后修复问题。他们可以运行 AdWords 已存在的测试用例,也可以自己增加一些新的用例。然后他们把所有的改变写入改变列表(change list)并提交评审。因为他们的 change list 涉及到框架(AngularDart)和调用方(AdWords)的代码,所以系统会自动请求来自双方面的成员进行代码代码审核和批准请求。

当然,业界也有其他的批评,认为 AngularDart 开发者仅关注了谷歌内部的使用方,例如 AdWords,而没有关注外部的使用方,例如 Workivas、Wrikes,以及 StableKernels。

大规模改变

如果 AngularDart 准备进行一次大规模的改变,例如从 2.x 升级到 3.0,是否真的需要为所有的使用者(框架依赖方)修复缺陷、运行测试用例,答案是:Yes。

当类 Foo 里的一个方法从 bar() 变为 baz(),你可以构建一个工具,这个工具可以遍历整个 Google 代码库,自动搜索所有的 Foo 类及其子类的实例,直接把它们修改为 baz()。

性能指标

除了关注功能,谷歌还要求框架提供方关注提交代码后出现的性能问题。谷歌会自动为每一个使用方生成性能测试结果,这个性能测试是针对生产环境的,绝对真实。

Hermetic 构建工具

对于大量的测试用例,开发人员当然不可能一个一个去运行,一个个修复缺陷,他们使用的是 Bazel(开源构建代码工具)。在这个量级下你不可能使用一系列的 shell 脚本构建工程,你需要的是 hermetic 构建工具。

hermetic 在这里的意思有点类似于“纯正”,你构建的步骤不能有单边影响(例如 temo files、changes to PATH 这些修改),修改需要是可以判断的(例如输入什么导致输入改变)。你可以在自己的机器上通过 hermetic 工具先运行测试用例,相当于你机器上的客户端,运行通过后把改变代码提交到服务器上并行构建它们。

总结

通过这种类似于提供方作为责任方的制度,让谷歌的软件开发人员对于每一行代码的提交都会非常谨慎,但是也对生产环境的程序稳定性、性能提供了充分的保障,此外,通过这种方式也会影响开发人员对于产品的开发思维,让他们可以站在用户的立场上思考如何更好地构建自己的框架,这其实也是在一定程度上推动技术和产品的发展。


给 InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们。

2017-08-07 19:004202
用户头像

发布了 50 篇内容, 共 26.1 次阅读, 收获喜欢 38 次。

关注

评论

发布
暂无评论
发现更多内容

点进来,与白洞一起体验一场沉浸式智慧轨道之旅

脑极体

消息队列表结构设计

guangbao

MVCC的机制初识

卢卡多多

MVCC 11月日更

HW3 - 外包学生管理系统架构文档

WWH

架构实战营

版本化ASP.NET Core WebApi

喵叔

11月日更

译文 | 科普:Pulsar 和 Kafka 架构对比

Apache Pulsar

kafka 架构 分布式 中间件 Apache Pulsar

自定义View:多点触摸与实现任意拖动图片控

Changing Lin

11月日更

Go 语言,测试功能详解 - 下

微客鸟窝

Go 语言 11月日更

16 K8S之容器健康监测

穿过生命散发芬芳

k8s 11月日更

使用 JavaScript 创建和下载文件

devpoint

JavaScript File Blob 11月日更

详解低延时高音质:丢包、抖动与 last mile 优化那些事儿

声网

音频体验 RTE技术详解 last mile 优化

“元宇宙”到底是啥?为啥火了?鼓励探索警惕忽悠

CECBC

什么是低代码平台?

石云升

低代码平台 11月日更

在线极限词,敏感词,违禁词查询工具

入门小站

工具

【Promise 源码学习】第九篇 - Promise.resolve 和 Promise.reject 的实现

Brave

源码 Promise 11月日更

TypeScript 类型系统

HoneyMoose

一个基于DPoS共识算法的区块链案例解析

Regan Yue

区块链 11月日更 细讲区块链

Android C++系列:访问Assets 文件夹

轻口味

c++ android jni 11月日更

双十一还是孤身一人?超强AI神器送你一个"对象"

百度大脑

人工智能 百度

博文推荐 | Apache Pulsar 对现代数据堆栈至关重要的四个原因

Apache Pulsar

kafka 架构 Apache Pulsar 数据堆栈 DataStax

进击的Java(八)

ES_her0

11月日更

Golang Gin 框架参数解析介绍(三)

liuzhen007

11月日更

VR和AR只是入门,真正的元宇宙远不止于此

CECBC

你找的网络安全系列书籍,都在这了!

喀拉峻

网络安全 安全 信息安全

AlmaLinux树莓派初体验

IT蜗壳-Tango

11月日更

Pulsar的Chunk Message原理剖析

Zike Yang

Apache Pulsar 11月日更

linux实战清理挖矿病毒kthreaddi

入门小站

Linux

【Quarkus技术系列】「云原生架构体系」配置参考指南相关的功能机制配置介绍分析

洛神灬殇

入门 配置信息 Quarkus 11月日更

Ta们用数字种植绿色山河:牛津博士与储能之变

脑极体

技术改进项目的质量保障思路

QualityFocus

架构 软件测试 自动化测试 质量保障 技术改进

TypeScript 是弱类型

HoneyMoose

谷歌是如何构建Web框架的_Web框架_麦克周_InfoQ精选文章