分享

Google的软件工程概述

 Rdubuis 2017-02-15

1. 介绍

Google已经是一个非常成功的公司。正如在搜索和竞价广告方面的成功一样,Google也提供了许多其他突出产品,包括Google地图,Google新闻,Google翻译,Google语音识别,Chrome和Android。Google还通过购买小公司大大增强和扩展了许多产品,例如YouTube,并对多种多样的开源项目做出了重大贡献。Google也展示了一些尚未投入市场的惊人产品,如自动驾驶汽车。


Google的成功有很多原因,包括开明的领导力,技术牛人,高标准招聘,以及成功带来的经济实力,可以在非常迅速增长的市场早期进行介入。但其中一个原因是谷歌开发出的优秀软件工程实践,这帮助谷歌走向成功。这些实践基于全球最有才华的软件工程师的大量积累和提取的智慧,随着时间的推移而不断演化。我们想跟全球各地的人们分享我们的知识与实践以及我们从中学到的一些教训。


本文的目的是记载并简要介绍Google的关键软件工程实践。其他组织和个人可以进行比较和对比,并考虑是否应用一些做法。


许多作者(例如[9],[10],[11])都有书籍或文章来分析Google的成功历史。但大多数主要涉及商业,管理和文化;只有一小部分(例如[1,2,3,4,5,6,7,13,14,16,21])谈到了软件工程方面的内容,大多数只探讨一个方面;并且没有从整体上提供一个简短的、书面的关于谷歌软件工程实践的概述,本文目的正在于此。


2. 软件开发

2.1 源码存储库

大多数Google代码存储在一个统一的源代码存储库中,Google的所有软件工程师都可以访问。有一些值得注意的例外,特别是两个大型开源项目Chrome和Android,分别使用了独立的开源代码存储库,以及一些高价值或关键的安全代码有更严格的访问限制。但大多数Google项目共享相同的存储库。自2015年1月起,这个86 TB的存储库包含了10亿个文件,包括超过900万个源代码文件,20亿行源代码,具有3500万个版本修改的历史记录和每工作日提交的4万个版本修改的变更率[18]。存储库的写访问是受控的:只有存储库的每个子分支列出的所有者才可以批准修改该分支。但一般来说任何工程师都可以访问任一代码段,可以签出并构建,可以进行本地修改,可以测试它们,并可以发送变更以供代码所有者审核,如果所有者同意,可以签入(提交)这些变更。在文化上,鼓励工程师修复他们看到的任何有问题的知道如何修复的软件,无论项目边界如何。这鼓励了工程师并带来了更高质量的基础设施,更好地满足了使用它的人的需求。


几乎所有的开发都发生在仓库的“头部head”(指git中的head),而不是在分支上。这有助于早期识别集成问题,并最大限度地减少所需的合并工作量。也更容易和更快地推出安全修复程序。


频繁运行测试的自动化系统,通常在每次更改任何文件,进行传递性依赖测试之后进行,虽然这并不总是可行的。这些系统自动通知作者和审阅者测试失败的任何变更,通常都在几分钟之内完成。大多数团队通过安装使构建的当前状态突出显示,甚至用颜色编码来表示(绿色为建立成功和所有测试通过,红色表示有一些测试未通过,黑色表示失败的构建)。这有助于工程师集中精力注意保证构建通过。大多数更大的团队也有一个“构建巡警”负责确保测试的持续通过,通过与作者合作,不期望的变更能快速修复或回滚。(构建巡警角色通常在团队或其经验丰富的成员之间轮流承担。)这种专注于保持构建通过的做法使开发在头部进行具有实用性,即使是规模非常大的团队。


代码所有权。存储库的每个分支都可以有一个列出分支“所有者”用户ID的文件。子目录还从父目录继承所有者,尽管可以有选择地限制。每个分支的所有者控制写访问权限,如下面的代码审查部分所述。每个分支都需要有至少两个所有者,虽然通常需要有更多,特别是在地理分布较远的团队。通常将整个团队列在所有者文件中。变更分支可以由Google公司的任何员工实施,不只是所有者,但必须由所有者批准。这确保每个变更由理解软件的工程师审核


有关Google源代码存储库的更多信息,请参阅[17,18,21];以及另一个大公司如何处理同样的挑战,见[19]。


2.2 构建系统

Google使用一种称为Blaze的分布式构建系统,负责构建和链接软件和运行测试。它提供了在整个存储库用于构建和测试的标准命令。这些标准命令和高度优化的实现意味着对于Google工程师构建和测试存储库中的任何软件变得相当简单和迅速。这种一致性是关键的推动者,这有助于工程师能够跨项目边界进行变更。


程序员编写“BUILD”文件,Blaze用它来确定如何构建他们的软件。构建实体(例如库,程序和测试)使用相当高级别的声明性构建规范,为每个实体指定其名称,源文件和库或其依赖的其他构建实体。这些构建规范包括称为“构建规则”的声明,每个都指定高级概念,如“这是一个C++库,这些源文件依赖这些其他库文件”,这是由构建系统将每个构建规则映射到一组构建步骤,例如编译每个源文件的步骤和链接步骤,以及确定编译器和编译标志。


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


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


各个构建步骤必须是“密封的”:仅取决于他们所声明的输入。强调所有依赖正确声明是分发构建的结果:只有声明的输入被发送到构建步骤的机器上运行。结果是构建系统能可靠地知道真正的依赖。甚至是构建系统调用的编译器被视为输入。


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

    

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


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


增量重建速度快。构建系统驻留在内存中,以便为了重建,它可以递增地分析上次构建以来已变更的文件。


预提交检查。 Google提供了在启动时自动运行一系列测试的工具,当启动代码审查和/或准备向存储库提交变更时。每个存储库分支可以包含测试运行的配置文件,以及是否在代码审查时或在提交之前立即运行它们。测试可以是同步的,即在发送变更以供审阅之前和/或在提交变更到存储库之前运行(有利于快速运行测试);或异步结果通过电子邮件发送给审查讨论线程。 [审查线程是代码审查之上的电子邮件线程;该线程中的所有信息也显示在基于Web的代码审查工具中。]


2.3 代码审查

Google已经建立了完善的基于网络的代码审查工具,与电子邮件集成,允许作者提出审查请求,并允许审阅者并排比较差异(同时有漂亮的颜色编码)并进行评论。当提出变更的作者启动代码审查时,通过电子邮件通知审核人,并提供指向该变更的评审工具所在页面的链接。当审核人提交审核评论时,会自动发送通知电子邮件。此外,自动化工具可以发送通知,包含例如自动测试或静态分析工具发现的结果。


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


在特殊情况下,在审查之前,分支所有者可以签入(提交)紧急变更到该分支,但仍然必须指定审查者,并且变更作者和审查者将自动被定期提醒,直到变更被审核批准。在这种情况下,任何回应评审意见的修改必须提交另一个变更,因为最早的变更已经提交。


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


代码审查的一个潜在问题是,如果审阅者的响应太慢,或者是不太愿意批准变更,这可能会阻碍开发的进展。事实是代码作者选择审阅者有助于避免这样的问题,允许工程师避开可能对其代码过度干涉的审阅者,或发送简单变更给经验少的审阅者,复杂变更发送给有经验的审阅者或同时发给好几个审阅者共同审阅。


每个项目的代码审查的讨论将自动复制到项目维护者的专属邮件列表中。任何人都可以对任何变更发表评论,无论他们在变更前后是否被指定为该变更的审阅者。如果一个bug被发现,它通常会跟踪导致bug的变更并在初始的代码审查线程中指出错误以便原来的作者和审阅者意识到该错误。


也可以向几个审阅者发送代码审查请求,然后在他们其中之一批准后尽快提交变更(假设作者或第一个答复的审阅者是分支所有者),在其他审阅者还没有评论之前。任何随后的审查意见在后续变更中处理。这可以减少评审的周转时间。


除了仓库的主库部分,还有一个“实验”库的正常代码审查要求不是强制的。然而,在产品中运行的代码必须放在仓库的主库中,工程师被强烈鼓励在存储库的主库中开发代码,而不是在实验库中开发然后迁移到主库,因为代码审查最有效是在代码开发阶段而不是之后。实际上,工程师们经常要求代码评审即使是在实验库中写代码阶段。


鼓励工程师保持独立的小变更,大变更最好分解成一组小的变更,审阅者可以一次轻松地查看。这也使作者更容易在评审期间对提出的主要变更作出响应;非常大变更的作者往往太死板,并且抗拒审阅者建议的变更。鼓励保持小变更的一种方法是代码审查工具将变更规模描述在每个代码审查中,30-99行的添加/删除/移除被标记为“中”变更,大于300行的变更被标记为受蔑视的标签,如“Large大”(300-999),“freakin hug出奇大”(1000-1999),(但是,在通常的Google方式中,在每年的那几天用一些搞笑的方式替换这些熟悉的描述,talk-like-a-pirate day。 :)

1.近年来这种情况发生了一些变化。更新版本的代码审查工具不再使用更多的蔑视标签,但是仍然标记变更的规模,例如, “S”,“M”,“L”,“XL”。


2.4 测试

我们强烈鼓励并广泛使用单元测试。产品中所使用的所有代码期望都有单元测试,代码审查工具将突出显示没有进行相应测试的源代码。代码审查人通常要求任何变更添加新功能时,也应添加相应的测试。Mocking框架(允许构建轻量级单元测试,甚至是依赖重量级库文件的代码)是相当普遍的。


集成测试和回归测试也被广泛应用。


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


Google还提供用于测量测试覆盖率的自动化工具。结果也被整合到源代码浏览器中,作为一个可选层次。


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


2.5 缺陷追踪

Google使用一个名为Buganizer的错误跟踪系统来跟踪问题:缺陷,功能请求,客户问题和过程任务(如版本发布或清理工作)。缺陷被分配到有层次的组件上,并且每个组件可以具体到可以抄送的默认责任人和默认的电子邮件列表。当发送源代码变更以供审核时,系统会提示工程师将该变更与特定版本发行号相关联。


Google的团队通常(但不是通用的)定期扫描期组件中的未解决问题,确定优先级,并在适当时候分配给特定的工程师。一些团队有专人负责缺陷分类,其他团队采取在小组常规会议上进行缺陷分类的方法。 Google的许多团队都使用缺陷标签表示缺陷是否已被分类,以及哪个版本将修复缺陷。


2.6 编程语言

Google强烈鼓励软件工程师选用4个官方批准的编程语言之一:C ++,Java,Python或Go。减少编程语言的数量降低了代码重用和程序员间的协作障碍。


针对每种语言的Google风格指南,确保遍布公司各处的代码有相似的风格,布局,命名约定等。另外还有一个公司范围内的代码可读性培训流程,由经验丰富的工程师来培训其他工程师编写可读性好,特定语言的常用代码,通过重大变更审查或系列变更审查,直到审阅者认为工程师知道如何用该语言编写出可读性好的代码。一门特定语言上每个重大新代码的变更必须由已经通过“可读性”训练过程的人审批。


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


这些不同的编程语言之间的交互操作主要使用Protocol Buffer。ProtocolBuffer是一种以高效而可扩展的方式编码的结构化数据的方法。它包括用于指定结构化数据的特定领域语言,带有相应描述的编译器并在C ++,Java,Python中生成代码,构建,访问,序列化和反序列化这些对象。 Google的ProtocolBuffer版本与谷歌的RPC库集成,可使用简单的跨语言RPC,具有请求和响应的序列化和反序列化,由RPC框架自动处理。


流程通用性是使开发变得容易的关键,即使使用巨大的代码库和多种语言:有一组单一命令执行所有通用的软件工程任务(如签出,编辑,构建,测试,审查,提交,文件错误报告等等),并且无论什么项目或语言都可以使用相同的命令。开发人员不需要学习一个新的开发过程,只是因为他们正在编辑的代码恰好是另一个项目的一部分或者是用不同的语言编写的相同功能。


2.7 调试和分析工具

Google服务器与库相关联,这些库提供了许多用于调试运行的工具。在服务器崩溃的情况下,信号处理程序将自动将堆栈跟踪转储到日志文件,而且保存核心文件。如果崩溃是由于内存泄漏,服务器将转储活动堆对象的采样子集的分配站点的堆栈跟踪。还有用于调试的Web界面,允许检查传入和传出的RPC(包括定时,错误率,速率限制等),改变命令行标志值(例如增加特定模块的日志级别),资源消耗,概要分析等。这些工具大大增加了调试的整体便利性,传统的调试器难以实现该目的,如gdb。


2.8 发布工程

只有一部分团队有专门的发布工程师,但对于Google的大多数团队来说,发布工程工作由常规软件工程师完成。


大多数软件经常发布;每周或每两周发布一次是常见的,有些团队甚至每天发布。这是通过自动化大部分正常的发布工程任务实现的。经常发布有助于保持工程师的积极性(如果许多个月甚至几年后才发布,很难被认为是激动人心的事),通过允许更多的迭代从而增加整体速度,因而在给定的时间越多的反馈带来越多响应反馈的机会。


发布通常在新的工作区中开始,通过同步到最新的“绿色”构建的变更号(即,所有自动测试通过的最后一个变更),并产生一个发布分支。发布工程师可以选择“最优选择”的额外变更,即从主分支合并到发布分支上。然后从草稿重建软件并执行测试。如果有任何失败的测试,则进行变更以修复缺陷并且让那些额外的变更在发布分支上达到最优,之后再次进行软件重建和测试重运行。当测试全部通过,构建的可执行文件和数据文件被打包。所有这些步骤都是自动的,以便发布工程师只需运行一些简单的命令,甚至只需在菜单驱动的UI上选择一些条目并选择那些最优变更(如果有)。


一旦候选构建被打包,它通常被加载到“预演staging”服务器上做进一步通过少量用户的集成测试(有时只是开发团队)。


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


下一步通常是推出一个或多个“公测canary”服务器来处理一小部分实时生产流量。与“预演”服务器不同,这些是处理和响应是真实的用户。


最后,该版本可以推广到所有数据中心中的所有服务器。对于超高流量,高可靠性的服务,这种逐步推出在几天的时间内完成,有助于减少任何运行中断的影响,因为新引入的缺陷没有被前面的步骤捕获。


有关Google发布工程的更多信息,请参见SRE手册[7]的第8章。也可以参见[15]。


2.9 上线批准

 任何用户可见的变更或重大设计变更的上线都需要来自实施变更的核心工程团队之外的审批。某些特定批准(通常需经过详细审核),需要确保代码合规,符合法律,隐私,安全以及可靠性方面的要求(例如具有适当的自动监控以检测服务器中断并自动通知相关的工程师),以及业务需求等。


上线过程还旨在确保公司内的适当人员在任何重要的新产品或功能投放时能被通知到。


Google有一个内部上线批准工具,用于跟踪所要求的评审,批准并确保符合为每个产品定义的上线过程。这个工具很容易客户化,所以不同的产品或产品领域可以有不同的审查和批准。


有关上线过程的更多信息,请参见SRE手册[7]的第27章。


2.10 事后分析

每当我们的任何生产系统发生严重停机或类似事故时,涉及的人员需要写一份事后分析报告。这份文档描述了事件经过,包括标题,摘要,影响,时间表,根本原因,什么有效/什么无效,以及行动计划。重点是问题,如何在未来避免,而不是责任人或分摊责任。影响部分试图量化事件的影响,术语上报告中断持续时间,丢失的查询数(或失败的RPC等),以及收益。时间表部分给出了事件中断、分析及修正步骤的时间表。什么有效/什么无效部分描述了经验教训 - 

这些做法有助于快速发现和解决问题,出了什么问题,采取了什么具体行动(最好记录下解决缺陷的特定责任人)以减少未来类似问题发生的可能性和/或严重性。


有关Google事后分析文化的更多信息,请参阅SRE手册[7]的第15章。


2.11 频繁重写

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


这看起来成本非常高。事实上,这消耗了谷歌的很大一部分

资源。然而,这也有一些决定性的好处,这是谷歌敏捷性和长期成功的关键。在几年的时间里,对一个产品变更有显著需求是典型的现象,随着软件环境等周围的技术发生变化以及技术或市场的变化影响到用户的需求和期望。几年前的软件是围绕一套老的要求设计的,通常不是以当前要求的最佳方式设计的。此外,它通常积累了很多的复杂性。重写代码能消除所有不必要累积的,不再那么重要的复杂性。此外,重写代码是一种将知识和所有权感觉传递给后来的团队成员的方式。这种所有权意识对于生产力至关重要:工程师自然会更努力开发软件特性并修复他们认为是“自己的”的代码中的问题。频繁重写也鼓励工程师在不同项目之间的移动,这也有助于鼓励思想的交叉碰撞。频繁重写也有助于确保完成的代码使用了更先进的技术和方法。


3. 项目管理

3.1 20%时间

工程师被允许花费高达20%的工作时间在他们选择的任何项目上,无需他们的经理或任何人的批准。针对几个原因,这种对工程师的信任是非常有价值的。首先,它允许任何有好主意的人,即使这只是一个其他人不会立即认同的想法,有足够的时间开发原型,演示或介绍来展示他们的想法的价值。其次,它向管理层提供可能被隐藏活动的可见性。在其他公司没有官方政策允许20%的时间,工程师有时候会工作在“臭鼬(注:指秘密项目,上世纪洛克希德.马丁公司生产U-2、F117等飞机的秘密项目)”项目上而不会提示管理层。更好方式是,如果工程师可以公开这些项目,定期更新他们在这些项目上的状态,即使其管理层可能不同意项目价值。拥有一个公司范围内的官方政策和支持文化使这成为可能。第三,允许工程师花费一小部分时间在更有趣的事情上工作可以保持工程师的动力和激情,防止他们因感觉被迫花费100%的时间在更多乏味的工作任务上而心力交瘁,这是很容易发生的。受到激励的工程师的生产力能够提高20%以上。第四,它鼓励创新文化。看到其他工程师工作在20%的有趣的试验性项目上会鼓励大家做相同的事。


3.2 OKRs

Google的个人和团队需要明确记录他们的目标并评估在实现这些目标所取得的进展。团队设置季度和年度目标,带有可衡量的关键结果,显示在实现这些目标方面取得的进展。这是每个公司水平要做的事,自底向上直到为整个公司定义目标。个人和小团队的目标应该与更大的团队的更高级目标保持一致,他们是公司总体目标的一部分。在每个季度结束时,可度量关键结果的进展情况被记录,并且每个目标被赋予从0.0(无进展)至1.0(100%完成)的分数。 OKRs标准 和OKR分数通常在Google内部是公开的(偶尔会出现例外情况,例如高度敏感的机密项目),但它们不直接作为个人绩效评价的输入。


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


OKRs提供了一个重要机制,用于沟通公司的每个工作部分,并鼓励员工通过社会激励获得好的绩效。工程师知道他们的团队将有一个关于OKRs打分的会议,并自然而然试着获得好分数,尽管OKR对绩效考核没有直接影响,但仍然努力取得好成绩。定义客观和可衡量的关键结果有助于将员工引导到做真正具体可衡量的事情上来,对实现共同目标的进展产生正面影响。


3.3 项目审批

虽然有一个明确的启动批准的过程,但Google没有一个明确的项目审批或取消过程。尽管已经在谷歌呆了近10年,现在已经成为一个自我管理者,我还是不完全明白是怎样做出这样决定的。某种程度上,这是因为这不是一种贯穿整个公司的统一方法。每个级别的管理者都对他们团队的项目负责,并行使自己的决策权。在某些情况下,这意味着这样的决定是以完全自下而上的方式做出的,工程师可以自由地

在他们的团队范围内选择工作项目。在其他情况下,类似的决定更多是以自上而下的方式进行,由高管或经理决定哪些项目将继续,这将获得额外的资源,或者将取消。


3.4 组织重组

偶尔,管理层决定取消一个大项目,然后许多曾经在该项目上工作的工程师可能不得不在新的团队中寻找新的项目。同样,偶尔会出现“碎片整理”工作的情况,跨越多个地理位置的项目被整合,有些地方的工程师被要求换一个团队和/或项目,以实现整合的目的。在这种情况下,工程师通常可以在他们的地理位置上自由选择新团队和角色,或在碎片整理的情况下,他们也可以选择留在同一个团队和项目,移动到不同的位置。


此外,其他类型的团队重组,如合并或拆分团队以及报告关系的变更,似乎是相当频繁地发生,虽然我不知道如何在这方面把Google与其他大公司进行比较。在一个大的,技术驱动的组织,有时频繁的重组可能是必要的,以避免组织在技术和需求发生变化时出现低效率。


4. 人员管理

4.1 角色

我们将在下面更详细地解释,Google将工程和管理分开成不同的职业发展阶梯,将技术领导角色与管理层分开,将工程嵌入到研究中,并支持产品经理,项目经理和现场保障工程师角色(SREs)。似乎至少有一些做法很重要,支持了Google开发的创新文化。


Google在工程中有少量不同的角色。在每个角色中,有一个职业发展可能,有一系列的层次和晋升的可能性(关系到报酬增长,例如。工资)来识别下一个绩效水平。


主要角色有:


●工程经理


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


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


经理负责选择技术主管和并评估他们团队的绩效。他们执行指导并协助员工的职业发展,进行绩效评估(使用同行反馈的输入,见下文),并负责一些薪酬方面的工作。他们也负责招聘的一些部分。


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


●软件工程师(SWE)


大多数做软件开发工作的人都有这个角色。Google的软件工程师招聘条件非常高;通常只聘用异常优秀的软件工程师,这能避免或减小困扰其他组织的很多软件问题。


Google有独立的工程和管理职业发展序列。虽然软件工程师可以管理人员,也可以转任工程经理,但管理人员不是晋升所必需的,甚至在最高级别也是如此。在更高的层次,显示领导力是需要,但可以有多种形式。例如创造有很大的影响力的伟大软件或者被很多其他工程师使用就够了。这是重要的,因为它意味着有强悍的技术技能但缺乏人员管理技能仍然有一个很好的职业发展道路,没有要求他们一定有管理经验。这避免了一些组织遭受的问题,人员由于职业发展原因结束在管理职位上,但忽视了团队中人的管理。


●研究科学家


这个角色的聘用标准非常严格,并且招聘条件也是非常高的,要求表现出杰出的研究能力,需要有大量的出版记录的证明 *并且* 有能力编写代码。在学术界许多非常有才华的人胜任软件工程师角色但并不符合谷歌的研究科学家角色;大多数在谷歌有博士头衔的人是软件工程师,而不是研究科学家。研究科学家在他们的研究贡献上被评价,包括他们的出版物,但除此之外和不同的头衔,软件工程师和研究科学家的角色之间没有太大的不同。两者都可以做原创研究和发表论文,都可以开发新的产品思路和新技术,也能够写代码和开发产品。 Google的研究科学家通常与软件工程师一起工作,在相同的团队和工作在相同的产品或相同的研究上。这种将工程嵌入到研究工作中的做法极大地方便了新的研究成果落地形成产品。


●现场保障工程师(SRE)


 操作系统的维护由软件工程团队完成,而不是传统的系统管理类型,但SRE软件工程师的招聘要求的技能略低于软件工程师的要求。 SRE角色的性质和目的在下文中进行了详细的解释,SRE书[7],所以我们不在这里进一步讨论。


●产品经理


产品经理负责管理产品;作为产品用户的支持者,他们协调软件工程师的工作,将重要的产品特性传导给用户,与其他团队协调,跟踪错误和计划,并确保所需的一切资源按时到位,以产生高品质的产品。产品经理通常不会自己编写代码,而是与软件工程师一起工作,确保代码的正确。


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


项目经理的角色与产品经理大致相同,但是相比管理产品,他们管理项目,过程或运维(例如数据采集)。技术项目经理工作类似,但也需要与工作相关的特定的技术专门知识。例如处理语音数据的语言学。


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


4.2 办公条件

Google有名是因为它有趣的娱乐设施,如像滑梯,球池和游戏室等。这有助于吸引和留住优秀的人才。 Google的咖啡馆,对员工免费,这也巧妙鼓励了Google员工留在办公室;饥饿绝不是离开的理由。 “微型厨房”的频繁安置,员工可以随时取用小吃和饮料,也可以作为一个重要的非正式想法交流的地方,因为许多沟通就是从那里开始的。健身房,运动和现场按摩帮助保持员工健康,快乐,提高生产力并留住人才。


Google的座位是开放式的,通常相当密集。虽然有争议[20],但这鼓励了沟通,有时牺牲个人的注意力集中,但也很经济。


员工分配到一个单独的座位,但座位相当频繁地重新分配(每隔6-12个月,通常是由于组织扩大),通过管理者推动和鼓励沟通,员工可以选择座位,这些座位总是比较容易彼此相邻或接近相邻的其他人。


Google的办公设施都配备有最先进的视频会议设施的会议室,其中连接到另一方预先安排的日程邀请只需单击一下屏幕。


4.3 培训

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

●新的Google员工(“Noogler”)有一个强制性的初始培训课程。

●技术人员(SWE和研究科学家)从“Codelabs”开始:在线短期个人技术培训课程,编码练习。

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

●Google还支持在外部机构学习。


此外,每个Noogler通常有官方任命的“导师”和一个单独的“伙伴”帮助他们加快成长速度。非正式指导也通过与经理的定期会议,团队会议,代码审查,设计审查和非正式过程而进行。



4.4 换岗

鼓励公司不同部门之间的换岗,有助于跨组织的知识和技术的传播,改善跨组织的沟通。允许员工在12个月后,可以项目和/或办公室之间进行交流。软件工程师也鼓励做组织其他部分的临时任务,例如一个六个月的SRE(现场保障工程师)“轮换”(临时的分配)。


4.5 绩效考核和奖励

Google积极鼓励反馈。工程师可以给对方明确积极的反馈,通过“同行奖金”和“kudos”。任何员工可以提名任何其他员工的“同行奖金” - 每年100美元的现金奖金,每年最多两次的超出正常工作职责的协作,只需填写一个Web表单来描述原因。队友也是发放同行奖励才通知。员工也可以给予“kudos”,正式的赞扬声明,为良好工作提供明确的社会认可,但没有财务上的奖励;对于“kudos”,没有要求工作要超出正常的工作职责,也不限制授予的次数。


经理还可以奖励奖金,包括现金奖金,例如,项目完成后发奖金。与许多公司一样,Google员工基于绩效获得年度绩效奖金和股权奖。


Google有一个非常仔细和详细的晋升过程,由自己或经理提名经理,自我审查,同行评审,经理评价;然后由晋升委员会做出实际决定,结果可以由晋升上诉委员会进一步审查。确保正确的人得到晋升至关重要,保持对员工的正确激励。


另一方面,较差的绩效由管理者反馈处理,如果需要的话,提出绩效改进计划,其中涉及设置非常明确的具体绩效目标并评估这些目标的进展情况。如果失败,终止不良绩效是可以的,但在实践中这是非常罕见的。


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


5. 结论


 我们简要介绍了Google使用的大多数关键软件工程实践。当然Google现在也是一个庞大和多样化的组织,并且组织的一些部分有不同的做法。但是这里描述的做法通常被大多数谷歌团队遵循。


有这么多不同的软件工程实践被涉及到,有很多其他Google成功的原因与我们的软件工程实践无关,非常难以给出任何量化或客观的证据。然而,这些做法经受了时间的考验,是数以千计的优秀谷歌软件工程师的集体主观判断。


对于那些主张使用特定实践,这篇文章中描述到的其他组织,也许会说“这对谷歌足够好了”。


长按二维码发现惊喜

L

O

V

E

致谢

特别感谢Alan Donovan非常详细和建设性的反馈,感谢Y aroslav Volovich,UrsH?lzle,Brian Strope,Alexander Gutkin,Alex Gruenstein和Hameed Husaini对本文的早期草稿提出了非常有益的意见。


作者简介

 Fergus Henderson在Google做软件工程师已经超过10年以上。当他在1979年还是一个孩子时就开始了编程,并一直在编程语言设计与实现方面做学术研究。与他的博士生导师在墨尔本大学共同创立了一个研究小组,开发了名为水星的编程语言。他是8个国际会议的方案委员会成员,并发布了超过50万行的开源代码。他还是Usenet新闻组comp.std.c ++的前主席并且是ISO C和C ++委员会官方认可的“技术专家”。他有超过15年的商业软件行业经验。在Google,他是Blaze的初始开发人员之一,这是一个构建(编译连接)工具,现在在Google内部使用,并工作在服务器端,用于语音识别、语音动作(早于Siri!)以及语音合成。他目前管理着Google的文字转语音工程团队,但仍然编写与评审很多的代码。他编写的软件安装在十亿多个设备上,并每天被调用十亿次以上。

张勇译,吴穹审

引用

[2] Build in the Cloud: How the Build System works , Christian Kemper,

[1] Build in the Cloud: Accessing Source Code , Nathan York,

[3] Build in the Cloud: Distributing Build Steps, Nathan York

[4] Build in the Cloud: Distributing Build Outputs, Milos Besta, Yevgeniy Miretskiy and Jeff Cox

[5] Testing at the speed and scale of Google , Pooja Gupta, Mark Ivey, and John Penix, Google engineering tools blog, June 2011.

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

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

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

[9] What would Google Do?: Reverse-Engineering the Fastest Growing Company in the History of the World , Jeff Jarvis, Harper Business, 2011.

[10] The Search: How Google and Its Rivals Rewrote the Rules of Business and Transformed Our Culture , John Battelle, 8 September 2005.

[11] The Google Story , David A. Vise, Pan Books, 2008. 

[12] Searching for Build Debt: Experiences Managing Technical Debt at Google,  J. David Morgenthaler, Misha Gridnev, Raluca Sauciuc, and Sanjay Bhansali.

[13] Development at the speed and scale of Google , A. Kumar, December 2010, presentation, QCon.

[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. 

[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. 

[18] The Motivation for a Monolithic Codebase , Rachel Potvin, Josh Levenberg, to be published in Communications of the ACM, July 2016.

[19] Scaling Mercurial at Facebook, Durham Goode, Siddharth P. Agarwa, Facebook blog post, January 7th, 2014.

[20] Why We (Still) Believe In Private Offices , David Fullerton, Stack Overflow blog post, January 16th, 2015.

[21] Continuous Integration at Google Scale , John Micco, presentation, EclipseCon, 2013.

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多