持续交付2.0

不一样的《软件工程@Google》

Image

本文作者:Marine Wu

本文是 Software Engineering at Google(https://arxiv.org/abs/1702.01715)这篇论文的翻译,作者是 Fergus Henderson。它的侧重与同名的 Software Engineering at Google 略微不同,并且更为精简。

本文在翻译外添加了部分说明,包括本文的内容在 SE@G(Software Engineering at Google)书中的对应章节、详解、开源或已知的类似系统建设等。由于篇幅关系,大部分说明内容不做详细展开。

另外,本人不同意原文中定义的Google的成功、工程和文化观点。

1

简介

Google 是一家非常成功的公司。除了Google 搜索和 AdWords 的成功之外,Google 还提供了很多其他出色的产品,包括Google 地图、Google 新闻、Google 翻译、Google 语音识别、Google 浏览器和安卓系统等。Google 还极大地增强和拓展了许多通过收购小公司而获得的产品(例如 YouTube),并为各种开源项目做出了重大贡献。Google 展示了尚未推出的惊人产品,例如自动驾驶汽车(注: waymo)等。

Google 的成功有多方面的原因,包括开明的领导层、优秀的团队、高招聘⻔槛,以及在快速增⻓的市场中成功利用早期领先优势所带来的财务实力。其中不可忽视的一个原因是 Google 发展了优秀的软件工程实践。由全球最有才华的软件工程师队伍写就,并经过长期积累,碰撞,提炼,这些实践承受了时间的检验,并不断地演进与完善。

我们希望与世界分享我们的实践知识,并分享我们从错误中吸取的一些教训。

本文的目的是对 Google 的关键软件工程实践进行分类和简要描述。然后其他组织和个人可将这些与其自身的软件工程实践进行比较和对比,并考虑是否自行应用其中的一些实践。

许多作者(例如 [9]、[10]、[11]) 撰写了分析 Google 的成功和历史的书籍或文章。但其中主要涉及商业、管理和文化。只有一小部分(例如 [1, 2, 3, 4, 5, 6, 7, 13, 14, 16, 21]) 涉及了软件工程方面,并且大多数只探索了一个子领域。并且它们都没有像本文这样,旨在提供对整个 Google 软件工程实践的简短书面概述。

如果一定要从本文中记住一句话,译者的希望是“其他组织和个人可将这些与其自身的软件工程实践进行比较和对比,并考虑是否自行应用其中的一些实践。”

Google 的软件工程实践是一个繁杂的系统,即使 Google 内部也很少有人能够完整了解 Google 的软件工程体系和基础设施,以及工程师文化全貌。Google 的软件工程的形态深受其商业形态影响,且它的商业形态不具有普适性。Google 的工具、流程和文化经历了长期的演化,并且仍然在快速的演进过程中——在当前状态的系统和工程实践未必(甚至很可能并不)是完美状态。任何类似本文的尝试注定只会是不全面的、不完美的、不准确甚至是错误的。

因此,在考虑学习应用任何工程实践(不限于 Google 工程实践)时,不能只局限于知道实践的内容(更糟糕的是只学了个皮毛,只知道名词)。下面的两个问题至关重要:

  • 图个啥?理解实践所试图达到的目标。没有银弹,实践通常是为了(部分)解决特定的问题。如果这个问题并不是组织当前的核心问题,那一个好的实践未必是当前重要的实践。

  • 为啥要这么干?理解实践的上下文。注意到工程实践往往不是孤立的,一个工程实践往往需要工程、组织和文化上的多个前置条件,而且会造成工程、组织和文化上多种影响。一个好的实践在组织当前的上下文下未必可行。

“治大国如烹小鲜”。

2

软件开发

2.1 源码仓库

Google 的大部分代码都存储在一个统一的源码仓库中,Google 的所有软件工程师都可以访问(客户数据受到严格保护,可访问的仅仅是源代码)。有一些例外,如 Chrome 和 Android 这两个大型开源项目使用单独的开源仓库。另外,一些高价值(注:如 search 的核心逻辑)或安全关键代码段,它们的读取访问权限被更严格地限制。但大多数 Google 项目共享同一个仓库。

截至 2015 年 1 月,这个 86 TB 的仓库包含十亿个文件,其中包括超过 900 万个源代码文件,总共包含 20 亿行源代码,具有 3500 万次提交的历史记录和每个工作日 4 万次提交的更改率 [18]。对仓库的写入访问受到控制:只有仓库每个子目录的所有者才能批准对该子目录的更改。但通常任何工程师都可以访问任何一段代码,可以检出并构建,可以进行本地修改,可以测试它们,可以将更改发送给代码所有者审查,而且在所有者批准的情况下,可以签入(提交)这些更改。

Google 鼓励工程师修复他们看到的任何缺陷,也鼓励他们掌握如何修复,尽管他们可能不参与这个项目。这赋予了工程师权力,并带来更高质量的基础设施,更好地满足代码使用者的需求。

几乎所有的开发都在代码仓库的主干 HEAD 上,而非在(长期)分支上。(注:换言之,采取主干开发)这有助于尽早发现并最大限度地减少合并冲突,并减少合并所需工作量。主干开发还简化并加速了对安全问题的修复。

自动化系统频繁运行测试。Presubmit 通常会运行 Changelist 所修改文件的所有反向依赖中的测试目标,虽然有时这并不可行。这些系统将在几分钟内自动将测试失败的任何更改通知作者和评审人。大多数团队通过在 Presubmit 结果页放置显眼的主干健康监控,例如可能是带有颜色编码的指示灯(绿色表示构建成功并且所有测试通过,红色表示一些测试失败,黑色表示构建失败,注:紫色表示测试不稳定,即 flaky tests),来提醒他们当前的构建状态。这有助于将工程师的注意力集中在保持“绿色”构建上。大多数较大的团队也有一个富有经验的成员充当“构建警察 (Build Cop)”,通过与代码作者一起快速解决任何问题或回滚有问题的更改,确保测试继续通过。

代码所有权。仓库的每个子目录都可以有一个 OWNERS 文件,列出该子目录所有者(Owner) 的用户 ID。子目录也从其父目录继承所有者(可以选择禁止继承)。每个子目录的所有者控制对该子目录的写入权限,如下面的代码审查部分所述。每个子目录都需要至少有两个所有者(尽管通常会有更多所有者),尤其是在成员地理位置相对分散的团队中。整个团队都列在所有者文件中是很常⻅的。Google 的任何人都可以对子目录进行更改,而不仅仅是代码所有者,但必须得到其代码所有者的批准。这确保了每个被修改的代码都由熟知该代码的工程师审查。

注释:

  • 有关 Google 大仓的更多信息,请参阅 [17、18、21];以及另一家大公司如何应对同样的挑战,请参⻅ [19]。

  • 对应 SE@G 的第 16 章: Version Control and Branch Management

大仓

大仓的方案通常有两种:

(1)通常在文件系统层面实现的按需获取所需文件的 lazy loading 模式,

(2)在仓库内部分检出(sparse checkout/partial clone)的 eager loading 模式。

前者的优势在于对用户通常是无感的,但是实现难度非常高,并且会有性能的隐患,以及无法在无网络环境下正常工作[见下注]。后者的优势在于具体的操作对用户透明,但是这要求用户需要能够明确地声明自己编译所需要的依赖关系。

(注:Google 因为由于技术能力不足,无法保证离线环境的代码安全,所以要求所有的与代码相关的操作必须在公司内部网络环境中。所以无法在无网络环境下正常工作在 Google 是 Working as intended。并且由于都是在内部网络操作,并不支持复杂多样的开发环境,所以懒加载方案受硬件的影响较小。)

Google/Meta 采取了前者:

  • Google 的 Piper 并没有开源,但是本身原型是 Perforce。

  • 开源的最接近的类似设计是 Meta 的 https://github.com/facebook/sapling。

有一个值得注意的关键是 Google/Meta 都采取了基于差异(类似于 Mercurial)的代码储存,而非像 Git 是基于代码快照全量存储。前者对大型仓库更加友好,但更依赖主干开发的模型。

Microsoft 采取了后者:

  • Microsoft 贡献了 Git Sparse Checkout。 Sparse Checkout 也就是 Partial Clone 支持显式地声明只 Checkout 部分目录而非全量仓库。

  • Microsoft 开发了 VFS for Git,即也创建了一层 vfs(殊途同归,最终都要在 FS 层做文章)以处理 Partial Clone。在此基础上继续开发了 Scalar(https://github.com/microsoft/scalar)。这是现在已开源的主要可行的大仓的方案。

OWNERS 机制

代码所有权的机制, 参看《 OWNERS 机制的规则设置》(evernote://view/19159290/s20/186dc414-6b3b-4089-98ff-0c6784a5e7e3/186dc414-6b3b-4089-98ff-0c6784a5e7e3/)。

自动化系统

自动化系统的 Postsubmit 的指示灯类似于 可以展示构建状态的Dashboard。

2.2 构建系统

Google 使用名为 Blaze 的分布式构建系统来编译和链接程序以及运行测试。它提供了用于构建仓库内所有工程的标准命令以及覆盖执行仓库内所有进行测试的命令。这些标准命令和高度优化的实现意味着对于任何 Google 工程师来说,构建和测试仓库中的任何软件通常都非常简单快捷。这种一致性是一个关键的推动因素,它使工程师跨项目提交更改变得切实可行。

程序员编写 BUILD 文件。Blaze 使用这些文件来确定如何构建他们的软件。库、程序和测试等构建实体使用相当高抽象的声明式构建规范为每个实体指定其名称、源文件及其所依赖的库或其他构建实体的名称和地址。这些构建规范由称为“构建规则(Rule)”的声明组成,每个声明都指定高层抽象概念,例如“这里是一个 C++ 库,其中包含依赖于这些其他库的这些源文件”。构建系统会决定如何映射每个构建规则到一组(它所调用的)构建步骤的规则,例如编译每个源文件的步骤和链接的步骤,以及确定要使用的编译器和编译标志的步骤。

在某些情况下,特别是 Go 程序,构建文件可以自动生成(和更新),因为构建文件中的依赖信息(通常)是源文件中依赖信息的抽象化。但它们仍被签入到仓库。这确保了构建系统可以通过仅分析构建文件而不是源文件来快速确定依赖关系,并且它避免了构建系统与支持不同编程语言的编译器或分析工具的过度耦合。

构建系统的实现使用了Google 的分布式计算基础设施。每个构建的工作通常是分布在数百甚至数千台机器上。这使得快速构建非常大的程序或并行运行数千个测试成为可能。

各个构建步骤必须是密闭的(hermetic):它们仅依赖于它们声明的输入。 分布式构建要求必须正确声明所有依赖项,因为这样才可能仅把声明的依赖项输入发送到运行构建的机器。因此,可以通过构建系统来了解真正的依赖。甚至,构建系统调用的编译器也被视为输入。

各个构建步骤是具有确定性的(deterministic)。因此,构建系统可以缓存构建结果。软件工程师可将其工作区同步回旧的代码提交(注:代码提交在 Google 称为 changelist, 类似于 commit/MR 的结合),并可重建并将获得完全相同的二进制文件。此外,此缓存可以在不同用户之间安全地共享(为了使其正常工作,我们必须消除构建调用的工具中的不确定性,例如通过清除生成的输出文件中的时间戳)。

构建系统是可靠的。构建系统跟踪对构建规则本身更改的依赖性,并且知道如果生成目标的操作发生变化就重建目标,即使该操作的输入没有发生变化,例如当只有编译器选项发生变化时。它还能正确处理中断构建过程,或在构建过程中修改源文件:在这种情况下,您只需要重新运行构建命令,而永远不需要运行类似于 “make clean” 的命令。

构建结果缓存在“云端”。这包括中间结果。如果另一个构建请求需要相同的结果,构建系统将自动重用它们而不是重新构建,即使请求来自不同的用户。

增量编译很快。构建系统驻留在内存中,因此增量编译时,它可以增量分析自上次构建以来发生变化的文件。

Presubmit 检查会执行构建/测试。Google 有一些工具可以在启动代码审查和/或准备向仓库提交更改时自动运行一套测试。 仓库的每个子目录都可以包含一个配置文件(注:名为 METADATA),该文件确定要运行哪些测试,以及是在代码审查时运行它们,还是在提交前立即运行,或两者都运行。测试可以是同步的,即在发送更改以供审查之前和/或在将更改提交到仓库之前运行(有利于快速运行的测试);或是异步的,将结果通过电子邮件发送到评论讨论串。[审查邮件串是代码审查生成的电子邮件串;该串中的所有信息也显示在基于 Web 的代码审查工具中。]

注解:

  • 构建系统对应 SE@G 的第 18 章: Build Systems and Build Philosophy

  • 持续集成对应 SE@G 的第 23 章:Continuous Integration

  • 代码浏览器对应第 17 章: Code Search

Blaze

Blaze 的开源版是 Bazel, 即 https://bazel.build/

文中提到的 Go 自动生成构建文件是 Gazelle,即 GitHub - bazelbuild/bazel-gazelle。其它的语言如 C++/Java/Python 等,均需要手动编写 BUILD 文件。

Bazel 和 Gazelle 在我司目前已大量投入应用,在此不再详细介绍。

构建集群

远程构建(即将 Bazel 的构建原子发送到远程构建)的复杂性更高。稳定性是一个大的挑战。目前远程缓存处于 Beta 阶段,正在双跑验证,并开放试用 。

经验数据显示,远程缓存通常可以减少 ~50% 的构建时间,而远程构建在远程缓存的基础上会继续减少~20% 的构建时间。(注意这些数据是平均经验数据,具体的效果可能受网络、硬件、构建任务的性质等多种因素影响)

Image

BES 结果展示

Bazel 提供了非常详尽的构建信息输出(以 BEP 的形式): https://bazel.build/remote/bep

BEP 可以提供做构建相关的研效数据分析的几乎所有信息。

Bazel 可以通过指定远程接口输出 BES,而一个 BES 分析处理系统可以有效地整合这些信息。是一个所有 Bazel 构建的聚合页面,

Bazel 密闭性

Bazel 的密闭性并不像所声明的那样容易实现。C/C++ 工具链会涉及系统库,这使得一个完整而密闭的 cc_toolchain 的构建并不平凡。一个密闭的 cc_toolchain 工具链。

对 C++ 的工具链的封装通常是平台相关的,这意味着可能会在未定义相关 cc_toolchain 的平台不可用。

Google 对环境的治理非常严格——只有在公司内网的台式机可以进行编译,而台式机的环境与生产环境是完全一致的。这避免了我们现在遇到的环境治理的诸多困难,也意味着上述的密闭性不再是一个问题。

但这意味着强制所有的人使用同样版本的编译器和语言 SDK。

声明式 CI 配置

Presubmit 系统的配置 METADATA 是声明式的。由于构建系统的高度统一和良好的封装,使得用户无需配置繁琐的流水线而只需声明式地指定希望开启哪些检查即可。

METADATA 配置风格使用 textproto 作为 Schema。

与下文有关的一个例子是,当我们希望开启覆盖率红线时,只需要在配置文件中定义即可,而无需配置覆盖率前置后置插件。

rule_set {
static_analyzer {
test_coverage {
changelist_threshold:40
}
}
}

一个 Google 开源项目的 METADATA 是 madi/METADATA at master · google/madi · GitHub

Code Search

Google 的开源代码都在其对外的 Code Search,如:https://cs.opensource.google/bazel。除了缺少一些代码分析的视图,以及多了不少 bug 之外,外观较为相似。

开源项目有sourcegraph( https://github.com/sourcegraph/sourcegraph )

2.3 代码审查

(注:以下 CL = Changelist = 变更,相当于向主干的 Merge Request)

Google 已经建立了优秀的 Web 端的代码审查工具,并与电子邮件集成,允许作者请求审阅,并允许评审人按双栏视图查看 diff(使用彩色编码,注:像是工蜂的 cr 双栏视图)并对其进行评论。当 CL 作者者发起代码审查时,审查人员会收到电子邮件通知,并附有指向该 CL 的 Web 审查工具⻚面的链接。当评审人提交评审意⻅时,将发送电子邮件通知。此外,自动化工具可以发送通知,例如包含自动化测试或静态分析工具的结果。

对主要源代码仓库的所有 CL 必须由至少一名(除作者外)工程师审查。此外,如果 CL 的作者不是被修改文件的所有者之一,则至少有一个代码所有者必须审阅并批准 CL。

在特殊情况下,子目录的所有者可以在代码审查前提交对该子目录的紧急更改 CL (注: TBR, To Be Reviewed),但仍必须指定评审人,并且 CL 作者和评审人将自动被提醒,直到 CL 被评审并批准。在此情况下,由于原始 CL 已被提交,处理评论意⻅所需的任何修改必须发起另一个 CL 作为处理依据。

Google 有些工具(注: 如 gwsq)可以通过查看被修改代码的所有权和作者、最近评审人的历史以及每个潜在评审人的待处理代码审阅数量,自动为给定的 CL 建议评审人。任何修改的文件至少一个 OWNER 必须 CR 并批准该 CL。但除此之外,作者可以自由选择他们认为合适的评审人。

代码审查的一个潜在问题是,如果审查人员反应慢或过于不愿批准 CL,将会影响开发速度。代码作者能够选择他们的评审人,这有助于避免此类问题,使工程师能够避开吝于分享个人代码的评审人,或者将对简单变更的请求发送给过审快的评审人,并将对更复杂变更的审阅请求发送给更有经验的评审人或多个评审人。

每个项目的代码审查讨论会自动复制到指定的邮件列表中。任何人都可以在 CL 提交之前和之后对该 CL 发表自由评论,无论他们是否被指定为该 CL 的评审人或批准人。若发现问题,人们通常会回溯到引入该问题的 CL,并在原始 CR 消息流上发表评论予以指出,以引起原作者和评审人注意。

也可以向多个评审人发送代码审阅,然后在其中一个评审人批准后立即提交 CL(当然,前提是作者或第一个响应评审人是所有者),然后其他评审人才发表评论,在后续 CL 中处理任何后续审查意⻅。这可以减少审核的周期。

除了仓库的 main 部分之外,仓库中有一个“实验”(注: depot/google3/exprimental/...)部分,正常的代码审查要求在其中不作为强制要求。但是,在生产环境中运行的代码必须位于仓库的 main 部分,强烈鼓励工程师在仓库的主要部分开发代码,而不是在实验中开发然后将其移至主要部分,因为 CR 在开发代码时完成比在事后完成更有效。在实践中,工程师甚至会要求对实验目录内的变更做 CR。

鼓励工程师编写小的 CL。最好将较大的 CL 拆分为一系列较小的 CL,以便评审人可以轻松地一次审阅。这也使作者更容易回应在审阅时建议的大的调整:大的 CL 通常过于僵硬而难以修改,使得作者更难采取评审人的建议。鼓励保持小 CL 的一种方法是代码审查工具主动标记 CL 的大小,添加/删除/移动 30-99 行的 CL 被标记为“中等大小”,超过 300 行的 CL 被标记为负面色彩的标签,例如“large (300-999),“freakin huge”(1000-1999)等。

(注:似乎后来有过调整,范围如下:S: [0, 30), M: [30, 250), L: [250, 1000), XL: [1000, infinity) )

注解:

  • 对应 SE@G 的第 19 章 Critique: Google's Code Review Tool

  • 以及第 9 章 Code Review

Code Review

腾讯工蜂实现了上文所描述的 CR 工具的主要功能,包括评审视图、OWNERS、待评审页面、MR 可以添加抄送人、与 TAPD 的关联等。

文中描述的 CR 工具的开源实现是 Gerrit。(https://github.com/GerritCodeReview/gerrit)

experimental/

experimental/ 目录的实践类似于个人实验代码,通常不会正式上线。

2.4 测试

单元测试在 Google 强烈鼓励并广泛实践。生产环境中使用的所有代码都应进行单元测试。如果添加的源文件没有进行相应的测试,CR 工具将突出显示。代码评审人通常要求任何新功能的更改也应添加新测试以覆盖。Mock 框架(即使对于依赖于重量级库的代码也允许构建轻量级单元测试)非常流行。

集成测试和回归测试也被广泛实践。

正如所讨论的 Presubmit ,测试可以作为代码审查和提交过程的一部分自动执行 (注:自动化测试平台称为 TAP = Testing Automated Platform)。

Google 也有用于测量测试覆盖率的自动化工具 (注:Zapfhahn,“水龙头”的意思,可能是 TAP 的双关梗)。结果还集成为源代码浏览器(注: Code Search/Critique)中的可选层。

部署前的负载测试在 Google 也是必须的。团队需要制作一张表格或图表,显示关键指标(尤其是延迟和错误率)如何随传入请求率变化。

注解:

  • 对应 SE@G 的第 11 章到第 15 章

  • 关于测试类型,更详细的介绍可参见 How Google Tests Software

  • 关于测试的更多实践可参见 Google Testing Blog

TAP

TAP 的具体设计类似于这个文档的描述(当然 TAP 更复杂得多。

Zapfhahn 和公司普遍使用的覆盖率平台较为相似。腾讯工蜂也支持将覆盖率的结果会直接显示在 CR 界面(通过开启 TCoverage 视图)。

2.5 缺陷管理

Google 使用称为 Buganizer 的缺陷管理系统来跟踪 Issue:Bug、Feature Request、Client Issues 和 Process(例如发布或清理工作)。Issue 会被分类为分层的组件(注:如 Geo -> Directions -> Navigation -> Transit Navigation),每个组件可以有一个默认的指派人(assignee)和默认的抄送(cc)列表。 发起 CR 时,系统会提示工程师将 CL 关联 Issue。

Google 的团队经常(尽管不是普遍的)定期扫描其组件中的未解决问题,确定它们的优先级,并在适当的时候将它们分配给特定的工程师(注: 分类分配过程被称为 triaging)。一些团队有一个特定的人负责错误分类,其他人在他们的定期团队会议上进行错误分类。Google 的许多团队都使用了标签来指示错误是否已分类,以及每个错误的目标版本是在哪个版本中被修复。

注解:

  • 在 SE@G 中没有对应的章节。

  • Google Issue Tracker 是 Buganizer 的开源版:https://issuetracker.google.com/

Image

值得一提的是,类似于代码托管的思路, Buganizer 中的绝大多数项目的 Issue 都是公开的,并且所有人都可以自由地添加评论甚至修改。大部分产品的内部反馈 Bug 都是通过 Buganizer,与其它的项目本身的需求相同。团队在 Tiraging 的时候也会负责回复或归类内部反馈的 Bug。

Google 没有统一的项目管理工具,也没有需求标准化,敏捷、看板等项目管理方法论都是通过民间传播。这主要是因为不同的团队的项目管理风格差距很大,工具的选择也各不相同。有的团队使用 Buganizer 来管理需求,有的团队使用 Google Sheets 并与 Buganizer 关联(通过 Buganizer 提供的 API 以及 Google Sheets 提供的编程能力),有的团队使用更复杂的项目管理工具,如 Planr(像 TAPD 的需求版块)或 Kanban (像 TAPD 的看板)。

但是,这些项目管理工具通常不使用自己的存储,而是通过Buganizer API,将需求和工具记录在 Buganizer。因此,Buganizer 比起缺陷管理系统,更像是一个数据库——这是 Google 的大部分底层工具的设计偏好——以 API 为中心,提供开放的平台以方便别人在上层继续搭建合适的工具。

2.6 编程语言

Google 内部强烈鼓励软件工程师使用 Google 官方批准的五种编程语言之一进行编程:C++、Java、 Python、Go 或 JavaScript。最大限度地减少使用的不同编程语言的数量可以降低代码重用和程序员协作的成本。 (注:Kotlin 在 2020 年成为第五种后台通用语言。 JavaScript 不是后台通用语言,Google 极少使用 Node.js。)

Google还有对于每种语言的⻛格指南(注:style guide),确保整个公司的代码都以相似的⻛格、布局、命名约定等为基础进行编写。此外,还有一个全公司范围的可读性(注:readability)培训过程,关注代码可读性的有经验的工程师通过 CR 实质性更改(注: one-off readability approval)或一系列 CL 的评审(注:incremental readability approval)来培训其他工程师如何用特定语言编写可读的、惯用的代码,直到评审人(注:readability approver)对作者知道如何用该语言编写可读代码感到满意为止。每个以特定语言添加重要新代码的更改都必须得到已获得该语言“可读性”认证的人员的批准。

除了这五种语言,还有许多专⻔领域特定语言用于特定目的(例如,用于指定构建目标及其依赖项的构建语言。注:Starlark)。

不同编程语言之间的交互主要通过 Protocol Buffers。Protocol Buffers 是一种以高效且可扩展的方式对结构化数据进行编码的方法。它包括用于指定结构化数据的特定领域语言,以及接受此类描述并生成 C++、Java、Python 等代码的编译器,用于构建、访问、序列化和反序列化这些对象。Google 的 Protocol Buffers 版本与 Google 的 RPC 库(注:内部的 Stubby,开源的 gRPC)集成,支持简单的跨语言 RPC。请求和响应的序列化和反序列化由 RPC 框架自动处理。

流程一致性 是在有庞大的代码库和多种语言,简化开发的关键:有一组命令可以执行所有常⻅的软件工程任务(例如检出、编辑、构建、测试、审查、提交代码、提起 bug 等)并且无论什么项目或语言都可以使用相同的命令。开发人员无需因为他们正在编辑的代码恰好属于不同项目或用不同语言编写,就必须学习新的开发流程。

注解:

  • 风格指南对应 SE@G 的第 8 章: Style Guide and Rules

Style Guide

Google Style Guide 开源在 Google Style Guides | styleguide

Readability

腾讯工蜂实现了可读性认证的功能。仓库可以根据自己需求选择是否开启。

Google 历史上只有 one-off readability approval。最近几年 Google 在全面转向 incremental readability approval。

腾讯 PCG 的可读性认证是对 Google 的可读性认证的一种本土化尝试,自2021年初由顾问乔梁老师推动并实施,现已形成较完备的体系。最初,代码可读性认证分为三个等级的考试,现在简化为两个,绿带与红带。

其它语言

虽然 C++/Java 等是官方推荐的语言,Google 代码库中仍然有大量不同业界流行语言的代码。这主要是由于大量的收购。Google 内不同语言的爱好者会提供对该语言的非官方的支持,例如 Haskell,Rust 等。

Google 内部有大量的领域特定语言。出于笔者不知道的原因,Google 内部非常喜欢为系统设计特殊的 DSL,例如 Borgmon(Borgmon 甚至有自己的 readability),blueprint,mash,GCL (以及 BCL = GCL + Borg built-in), Piccolo,Starklark,等等,并在他们开源的系统里又发明了一些新的 DSL,如 Jsonnet(https://jsonnet.org/),CUE(https://cuelang.org/) 等。但又出于某些原因,他们把 K8s 工程师变成了 yaml 配置工程师,而 Google 内部不使用 yaml。

2.7 调试和分析工具

Google 的服务通常自动链接一些库,这些库提供了大量用于调试正在运行的服务器的工具。在服务器崩溃的情况下,一个中断(signal)处理器会自动将 Stack Trace 转储到日志文件,并保存 Core Dump 文件。如崩溃是由于 OOM 所致,中断处理器会采样当前堆上对象的 allocaiton-site,并 dump 其 Stack Trace 到日志文件。

此外,还有用于调试的 Web 界面,允许检查上游和下游的 RPC(包括时间、错误率、QPS 限制等)、变更配置(例如,增加特定模块的日志记录详细程度)、资源消耗、profiling,等等。这些工具极大地提高了调试的整体便利性,以至于工程师很少启动传统调试器(如 gdb)。

2.8 发布工程

有些团队会配置专⻔的发布工程师。但对于 Google 的大多数团队而言,发布工程工作是由项目开发者兼职的。

对于大多数软件而言,最少每周或每两周发布一次是一个共识,有些团队甚至每天发布一次。 这是通过自动化大部分正常的发布工程任务实现。频繁发布有助于保持工程师的积极性(如果某个东西要到几个月甚至几年后才发布,就很难对它感到兴奋),并通过允许更多的迭代来提高整体速度,从而获得更多更及时的反馈,并进一步地,有更多的机会及时响应反馈。

发布通常从一个新的工作区开始,通过同步到 “LAST_GREEN” 构建的更改快照(即所有 Postsubmit 通过的最晚的 CL),并创建一个发布分支。发布工程师可以选择 cherry-pick (即从主分支合并到发布分支)其他更改,然后对软件进行重建并运行测试。如果任何测试失败,则会进行额外的更改以修复失败,并且这些额外的更改会被 cherry-pick 到发布分支上,之后将重建软件并重新运行测试。当测试全部通过时,构建的可执行文件和数据文件被打包。所有这些步骤都是自动化的,因此发布工程师只需运行一些简单的命令,甚至只需在 UI 上点点点,以挑选那些需要被变更的选项。

一旦 Release Candidate 构建被打包,它通常被加载到一个 Staging 环境进一步一小部分用户的集成测试(有时只是开发团队)。

通常,发布系统可能会采用以下有效的技术保证发布质量:复制来自 Prod 环境流量(一个子集)的请求的副本,将其发送到 Staging 服务器。但这些相同的请求也会发送到当前的生产服务器以进行实际处理。(注:即流量转发)来自 Staging 的响应被丢弃,来自 Prod 的响应被发送回用户。这有助于确保在正式发布到 Prod 之前检测到任何可能导致严重后果(例如服务器崩溃)的问题。

下一步通常是向一个或多个 Canary 环境(注:即金丝雀环境)发布。 Canary 环境的流量是处理实时 Production 流量的一个子集。与 Staging 服务器不同,这些服务器处理和响应真实用户。

最后,该版本可以发布到所有数据中心的所有 Prod 服务器上。对于高流量、高可靠性的服务,会通过在几天之内 rollout,以减少未被任何先前的步骤捕获的错误造成线上事故(如服务中断)的可能。

有关 Google 发布工程的更多信息,请参阅 SRE 书籍 [7] 的第 8 章。另⻅ [15]。

注解:

  • 持续部署对应 SE@G 的第 24 章 Continuous Delivery。

制品管理

Google 的一个制品管理工具称为 MPM。具体的介绍Distributing Software in a Massively Parallel Environment | USENIX(https://www.usenix.org/conference/lisa14/conference-program/presentation/mcnutt)

Google 的一个发布系统是 Rapid。具体的介绍见 SRE 书籍的第 8 章。更复杂的发布流程是 Sisyphus(已经 deprecated)。新一代的发布系统的设计变成了意图式声明(intention-based declaration)——用户不再声明发布具体流程,而是声明发布意图,由系统完成具体的调度。

持续发布

虽然发布系统支持 cherry-pick,但是在实际后台发布中并不常见。如果部署流程失败,大部分团队只会中止发布,等待下个版本修复后发布,而非 cherry-pick。毕竟下一个版本很快就会到来。如果已经上线后出现问题,大部分情况下采取的措施是回滚,而非继续 cherry-pick。毕竟 cherry-pick 的修复很难保证已经完整解决问题。在 Google,即使是内部工具团队,也很少会有“两个小时内紧急响应用户需求”这种 OKR。

一个基于类似理念和假设设计的自动化的发布系统是由顾问乔梁老师主导设计建设的BG内 CICD标准化平台,即大运河系统。该系统是从顶层设计开始,践行“XAC(everything as code)。

Image

2.9 上线批准

(注: 上线为原文 launch,即功能的发布上线)

任何用户可⻅的更改或重大设计更改的上线,均需获得实施更改的核心工程团队之外的许多关系人的批准。一些特别批准(通常需要进行详细审查)以确保代码符合法律要求、隐私要求、安全要求、可靠性要求(例如,具有适当的自动监控以检测服务器中断并自动通知适当的工程师)、业务要求等。

上线流程还旨在确保将任何重要的新产品或功能发布时通知公司内相关人员。

Google 有一个内部发布批准工具(注: Ariane),用于跟踪所需的审查和批准,并确保符合每个产品定义的发布流程。这个工具易于定制,因此不同产品或产品领域可以有不同的审查和批准集。

有关上线批准的更多信息,请参阅 SRE 一书 [7] 的第 27 章。

2.10 复盘(Post-mortems)

每当我们的任何生产系统出现严重中断或类似事故时,相关人员都需要编写一份复盘报告。此报告描述了事件,包括标题、摘要、影响、时间表、根因、有效/无效的尝试以及操作项。重点是问题,以及将来如何避免这些问题,而不是责备人或推卸责任(即对事不对人)。影响的部分尝试根据中断持续时间、丢失查询(或失败的 RPC 等)的数量和收入来量化事件的影响。时间线部分给出了导致中断的事件的时间线以及诊断和纠正它所采取的步骤。什么有效/什么无效则描述了经验教训——哪些实践有助于快速检测和解决问题,出了什么问题,以及可以采取哪些具体行动(最好作为缺陷分配给特定人员)来减少将来出现类似问题的可能性和/或严重性。

有关 Google 复盘文化的更多信息,请参阅 SRE 一书 [7] 的第 15 章。

注解:

  • Google 的复盘模板(中文版): https://docs.google.com/document/d/1PfnPMEY-XUOpg0DrsUnHVuDMGg4WOhqrVUq3JyDXhXY

2.11 频繁重写

Google 的大多数软件每隔几年就会被重写一次。

(注:注意是重写,不是重构。是从头完全重写。)

这看起来可能非常昂贵。实际上,它消耗了Google 的很大一部分资源。然而,它也有其重要性,这些好处是 Google 的敏捷性和⻓期成功的关键。在几年时间里,随着软件环境和围绕它的其他技术的变化,同时技术或市场的变化会影响用户的需求、愿望和期望,通常会使产品需求会发生显著变化。(1)几年前的软件是围绕一组较旧的需求设计,而不是以最适合当前需求的方式设计的。(2)此外,它通常已经积累了大量的复杂性。重写代码消除了所有不必要的累积复杂性,这些复杂性是为了解决不再重要的需求。(3)此外,重写代码是一种将传授知识和传递主人翁意识(ownership)给新团队成员的方式。这种主人翁意识对于生产力至关重要:工程师自然会投入更多精力来开发功能并修复他们认为属于“他们”的代码中的问题。

频繁的重写还促进了工程师在不同项目之间流动,这有助于思想传播。

频繁重写还有助于确保使用现代技术和方式进行代码编写。

注解:

  • Goomics 最著名的漫画之一:在 Google 内只有两种产品,一种已经 deprecated,另一种是 under construction。

Image

https://goomics.net/50/

这不全是玩笑——真的会出现 deprecated 产品强行下线、但新的还在开发阶段这种情况。

3

项目管理

3.1 20% 时间

工程师可以将最多 20% 的时间花在他们选择的任何项目上,而无需他们的经理或其他任何人的批准。

出于多种原因,这种对工程师的信任非常重要。

  • 首先,它允许任何有好想法的人,即使是其他人不会立即认为有价值的想法,也可以有足够的时间来开发原型、样稿或演示来展示他们的想法的价值。

  • 其次,它为管理层提供了对创新活动的可⻅性,否则这些活动可能会被埋没。在其他没有这 20% 时间官方政策的公司中,工程师有时会在不通知管理层的情况下从事“臭鼬工厂”(注:即偷偷执行的项目)的项目。如果工程师能够公开此类项目,在他们的定期状态更新中描述他们在此类项目上的工作,即使在他们的管理层可能不同意项目价值的情况下也是如此,这会更好。拥有公司范围内的官方政策和支持它的文化使这成为可能。

  • 第三,通过允许工程师将他们的一小部分时间花在更有趣的事情上,可以让工程师对他们所做的事情保持动力和兴奋,并防止他们因为将100% 的时间花在更繁琐的工作上而变得精疲力竭。敬业、积极进取的工程师和精疲力尽的工程师之间的生产力差异是远超20%的。

  • 第四,鼓励创新文化。看到其他工程师从事有趣的实验性 20%项目会鼓励每个人都这样做。

3.2 目标和关键结果 (OKR)

Google 的个人和团队需要明确记录他们的目标,并评估他们在实现这些目标方面取得的进展。团队设定季度和年度目标,并以可衡量的关键结果显示实现这些目标的进展。这在公司的每个层级上都会做,一直到为整个公司确定目标。个人和小团队的目标应与其所属的更广泛团队的更高层次目标以及公司的整体目标保持一致。在每个季度末,记录可衡量关键结果的进展情况,并为每个目标打分,从 0.0(无进展)到 1.0(100% 完成)。OKR 和 OKR 分数通常在整个 Google 中可⻅(偶尔会出现特别敏感的信息,例如高度机密的项目),但它们不是直接用作个人绩效评估的输入。

OKR 应该设置得较高:期望的目标总体平均得分为 65%,这意味着鼓励团队将目标设定为比实际可能完成的任务多 50% 的任务。如果一个团队的得分明显高于此,则鼓励他们为下一季度设置更雄心勃勃的 OKR(相反,如果他们的得分明显低于此,则鼓励他们在下一季度设置更保守的 OKR)。

OKR 提供了一种关键机制,用于沟通公司各部⻔的工作,并通过社会激励措施鼓励员工表现良好。工程师知道他们的团队将召开会议,对 OKR 进行评分,并且有一种自然的动力去尝试取得好成绩, 即使 OKR 对绩效评估或薪酬没有直接影响。定义客观和可衡量的关键结果有助于激发工程师力争上游的动力,引导他们做对实现共同目标具有真正具体可衡量影响的事情上。

3.3 项目审批

尽管有明确的启动批准流程,但 Google 没有明确定义的项目批准或取消流程。尽管在 Google 工作了 10 多年,现在自己也成为了一名经理,但我仍然不完全理解这样的决定是如何做出的。部分原因在于整个公司的处理方法并不统一。每个级别的经理对其团队从事的项目负责并承担责任,在他们认为合适的时候行使他们的自由裁量权。在某些情况下,这意味着此类决策是以自下而上的方式作出的,工程师可以在其团队范围内自由选择要从事的项目。在其他情况下,此类决策是以自上而下的方式做出的,由高管或经理决定哪些项目将继续进行,哪些项目将被取消。

3.4 公司重组 (注:俗称的 Reorg)

公司偶尔会做出取消大型项目的行政决定,然后许多从事该项目的工程师可能不得不寻找新团队。同样,偶尔会有“碎片整理”(注:俗称的 defrag) 工作,将分散在多个地理位置的项目合并到数量较少的地点, 一些地点的工程师需要改变团队和/或项目才能实现这一目标。在这种情况下,工程师通常可以自由地从其地理位置可用的职位中选择他们的新团队和⻆色,或者在碎片整理的情况下,他们也可以选择岗位流动留在同一个团队和项目中到不同的位置。

此外,其他类型的公司重组,如合并或拆分团队以及报告链的变化,似乎是相当频繁的,尽管我不知道Google 在这方面与其他大公司相比如何。在一个大型的、技术驱动的组织中,可能有必要进行一些频繁的重组,以避免技术和需求的变化而影响组织效率。它们可以帮助避免或减轻大型组织中“交付组织结构图”的常⻅问题,其中软件架构反映了组织的报告结构。

3.5 年度 Hackathon

Google 鼓励创新的另一种方式是举办“黑客⻢拉松”[23]。Google 的许多办公室举办一年一度、为期一周的“黑客⻢拉松”,软件工程师可以在他们的常规日程之外抽出时间来从事新的创新项目。在人们可以提出想法的启动会议之后,他们组成小团队,花一周时间根据新想法构建 demo 或原型,并在周末向观众和评委小组展示他们的 demo,这些观众和评委小组会为最佳项目颁发小奖品。不过,最大的回报是认可——以及让黑客⻢拉松项目成功蜕变为实际项目的机会。

尽管所有工程师都从他们的主管那里获得了参加此类黑客⻢拉松的许可,但许多工程师确实发现他们很难脱离日常职责,因此参与率通常相当低(例如 5-20%),尽管如此,更多人将参加最初的启动仪式和/或最后的演讲,并可能从提出的想法中得到启发。

4

人员管理

4.1 角色

正如我们将在下面更详细地解释的那样,Google 将工程和管理的职业发展路径分开,将技术领导角色与管理分开,将研究嵌入工程中,并为工程师提供产品经理、项目经理和 SRE 的支持。至少看起来,其中一些实践对于维持 Google 已经形成的创新文化很重要。

Google 在工程领域有少量几种⻆色。在每个⻆色中,都有其职业发展的可能性,包括一系列级别,以及晋升的可能性(与薪酬相关的提升,例如薪水)以认可下一级别的绩效。

主要⻆色如下:

● 工程经理

这是此列表中唯一的管理⻆色。有其它头衔的人,例如软件工程师,也可能会管理人,但工程经理总是会管理人。工程经理通常是前软件工程师,并拥有相当的技术专长和人际交往能力。

技术领导Tech Lead 和人员管理之间存在区别。工程经理不一定领导项目;项目由 Tech Lead(TL) 领导。TL 可以是工程经理,但更常⻅的是软件工程师。项目的 Tech Lead 对该项目的技术决策拥有最终 决定权。经理负责选择 Tech Lead,并负责其团队的绩效。他们进行职业发展的指导和协助,进行绩效评估(根据同事反馈,⻅下文),并负责某些方面的薪酬。他们还负责部分招聘过程。

工程经理通常直接管理 3 到 30 人,但最常⻅的是 8 到 12 人。

● 软件工程师(SWE)

大多数从事软件开发工作的人都担任这个⻆色。Google 软件工程师的招聘⻔槛很高;通过只雇用非常优秀的软件工程师,可以避免或最小化许多困扰其他组织的软件开发问题。

像许多现代软件公司一样,Google 对工程和管理有不同的职业发展序列。尽管软件工程师有可能成为管理人员,或转为工程经理⻆色,但成为管理人员并不是晋升的必要条件,即使他们已经级别非常高了。高级别管理人员需要表现出领导力,但却不拘泥于形式。例如,创建具有巨大影响力或为许多其他工程师所使用的优秀软件就够了。独立的工程序列很重要,因为这意味着那些拥有出色技术技能,但缺乏成为管理人员意愿或技能的人仍有较好的职业发展道路,不需要走管理路径。这避免了一些组织遭遇的问题,即有人出于职业发展的原因最终担任管理职位,却忽视团队的人员管理。

● 研究科学家

这个⻆色的招聘标准非常严格,⻔槛非常高,需要表现出出色的研究能力,并以出色的论文发表记录和编写代码的能力为证明。学术界许多非常有才华的人有资格担任软件工程师的⻆色,但没有资格担任 Google 的研究科学家;在 Google ,大多数拥有博士学位的人都是软件工程师,而不是研究科学家。研究科学家根据他们的研究贡献(包括他们的出版物)进行评估,但除去这点和头衔不同之外,Google 的软件工程师和研究科学家⻆色之间并没有太大区别——都可以做原创研究和发表论文,都可以开发新产品创意和新技术,两者都可以并且确实会编写代码和开发产品。Google 的研究科学家通常与软件工程师一起工作,在同一个团队中从事相同的产品或相同的研究。这种将研究嵌入工程的做法极大地促进了将新研究纳入产品发布中。

● SRE

运营系统的维护由软件工程团队完成,而不是传统的系统管理员的角色,但 SRE 的招聘要求与软件工程师职位的要求略有不同(如果有网络或 unix 系统内核等专业知识进行补偿,那么对软件工程技能的要求可能会略低一些)。

SRE ⻆色的性质和目的在 SRE 书籍 [7] 中有很好的详细解释,因此我们不会在这里进一步讨论。

● 产品经理

产品经理负责产品的管理。作为产品用户的倡导者,他们协调软件工程师的工作,向用户宣传重要的功能,与其他团队协调,跟踪缺陷和进度,并确保生产高质量产品所需的一切均已到位。产品经理通常不自己编写代码,而是与软件工程师合作以确保代码正确。

● 项目经理/技术项目经理

项目经理的⻆色与产品经理大体相似,但他们管理的不是产品,而是项目、流程或运营(例如 数据收集)。技术项目经理类似,但也需要与其工作相关的特定技术专⻓,例如处理语音数据 的语言学。

软件工程师与产品经理和项目经理的比例因组织而异,但通常很高,例如在 4:1 到 30:1 的范围内。

4.2 办公室设施

Google 以其有趣的办公室设施而闻名,其中包括滑梯、球坑和游戏室。这有助于吸引和留住优秀人才。Google 优秀的餐厅对员工免费,既提供了这个功能,同时也巧妙地鼓励员工留在办公室饥饿永远不是离开的理由。经常放置免费零⻝和饮料的 Micro Kitchen 也起到了同样的作用,但也是非正式思想交流的重要来源,因为许多对话都是从那里开始的。健身房、运动和现场按摩有助于保持员工健康、快乐,提高生产力。

Google 的座位是开放式的,且相当密集。虽然存在争议 [20],但这种方式鼓励交流,有时会以牺牲个人注意力为代价,而且这也很省钱。

员工被分配到一个单独的座位,但座位被重新分配的频率很高(例如,每 6-12 个月一次,通常是由于组织扩张),经理选择座位以促进和鼓励沟通,因为相邻个体之间的沟通通常更容易。

Google 的所有办公点均设有配备最先进视频会议设施的会议室,只需在屏幕上轻按即可连接至另一方,以进行预先安排的日历邀请。

4.3 培训

Google 通过多种方式鼓励员工接受教育:

  • 新的 Google 员工(注:称为 Nooglers = New Googlers)有一个强制性的初始培训课程。

  • 技术人员(SWE 和研究科学家)从 Codelabs开始 -- 针对个别技术的短期在线培训课程,以及编码练习。

  • Google 为员工提供各种在线和面对面的培训课程。

  • Google 还为在外部机构学习提供支持。

此外,每个 Noogler 通常都会指定一名官方“导师”和一名单独的“好友”,以帮助他们快速成长。 非正式的指导也通过与经理的定期会议、团队会议、代码审查、设计审查和非正式流程进行。

4.4 换部门(注:俗称的 transfer)

鼓励公司不同部⻔之间的调动,以帮助在整个组织中传播知识和技术,并改善跨组织的沟通。在任职 12 个月后,信誉良好的员工可以在项目和/或办公室之间调动。还鼓励软件工程师在组织的其他部分执行临时任务,例如在 SRE 中进行为期六个月的“轮换”(注: 称为 mission control)。

4.5 绩效考核与奖励

Google 强烈鼓励提供反馈。工程师可以通过“peer bonus”和“kudos”相互给予明确的积极反馈。任何员工都可以提名任何其他员工获得 peer bonus ——100 美元的现金奖金 ——每年最多两次,用于激励超出正常职责范围的工作,只需填写表格来描述原因。当 peer bonus被授予时,队友通常也会收到通知。员工也可以给予“Kudos”(正式的表扬声明),为其良好的工作表现提供明确的社会认可,但没有经济奖励;对于 “Kudos”,不要求工作超出正常职责范围,也没有授予次数的限制。

经理还可以奖励奖金,包括即时激励奖金,例如项目完成。和许多公司一样,Google 员工根据其表现获得年度绩效奖金和股权奖励。

Google 有非常细致的晋升流程,包括自我或经理提名、自我审查、同行评审、经理评估;晋升委员会随后根据该意⻅做出实际决定,晋升申诉委员会可进一步审查结果。确保合适的人得到晋升,这对于保持对员工的正确激励至关重要。

另一方面,绩效不佳是通过经理的反馈来处理的,如果有必要,还可以通过绩效改进计划来处理,这些计划包括设定非常明确的具体绩效目标,并评估这些目标的进展情况。若实际表现不佳而失败,则可能会终止计划,但实际上这在Google 极为少⻅。

经理的绩效是通过反馈调查评估的;每个员工每年都被要求匿名填写两次关于其经理绩效的调查,结果被汇总后提供给经理。这种向上的反馈将有助于保持和提高整个组织的管理质量。

5

结论

我们已经对Google 使用的大部分关键软件工程实践作了简要描述。当然,Google 现在是一个庞大而多元化的组织,组织的某些部分有所不同。但这里描述的实践通常被Google 的大多数团队所遵循。

由于涉及如此多不同的软件工程实践,而且 Google 的成功还有如此多与此无关的其他原因,很难提供任何定量或客观的证据来证明单个独立实践与改进结果之间的联系。然而,这些做法在 Google 经受住了时间的考验,是 Google 成千上万优秀软件工程师集体主观判断的结果。

致谢

特别感谢 Alan Donovan 非常详细和建设性的反馈,同时感谢 Yaroslav Volovich, Urs Hölzle, Brian Strope, Alexander Gutkin, Alex Gruenstein, Hameed Husaini, Glen Shires, Niall Murphy, Ranjit Mathew, Emma Soederberg 和 Rob Siemborski 对本文早期草稿提出的非常有帮助的评论。

参考

  • [1] Build in the Cloud: Accessing Source Code, Nathan York, http://google-engtools.blogspot.com/2011/06/build-in-cloud-accessing-source-code.html

  • [2] Build in the Cloud: How the Build System works, Christian Kemper, http://google-engtools.blogspot.com/2011/08/build-in-cloud-how-build-system-works.htm

  • [3] Build in the Cloud: Distributing Build Steps, Nathan York http://google-engtools.blogspot.com/2011/09/build-in-cloud-distributing-build-steps.html

  • [4] Build in the Cloud: Distributing Build Outputs, Milos Besta, Yevgeniy Miretskiy and Jeff Cox http://google-engtools.blogspot.com/2011/10/build-in-cloud-distributing-build.html

  • [5] Testing at the speed and scale of Google, Pooja Gupta, Mark Ivey, and John Penix, Google engineering tools blog, June 2011. http://google-engtools.blogspot.com/2011/06/testing-at-speed-and-scale-of-google.html

  • [6] Building Software at Google Scale Tech Talk, Michael Barnathan, Greg Estren, Pepper Lebeck-Jone, Google tech talk.

  • http://www.youtube.com/watch?v=2qv3fcXW1mg

  • [7] Site Reliability Engineering, Betsy Beyer, Chris Jones, Jennifer Petoff, Niall Richard Murphy, O'Reilly Media, April 2016, ISBN 978-1-4919-2909-4.

  • https://landing.google.com/sre/book.html

  • [8] How Google Works, Eric Schmidt, Jonathan Rosenberg.

  • http://www.howgoogleworks.net

  • [9] What would Google Do?: Reverse-Engineering the Fastest Growing Company in the History of the World, Jeff Jarvis, Harper Business, 2011. https://books.google.co.uk/books/about/What_Would_Google_Do.html?id=GvkEcAAACAAJ&re dir_esc=y

  • [10] The Search: How Google and Its Rivals Rewrote the Rules of Business and Transformed Our Culture, John Battelle, 8 September 2005. https://books.google.co.uk/books/about/The_Search.html?id=4MY8PgAACAAJ&redir_esc=y [11] The Google Story, David A. Vise, Pan Books, 2008.

  • http://www.thegooglestory.com/

  • [12] Searching for Build Debt: Experiences Managing Technical Debt at Google, J. David Morgenthaler, Misha Gridnev, Raluca Sauciuc, and Sanjay Bhansali. http://static.googleusercontent.com/media/research.google.com/en//pubs/archive/37755.pdf [13] Development at the speed and scale of Google, A. Kumar, December 2010, presentation, QCon.

  • http: //www.infoq.com/presentations/Development-at-Google

  • [14] How Google Tests Software, J. A. Whittaker, J. Arbon, and J. Carollo, Addison-Wesley, 2012.

  • [15] Release Engineering Practices and Pitfalls, H. K. Wright and D. E. Perry, in Proceedings of the 34th International Conference on Software Engineering (ICSE ’12), IEEE, 2012, pp. 1281–1284.

  • http://www.hyrumwright.org/papers/icse2012.pdf

  • [16] Large-Scale Automated Refactoring Using ClangMR, H. K. Wright, D. Jasper, M. Klimek, C. Carruth, Z. Wan, in Proceedings of the 29th International Conference on Software Maintenance (ICSM ’13), IEEE, 2013, pp. 548–551.

  • [17] Why Google Stores Billions of Lines of Code in a Single Repository, Rachel Potvin, presentation.

  • https://www.youtube.com/watch?v=W71BTkUbdqE

  • [18] The Motivation for a Monolithic Codebase, Rachel Potvin, Josh Levenberg, Communications of the ACM, July 2016. http://cacm.acm.org/magazines/2016/7/204032-why-google-stores-billions-of-lines-of-code-in-a- single-repository/fulltext

  • [19] Scaling Mercurial at Facebook, Durham Goode, Siddharth P. Agarwa, Facebook blog post, January 7th, 2014. https://code.facebook.com/posts/218678814984400/scaling-mercurial-at-facebook/

  • [20] Why We (Still) Believe In Private Offices, David Fullerton, Stack Overflow blog post, January 16th, 2015. https://blog.stackoverflow.com/2015/01/why-we-still-believe-in-private-offices/

  • [21] Continuous Integration at Google Scale, John Micco, presentation, EclipseCon, 2013. http://eclipsecon.org/2013/sites/eclipsecon.org.2013/files/2013-03-24%20Continuous%20Integr ation%20at%20Google%20Scale.pdf

  • [22] Bazel web site. https://bazel.build/

  • [23] Unlock your team’s creativity: running great hackathons, Max Saltonstall, Google blog post, Aug 28, 2018. https://www.blog.google/inside-google/working-google/unlock-your-teams-creativity-running-gre at-hackathons/

Image

乔梁老师开课啦~视频课程《持续部署训练营(Python版)》, 限时特价!

你的软件开发效率够高吗?质量够好吗?你的团队多长时间才能向用户实时推送一个生产变更?你的软件在发布时,你是否因担心软件交付质量而感到压力倍增?你是否遇到过部署失败,甚至导致停机的情况?持续部署可以帮助你消除软件交付的痛苦,让你能专注于为客户高价值的需求,而不会因为这些交付执行类问题而花太多精力。本课程通过学练结合,理论结合实战,让你体验如何使用构建-测试-部署管道,进行持续部署。并练习如何在有效监控部署的同时,逐步发布功能特性,并作数据库结构变化。

Image

(扫码订阅)

Image