软件工程在Google

本文翻译自《Software Engineering at Google》,该文章的英文版地址是 https://arxiv.org/abs/1702.01715 。

摘要

我们整理和描述了Google的关键软件工程实践。

作者个人简介

Fergus Henderson是一位在Google工作了10年以上的软件工程师。当他在1979年还是一个孩子的时候就开始编程,之后持续在编程语言设计和实现上进行研究。 他和他的博士导师在墨尔本大学共同创建了一个研究小组,开发了编程语言Mercury。他是8个国际会议的计划委员会成员,并发布了超过50万行的开源代码。 他是Usenet新闻组comp.std.c ++的前主席,并且是ISO C和C++委员会官方认可的“技术专家”。 他拥有超过15年的商业软件行业经验。在Google,他是Blaze的原创开发人员之一,Blaze是一个现在Google使用的软件构建工具。他也致力于语音识别和语音操作(在Siri!之前)的服务器端软件和语音合成的开发。他目前管理Google的文字转语音工程小组,但仍然编写和审查了大量的程序代码。他写的软件安装在十亿多个设备上,每天使用超过十亿次。

介绍

Google已经是一个非常成功的公司。除了Google搜索和AdWords的成功之外,Google还提供了许多其他突出的产品,包括Google地图、Google新闻、Google翻译、Google语音识别、Chrome和Android。 Google还大幅增强和扩展了通过购买小型公司(如YouTube)所获得的许多产品,并对各种开源项目做出了重大贡献。Google已经展示了一些尚未推出的惊人产品,例如自动驾驶汽车。

Google的成功有很多原因,包括开明的领导力,伟大的人才,高招聘标准,以及在迅速成长的市场中成功获利的财务实力。 但其中一个原因是Google摸索出了优秀的软件工程实践,帮助它成功。这些做法随着时间的推移,根据许多最有才华的软件工程师的积累和沉淀的智慧而演变而成。我们想与世界分享我们的做法,并分享我们从错误中学到的一些教训。

本文的目的是整理并简要介绍Google的关键软件工程实践。然后,其他组织和个人可以将它们与自己的软件工程实践进行比较和对比,并考虑是否自己应用这些实践中的一些。

许多作者都有分析Google的成功和历史的书籍或文章。但大多数主要涉及商业、管理和文化;只有那些的一小部分已经探索了软件工程方面的事情,并且大多数只探索一个方面;而且没有一篇文章提供了Google整体软件工程实践的简要概述,正如本文旨在做的那样。

软件开发

源码仓库

Google的大多数代码存储在一个统一的源代码仓库中,并且可供Google的所有软件工程师访问。当然有一些值得注意的例外,特别是两个大型开源项目Chrome和Android,它们使用单独的开源仓库,以及一些高价值或关键安全的代码,其读取访问被限制得更紧。但大多数Google项目共享相同的仓库。截至2015年1月,这个86 TB的存储库包含了10亿个文件,包括超过900万个源代码文件,包含总共20亿行源代码,具有3500万次提交的历史和每天的4万提交的变化率。 对存储库的写访问是被控制的:只有存储库的每个子树的所有者可以批准对该子树的更改。但一般来说,任何工程师都可以访问任何代码段,可以检查它并构建它,可以进行本地修改,可以测试它们,并可以发送更改供代码所有者审核,如果所有者批准,可以合并这些代码更改。 在文化上,鼓励工程师修复他们看到的任何东西,并且知道如何修复,无论项目边界如何。这导致出现更高质量的基础设备以便更好的满足使用它的人的需求。

几乎所有的开发都发生在仓库的“头”,而不是在分支上。这有助于及早识别集成问题,并最大限度地减少所需的合并工作量。它还使得更容易和更快地推出安全修复补丁。

自动化系统经常在每次更改任何文件之后运行测试。当代码更改的测试失败时,这些系统自动通知代码更改作者和审阅者,这通常在几分钟之内。大多数团队通过安装显示屏或者是有颜色编码的灯来表示他们当前代码构建的状态(绿色表示成功构建和所有测试通过,红色表示一些测试失败,黑色表示构建失败)。 这有助于将工程师的注意力集中在保持绿色状态,大多数更大的团队还有一个“构建警察”,负责确保测试持续通过,并与没有通过测试的代码更改的作者合作,以快速解决任何问题,或者回滚有重大问题的代码变更。构建警察角色通常在团队之间或在其经验丰富的成员之间轮流。这种集中关注绿色状态的习惯,使得开发变得实用,即使对于非常大的团队。

代码所有权。存储库的每个子树具有一个“所有者”文件,里面包含该子树的“所有者”的用户ID。子目录还从父目录继承所有者,但可以选择禁止。每个子树的所有者控制对该子树的写访问,如下面的代码审查部分所述。每个子树需要至少有两个所有者,虽然通常有更多,特别是在地理分布的团队。通常将整个团队列在所有者文件中。 Google的任何人都可以对子树进行代码更改,而不仅仅是所有者,但必须获得所有者的批准。这确保每个代码更改由理解该软件的工程师进行审核。

构建系统

Google使用称为Blaze的分布式构建系统,该平台负责编译和链接软件以及运行测试。它提供了用于构建和测试的标准命令。这些标准命令和高度优化的实现意味着,对于任何Google工程师来说,构建和测试存储库中的任何软件通常非常简单和快速。这种一致性是一个关键的推动因素,有助于使工程师能够跨项目边界进行代码更改。

程序员编写“BUILD”文件,Blaze用它来确定如何构建他们的软件。 构建实体包括函数库、程序、测试等,我们使用高级构建规范语言来声明这些实体,为每个实体指定名称、源文件以及它所依赖的库或其他构建实体。 这些构建规范包括称为“构建规则”的声明,每个都指定高级概念,如“这里是一个C ++库,这些源文件取决于这些其他库”,并且由构建系统映射每个构建规则到一组构建步骤,例如编译每个源文件的步骤和用于链接的步骤,以及用于确定使用哪个编译器和编译标志。

在某些情况下,特别是Go程序,可以自动生成(和更新)构建文件,因为BUILD文件中的依赖性信息是(通常)源文件中的依赖性信息的抽象。但是,他们仍然检入存储库。这确保构建系统可以通过仅分析构建文件而不是源文件来快速确定依赖性,并且避免构建系统和用于所支持的许多不同编程语言的编译器或分析工具之间的过度耦合。

构建系统的实现使用Google的分布式计算基础架构。每个构建的工作通常分布在数百甚至数千个机器上。这使得可以快速构建极大的程序或并行运行数千个测试。

各个构建步骤必须是“封闭的”:它们仅依赖他们所声明的输入。强制所有依赖关系声明正确是分发构建的结果:只有声明的输入被发送到运行构建步骤的机器。因此,构建系统可以依赖真正的依赖关系。即编译系统调用的编译器也被视为输入。

单独构建步骤是确定性的。因此,构建系统可以缓存构建结果。软件工程师可以将它们的工作空间同步到旧的更改号码,并且可以重建,并且将获得完全相同的二进制文件。此外,该高速缓存可以在不同用户之间安全地共享。 (为了正常工作,我们必须消除由构建调用的工具中的非确定性,例如通过清除生成的输出文件中的时间戳)。

构建系统是可靠的。构建系统跟踪对构建规则本身的更改的依赖关系,并且如果生成目标的操作更改,即使该操作的输入没有改变,也知道重建目标,例如当只更改编译器选项时。它也会正确处理构建部分被中断,或在构建期间修改源文件:在这种情况下,您只需要重新运行build命令。没有任何动作需要执行,比如相当于“make clean”的动作。

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

增量重建是快速的。该构建系统记录存储器用于重建它可以增量地分析自从上次构建以来已经改变的文件。

预先检查。 Google提供了在启动代码审查和/或准备向存储库提交更改时自动运行一系列测试的工具。 存储库的每个子树可以包含一个配置文件,该配置文件确定要运行哪些测试,以及是在代码审查时还是在提交之前立即运行它们,还是两者都运行。 测试可以是同步的,即在发送更改以进行审查之前和/或在将更改提交到存储库之前运行(对快速运行测试有利); 或异步,结果通过电子邮件发送到审查讨论主题中。

代码审查

Google已经建立了完善的基于Web形式的代码审查工具,并与电子邮件整合,允许代码更改的作者要求审核,并允许审核者查看代码差异(在网页中使用漂亮的颜色来表示各种代码)并对其进行评论。当更改作者发起代码审查时,系统会通过电子邮件通知审核者,并提供指向该网页的链接。当审核人提交审核评论时,系统会发送电子邮件通知。此外,自动化工具可以发送通知,包含例如自动化测试的结果或静态分析工具的结果。

对主源代码存储库的所有更改必须至少由另一位工程师进行审核。此外,如果更改的作者不是正在修改的文件的所有者,则至少有一个所有者进行审核并批准该更改。

在特殊情况下,子树的所有者可以直接合并紧急的代码更改,随后再进行代码审查。在这种情况下,为解决审核意见所需的任何代码修改必须单独进行,因为原始代码更改已经被提交。

Google有一些工具可以自动建议审核人,这通过分析正在修改的代码的所有者和作者,最近审核人的历史记录以及每个潜在审核人的待审代码数量。变更所影响的每个子树的至少一个所有者必须审核并批准该更改。但除此之外,作者可以自由选择审查者,只要他们认为合适。

代码审查的一个潜在问题是,如果审查者的响应太慢,或者不情愿批准更改,这可能会减慢开发速度。 代码作者可以选择他们的审查者的规则有助于避免这样的问题,允许工程师避免哪些过度强势的审查者,或者发送简单的代码更改给一般的审查者,并且将更复杂的的代码更改发送给更有经验的审查者们。

每个项目的代码审查讨论被自动复制到项目维护者指定的邮件列表中。任何人都可以对任何更改发表评论,无论他们是否被指名为该代码更改的审查人,无论是在代码更改合并之前还是之后。如果发现错误,通常追踪引入它的代码更改,并在原始代码审查讨论主题发表评论,指出错误,以便原始作者和审查者知道它。

还可以同时向几个审查者发送代码评审,一旦其中一个审查者批准(当然作者或第一个作出回应的审阅者是所有者),则代码变更被合并,随后的审查意见将在后续更改中处理。这可以减少审查者的处理时间。

除了存储库的主要部分,存储库中有一些“实验性”部分,不强制执行正常的代码审查要求。但是,在生产环境中运行的代码必须位于存储库的主要部分,并且非常强烈地鼓励工程师在存储库的主要部分开发代码,而不是开发实验性代码,然后将其移动到主要部分,因为代码审查是最有效的。实际上,工程师经常要求代码评审,即使是实验代码。

鼓励工程师提交小的单独的代码更改,大的代码更改最好分成一系列更小的代码更改,审查者可以轻松地一次查看。这也使作者更容易响应审查者提出的评论;非常大的代码变更通常太僵硬,并阻碍审查者提出建议。 鼓励提交小的代码更改的一种方法是代码审查工具标记每个代码变更的变化的大小的描述,添加/删除 30-99行的变化标记为“中型”,300行以上的变化标记为越来越大的标签,例如“大”(300-999),“巨大”(1000-1999)等。

测试

我们强烈鼓励并广泛使用单位测试。生产中使用的所有代码都需要进行单元测试,代码审查工具将突出显示是否添加了源文件而没有相应的测试。代码审查人员通常要求添加新功能的任何更改都应添加新测试以涵盖新功能。模拟框架(允许构建轻量级单元测试,甚至对于具有对重量级库的依赖的代码)是非常普遍的被使用。

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

如上面“预提交检查”中所述,测试可以作为代码审查和提交过程的一部分自动执行。

Google还提供用于测量测试覆盖率的自动化工具。结果也被集成为源代码浏览器中。

在部署之前进行压力测试也是Google的重点。团队需要生成一个表格或图形,显示关键指标(特别是延迟和错误率)如何随传入请求的速率而变化。

错误跟踪

Google使用一个名为Buganizer的错误跟踪系统来跟踪问题:Bug,功能需求,客户问题和流程(如发布或清理工作)。 错误被分类到不同的组织中,每个组织可以有一个默认的受托人和默认电子邮件列表。 当发送代码更改更改以供审查时,系统会提示这个代码更改涉及的问题的组织的工程师。

Google的团队通常定期扫描其组织中的没有被解决的问题,并确定优先级,并在适当时将其分配给特定工程师。 一些团队有一个特定的个人负责错误分类,其他人在他们的常规团队会议中进行错误分类。 Google的许多小组都使用错误标签来指明是否已对错误进行了分类,以及每个错误所针对的发布版本。

编程语言

Google的软件工程师被强力鼓励使用以下四种官方认可的编程语言之一进行编程:C ++,Java,Python或Go。最小化所使用的编程语言的数量减少了对于代码重用和程序员协作的障碍。

每种变成语言都有Google风格指南,以确保整个公司的代码都具有类似的风格,布局,命名约定等。此外,还有一个公司范围的可读性培训流程,由经验丰富的工程师来训练其他工程师如何以编写可读强的代码,通过检查一个或多个代码变更,直到审查者确信作者知道如何用该语言编写可读性代码。每个以特定语言添加重要的新代码的更改都必须由已通过该语言的“可读性”培训的人批准。

除了这四种语言之外,许多领域专用语言用于特定目的(例如用于指定构建目标及其依赖性的构建语言)。

这些不同的编程语言之间的互操作主要使用协议缓冲区(Protocol Buffers)。协议缓冲区是一种以高效但可扩展的方式编码结构化数据的方法。它包括一个用于指定结构化数据的领域特定语言,以及一个编译器,它接受这样的描述,并生成C ++,Java,Python中的代码,用于构建,访问,序列化和反序列化这些对象。 Google的Protocol Buffers版本与Google的RPC库集成,支持简单的跨语言RPC,对RPC框架自动处理的请求和响应进行序列化和反序列化。

开发过程的通用性是使开发变得容易的关键,即使具有巨大的代码库和多样化的语言:有一组命令来执行所有常见的软件工程任务(例如签出,编辑,构建,测试,审查,提交,文件错误报告等)在不同的项目和语言上。开发人员不需要学习新的开发过程。

调试和分析工具

Google的服务程序与工具库相链接,这些工具库提供了许多用于调试运行状态服务程序的工具。 在服务程序崩溃的情况下,信号处理程序将自动将堆栈跟踪信息转储到日志文件,以及保存核心文件。 如果崩溃是由于堆内存不足,服务器将转储活动堆对象的采样子集。工具库还有用于调试的网络接口,其允许检查传入和传出的RPC调用统计信息(包括定时,错误率,速率限制等),改变标志值(例如以增加特定模块的日志输出级别),资源消耗,分析 , 和更多。

这些工具大大增加了调试的便利性,以至于很少启动传统的调试器(如gdb)。

发布工程

有些小组有专门的发布工程师,但对于Google的大多数小组,发布工作由专职的软件工程师完成。

大多数软件经常发布新版本; 每周或每两周发布一个版本,一些团队甚至每天都发布一个版本。这是通过自动化的发布工程任务实现的。经常发布有助于保持工程师的积极性(如果它在几个月甚至几年后发布,就很难激发),并通过允许更多的迭代增加总体速度,从而获得更多的反馈机会和更多的机会在给定时间内响应反馈。

通常通过使用最新的“绿色”构建(即,所有自动测试通过的最后一个改变)的改变号来创建发布分支,并在新的工作区中开始发布。发布工程师可以选择额外的更改,即把这些额外的更改从主分支合并到发布分支上。然后软件将从头重建并运行测试。如果任何测试失败,则进行额外的修改以修复问题,并且那些额外的修改被挑选到发布分支上,之后软件将被构建和测试。 当测试全部通过时,构建的可执行文件和数据文件被打包。所有这些步骤都是自动化的,所以发布工程师只需要运行一些简单的命令,甚至只需在web界面上选择一些条目进行操作,并选择哪些更改(如果有)。

一旦候选构建已经被打包,它通常被加载到“预发布”服务器上,以便由小组用户(有时仅仅是开发团队)进行进一步的集成测试

一种有用的技术将来自生产流量的请求的副本(子集)发送到“预发布”服务器,但是也将这些相同请求发送到当前生产服务器用于实际处理。来自“预发布”服务器的响应被丢弃,而来自实际生产服务器的响应被发送回给用户。这有助于确保在将“预发布”服务器投入生产之前,可以检测到任何可能导致严重问题(例如服务崩溃)的问题。

下一步是把候选构建推出到正在处理实际生产流量子集到一个或多个“金丝雀”服务器。与“预发布”服务器不同,这些是处理和响应真实用户。

最后,该版本可以推广到所有数据中心中的所有服务器。对于非常高流量,高可靠性的服务,这是在几天的时间内逐步推出,以帮助减少任何中断的影响,这些中断可能由于新引入的bug引起的,这些bug没有在之前的步骤中被发现。

上线批准

上线任何用户可见的更改或重大设计更改需要来自该更改的核心工程团队之外的许多人员的批准。需要特别的批准(通常需要详细审查),以确保代码符合法律要求,隐私要求,安全要求,可靠性要求(例如,具有适当的自动监控以检测服务程序中断并自动通知相应的工程师),业务要求,等等。

上线过程还旨在确保在任何重要的新产品或功能启动时通知公司内的适当人员。
Google有一个内部上线批准工具,用于跟踪所需的审核和批准,并确保符合每个产品定义的启动流程。此工具可轻松自定义,以便不同的产品或产品区域可以具有不同的所需的审核和批准。

故障总结

每当我们的任何生产系统发生严重停机或类似事故时,所涉人员都必须写一份故障总结报告。该文档描述了事件,包括标题,摘要,影响,时间表,根本原因,什么正常工作,什么没有正常工作,行动项目。重点是针对问题,以及如何在将来避免这些问题,而不是针对人或分摊责任。故障报告中的影响部分根据中断持续时间,丢失的查询(或失败的RPC等)数量和收入来量化事件的影响。故障报告中的时间线部分给出了导致中断的事件的时间表,以及诊断和纠正它所采取的步骤。故障报告中的什么工作/什么没有部分描述教训 – 哪些实践帮助迅速发现和解决问题,什么错误,什么具体行动(最好作为错误提交分配给特定的人)可以采取减少未来类似问题的可能性和/或严重性。

频繁重写

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

这看起来非常昂贵。事实上,它消耗了Google资源的很大一部分。然而,它也有一些关键的好处,这是谷歌的敏捷性和长期成功的关键。在几年的时间里,随着软件环境和其周围的其他技术的变化,以及随着技术或市场的变化影响用户需求,期望和预期,产品的需求通常会发生显着变化。几年前的软件是围绕一组较旧的需求设计的,通常不是以对当前需求最佳的方式设计的。此外,它通常积累了很多复杂性。重写代码消除了所有不必要的累积复杂性,这些复杂性被用于解决不再那么重要的需求。 此外,重写代码是一种向新的团队成员传递知识和所有权感的方式。这种所有权感对生产力至关重要:工程师自然会更努力地开发特性,并在他们认为是“他们的”的代码中解决问题。频繁的重写也鼓励工程师在不同项目之间的移动,有助于鼓励思想的碰撞。频繁的重写也有助于确保代码使用现代技术和方法编写。

项目管理

20%的时间

工程师被允许花费高达20%的时间在他们选择的任何项目上工作,而无需他们的经理或任何其他人的批准。这种对工程师的信任是非常有价值的,有几个原因。首先,它允许任何人有一个好主意,即使这是一个想法,其他人不会立即认出是值得的,有足够的时间来开发原型,演示或演示,以显示他们的想法的价值。其次,它向管理层提供可能隐藏的活动的可见性。在没有允许20%时间的官方政策的其他公司中,工程师有时会在不通知管理层的情况下工作在“隐秘”项目。如果工程师可以公开这样的项目,描述他们在这些项目的工作在他们的正常状态更新,甚至在他们的上级可能不同意该项目的价值的情况下,这是更好的。拥有一个全公司的官方政策和支持它的文化使这成为可能。第三,允许工程师花费一小部分时间在更有趣的东西上工作,它保持工程师的动机和兴奋。如果他们觉得被迫花费100%他们的时间工作更繁琐的任务,这会毁掉他们的积极性。拥有积极性的工程师和没有积极性的工程师之间的生产力的差异是超过20%。第四,它鼓励创新文化。当看到其他工程师工作在有趣的实验20%项目时,这会鼓励大家做同样的事情。

目标和主要结果(OKR)

Google的个人和团队需要明确记录他们的目标,并评估他们在实现这些目标方面取得的进展。团队制定季度和年度目标,可衡量的关键结果显示在实现这些目标方面取得进展。这是在公司的每一个层面上进行的,一直到整个公司的定义目标。个人和小团队的目标应该与他们所参与的更广泛团队以及整个公司目标的更高级目标相一致。每个季度末,记录可衡量的关键结果的进展,每个目标的得分为0.0(无进展)至1.0(完成100%)。 OKR和OKR分数通常在Google上可见(对于特别敏感的信息,例如高度保密的项目,偶尔有例外),但它们不直接用作个人绩效评估的输入。

OKR应该设置为高:期望的目标总平均分是65%,这意味着鼓励团队将大约50%的任务设置为比它们实际完成的任务多。如果一个团队的得分明显高于这个数字,鼓励他们在下一个季度设置更加雄心勃勃的OKR(反之,如果他们得分明显低于这个数字,鼓励他们在下个季度更加保守地设置OKR)。

OKR提供了一个关键的机制,用于公司内部沟通,并激发良好的绩效。工程师知道他们的团队将有一个会议,在这个会议上会统计个人的OKR得分,尽管OKR对绩效考核或薪酬没有直接影响,但工程师仍然会努力取得良好的成绩。定义客观和可衡量的关键结果有助于确保这种良好表现的人类驱动力被引导到对实现共同目标的进展具有实际具体可衡量影响的事情。

项目审批

尽管有一个明确定义的上线批准流程,但Google没有明确定义的项目审批或取消流程。 尽管我在Google已经有将近10年,现在已经成为一个经理,我仍然不完全明白这样的决定如何做。 在某种程度上,这是因为在整个公司,这种方法是不统一的。 每个级别的经理都对他们的团队工作的项目负责和负责,并且在他们认为合适的时候行使其自由裁量权。 在某些情况下,这意味着这种决策是以自下而上的方式进行的,工程师可以自由选择在其团队范围内工作的项目。 在其他情况下,这种决策以更自上而下的方式进行,管理人员或管理人员决定哪些项目将进行,这将获得额外的资源,并将被取消。

合作重组

偶尔,执行者决定取消一个大型项目,然后许多在该项目上的工程师可能需要在新的团队上找到新的项目。类似地,偶尔进行“碎片整理”工作,其中分散在多个地理位置的项目被合并到较少数量的位置,其中一些位置中的工程师被要求改变团队或项目以实现这一点。在这种情况下,工程师通常可以自由地从他们的地理位置中选择他们的新团队和角色,或者在碎片整理的情况下,他们也可以被选择留在同一个团队和项目,这通过移动到不同的城市来实现。

此外,其他类型的内部重组,如合并或拆分团队和报告链中的变化,似乎是相当频繁的事件,虽然我不知道Google如何与其他大公司比较。在一个大型,技术驱动的组织中,可能需要进行频繁的重组,以避免由于技术和需求的变化而导致组织效率低下。

人员管理

角色

我们将在下面更详细地解释,Google将工程和管理职业发展阶梯分离开,将技术主导角色与管理层分开,将研究嵌入工程中,并给产品经理、项目经理、站点可靠性工程师(SRE)提供工程师 。 看来,至少有一些做法对维持Google的创新文化很重要。

Google在工程中有少量不同的角色。 在每个角色中,都有一个职业发展可能,一系列的水平,以及晋升(与相关的改善薪酬,如薪水)的可能性,以承认在下一个水平的绩效。

主要角色是:

  • 工程经理

这是此列表中唯一的人员管理角色。其他角色的人员(例如软件工程师)也可以管理人员,但是工程经理总是管理人员。工程经理通常是前软件工程师,并且总是有相当多的技术专长,以及人员技能。

技术领导和人员管理之间有区别。工程经理不一定领导项目;项目由技术主管领导,他可以是一名工程经理,但更多时候是一名软件工程师。项目的技术主管对该项目的技术决策有最终决定权。

经理负责选择技术领导,以及他们团队的表现。他们执行指导和协助职业发展,做绩效评估(使用同行反馈的意见,见下文),并且负责一些方面的补偿。他们还负责招聘过程的某些部分。

工程经理通常直接管理3到30人之间,一般8到12是最常见的。

  • 软件工程师(SWE)

大多数做软件开发工作的人都有这个角色。 Google的软件工程师的招聘门槛非常高;通过聘用特别好的软件工程师,困扰其他组织的许多软件问题被避免或最小化。

Google有独立的工程和管理职业发展顺序。虽然软件工程师可以管理人员或转移到工程经理角色,但人员管理不是职业晋升的要求,即使是在最高级别。在更高层次,显示领导力是必需的,但可以有许多形式。例如,创建具有巨大影响或被许多其他工程师使用的伟大软件就足够了。这是非常重要的,因为这意味着,具有很强的技术技能但缺乏管理人的愿望或技能的人仍然有一个良好的职业发展道路,不需要他们采取管理轨道。这避免了一些组织遭受的问题,其中人们由于职业晋升的原因而最终处于管理职位,但忽略了他们团队中的人的管理。

  • 研究科学家

这个角色的招聘标准非常严格,并且条件非常高,需要表现出杰出的研究能力,包括出色的出版记录和编写代码的能力证明。许多非常有才能的学术界人士能够在Google获得软件工程师的资格,就不能再在Google上获得研究科学家的资格; 大多数博士在Google的是软件工程师,而不是研究科学家。研究科学家被评估他们的研究贡献,包括他们的出版物,但除此不同的头衔之外,软件工程师和研究科学家在谷歌的作用没有太大的区别。两者都可以做原创研究和发表论文,都可以开发新的产品思想和新技术,并可以写代码和开发产品。 Google的研究科学家通常与软件工程师一起工作,在相同的团队中工作,在相同的产品或相同的研究。这种在工程中嵌入研究的做法极大地促进了新的研究能够转化到产品中去。

  • 站点可靠性工程师(SRE)

操作系统的维护由软件工程团队完成,而不是传统的系统管理员类型,但SRE的软件工程技能的招聘要求略低于软件工程职位的要求。 SRE角色的性质和目的在SRE书中有详细的解释,因此我们不在这里进一步讨论。

  • 产品经理

产品经理负责管理产品;作为产品用户的倡导者,他们协调软件工程师的工作,传播对这些用户重要的功能,与其他团队协调,跟踪错误和计划,以及确保所需的一切都到位,以产生高质量的产品。产品经理通常不会自己编写代码,而是与软件工程师合作,以确保正确的代码编写。

  • 项目经理/技术项目经理

项目经理的角色与产品经理大致相似,但是他们不是管理产品,而是管理项目,流程或操作(例如信息收集)。技术项目经理是类似的,但也需要与他们的工作有关的专门的技术专门知识。比如,处理语音数据的语言学。

软件工程师与产品经理和项目经理的比例在整个组织中各不相同,但通常很高,例如。在4:1至30:1的范围内。

设施

Google的有趣设施非常著名,有运动室和游戏室等。这有助于吸引和留住优秀的人才。 Google的优秀咖啡馆,对员工免费,提供了这个功能,也巧妙鼓励Google员工留在办公室;饥饿绝不是离开的理由。 “微型厨房”的频繁安置,员工可以抓住小吃和饮料,也提供同样的功能,但也作为非正式的想法交流的重要来源,因为许多对话开始在那里。健身房,运动和现场按摩帮助保持员工健康,健康和快乐,这提高了生产力和保持。

Google的座位是开放式的,通常相当密集。虽然有争议,这鼓励沟通。

员工被分配一个单独的座位,但座位重新分配相当频繁(例如每6-12个月,通常由于组织扩展的结果),由管理者选择的座位,以促进和鼓励沟通。

Google的设施都配备最先进的视频会议室,连接到另一方预订的日历会议邀请只需在屏幕上轻轻一点。

训练

Google鼓励员工在许多方面受到教育:

  • 新的Google员工(“Noogler”)有一个强制性的初始培训课程。
  • 技术人员(SWE和研究科学家)从“Codelabs”开始:在线短个人技术培训课程,编码练习。
  • Google为员工提供各种在线和面对面培训课程。
  • Google还支持在外部机构学习。

此外,每个Noogler通常被指定一名官方“导师”和一个单独的“伙伴”,以帮助他们的加速成长。 非正式指导还通过与其经理,小组会议,代码审查,设计审查和非正式流程的定期会议进行。

转岗

鼓励公司不同部门之间的转岗,以帮助在整个组织传播知识和技术,并改善跨组织的沟通。 允许在12个月后处于良好状态的员工在项目和/或办公室之间进行转移。 还鼓励软件工程师在组织的其他部门进行临时指派。

绩效考核和奖励

Google极力鼓励反馈。工程师可以通过“同伴奖金”和“kudos”给彼此明确的积极反馈。任何员工都可以提名任何其他员工的“同伴奖金” – 现金奖金100美元,每年最多两次,用于奖励超越正常工作职责的队友,只需填写一个web表单描述获奖原因。当“同伴奖励”被授予时,队友也通常收到通知。员工也可以给予“kudos”,这是形式化的赞美声明,为良好的工作提供明确的社会认可,但没有财政奖励;对于“kudos”,不要求工作超出正常的职责,并且没有对它们可以被授予的次数的限制。

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

Google有一个非常仔细和详细的职业晋升流程,包括由自我或经理提名,自我审查,同行评审,经理评价;然后由晋升委员会根据这些意见作出实际决定,结果可以由晋升上诉委员会进一步审查。确保正确的人得到晋升对于为员工维持适当的激励是至关重要的。

另一方面,绩效不佳则由经理反馈处理,如果有必要,还需要制定绩效改进计划,其中包括制定非常明确的具体绩效目标,并评估实现这些目标的进展情况。如果失败,可能会导致效果不佳,但实际上这在Google上极为罕见。

经理绩效通过反馈调查进行评估;每个员工被要求每年两次填写关于他们的经理的业绩的调查,结果被匿名化和聚合,然后提供给经理。这种向上反馈对于维护和提高整个组织的管理质量非常重要。

结论

我们简要介绍了Google使用的大多数关键软件工程实践。当然,Google现在是一个庞大而多元化的组织,组织的一些部分有不同的做法。但是这里描述的做法一般由Google的大多数团队遵循。

由于涉及这么多不同的软件工程实践,以及Google成功的许多其他原因与我们的软件工程实践无关,因此很难给出任何定量或客观的证据,将各个关键实践与改进的结果联系起来。然而,这些做法是经受了谷歌时间考验的,在那里它们受到了成千上万的优秀软件工程师的主观判断。

对于那些主张使用本文中描述的特定实践的其他组织中的人来说,也许本文有助于说“这些关键软件工程实践对Google来说足够好”。

1 Comment

Leave a Reply

Your email address will not be published. Required fields are marked *