在软件行业,虽然感觉平时大家讨论“质量保证”或“质量管理”不多,但实际上,许多优秀公司还是非常关注质量的,都有着自己独特的质量文化,把质量置于很高的地位,例如:
- 阿里的质量使命:做用户体验捍卫者,让客户百分之百放心;
- 华为的质量使命:让HUAWEI成为ICT行业高质量的代名词
这些优秀公司无需对外声张,都在默默在进行质量管理,赢得用户市场。这一期,介绍Google(谷歌)公司是如何进行质量管理的。谷歌是一家优秀公司,拥有顶尖的人才、崇尚技术等,很有优势,依旧非常重视质量。谷歌支撑公司产品质量的三大支柱就是:整洁的代码,要求代码遵守代码规范,之前许多公司的C++/Java语言规范都是以谷歌的代码规范为榜样。
又快又好的测试,强调任何单个测试超过60秒都没有价值,执行越快越有价值,每天执行近1亿个测试用例。
强大的基础设施,从代码管理、持续构建到整个产品发布,全面实现自动化操作、运行等。
大部分的代码都用统一的源代码库来管理,但开源项目Chrome和Android使用独立的开源代码库,而一些高价值的或高安全性的代码,则设定了严格的读取权限。一般来说,任意一位工程师都可以访问任何代码,但对代码库的写权限是被限定的:只有每个subtree的所有者(Owner)有权批准对subtree的修改。所有源代码主库的变更都必须经过除作者外至少一个以上工程师的审查。此外, 如果作者不是该修改文件的其中的所有者,那么此项变更还需要至少一个所有者的审查和批准。谷歌自己开发了优秀的基于Web的代码评审工具,并和邮件系统集成,允许作者发起评审请求、允许评审人员两边对比方式地去浏览代码差异 (带有颜色标注) 并能直接在工具上写评审意见。当代码变更的作者发起代码评审时,评审人员会收到电子邮件通知,并附有链接指向评审工具对应的web页面。当评审人员提交他们的评审意见时,也会发送邮件通知作者。
因为在刚写完代码后就进行代码审查是最有效的,而不是彻底完成代码开发工作之后再进行代码评审。鼓励工程师每次尽量保持小规模的变更,大的变更也最好是分解成一系列的小变更,以便评审人员很容易地一次性地完成评审。
每个项目的代码评审讨论会被自动拷贝到指定的项目维护者邮件列表中。任何人都可以对任何变更进行自由评论,如果发现一个错误,通常会追踪到引入此项错误的变更和原代码的评审意见,并指出问题在哪里,以便让原始作者和评审人员都了解问题所在。
在Google的团队中定期扫描各个组件中未关闭的Bug是十分常见的,优先关注这些Bug并合理地将它们分配给相应的工程师。
诸如库、程序和测试这些构建实体,均由高级的声明式构建规范(declarative build specifications,DBS)进行声明,描述具体的每一个实体,如实体的名称、源文件、相关的库文件或所依赖的其它实体。这些DBS是由被称为“构建规则”的声明来组成,每个声明均用来指定如“一个拥有依赖于其他库的一系列源文件构成的C++库” 这样的高层次概念,并取决于构建系统将每项构建规则和一系列的构建步骤映射起来。构建文件是可以自动生成和更新,并确保构建系统通过分析构建文件而不是源文件来快速地确定依赖关系,并以此避免了构建系统和编译器、或者用于支撑其他编程语言的分析工具之间的过度耦合。单元测试是Google公司非常提倡和广泛采用的工程实践。产品线上所有的代码都要求进行单元测试,如果新添加的源文件没有进行相应的测试,代码审核工具将会将它们突显出来。代码评审者通常要求:任何增加了新功能的变更都应该添加新的测试来覆盖这项新功能。 针对启动代码审查和/或准备提交变更到存储库时,工具自动运行一组测试。每个库subtree都可以包含一个配置文件,以确定要运行哪些测试, 以及是否在代码评审时或在提交之前即刻运行测试。测试可以是同步的,也可以是异步的,根据需要自动决定,而且 自动化工具可以发送包含自动化测试或静态分析工具的测试结果等相关通知。所有的构建都需要经过测试。如果测试失败,则几分钟内系统就能自动通知作者及其评审人员,从而添加新的变更来修复失败,新的变更会再次合并到新版本分支,再重新构建和重新测试。直到测试全部通过后,将构建好的可执行文件和数据文件一起打包。所有这些步骤都是自动执行的,因此发布工程师只需要运行一些简单的命令就能完成。大多数团队会通过安装引人瞩目的显示 (绿色代表构建成功和所有测试通过, 红色表示某些测试失败, 黑色表示构建失败) 非常直观地呈现构建的状态。这种行为有助于将工程师们的注意力集中在“构建处在绿色状态”。大多数规模较大的团队也有一个“构建警察” (这一角色通常由团队成员或是经验更丰富的成员轮流承担),通过与作者合作来快速解决问题或回滚其违规的修改以确保测试持续通过。集成测试和回归测试也得到了广泛的应用,Mocking框架很受欢迎,在此框架下仍允许对于重量级库函数有依赖的代码进行轻量级单元测试的构建。测试自动被视作代码审核和提交流程中的一部分。自动化系统频繁地运行测试, 只要有代码改动就进行回归测试, 虽然这并不总是可行。
一旦候选版本已经完成打包,则通常部署到staging服务器上,进一步完成集成测试。一个有用的技术,涉及到从产品线上发送一份请求的copy(或子集)到staging服务器,同时也发送同样的请求到当前真正的产品服务器以进行实际的处理。从staging服务器获得的响应已被丢弃,而从真实的产品服务器所获得的响应会送回给用户。这有助于确保在新版本真正上线之任何有可能会导致严重后果的问题(如服务器崩溃)能被检测出来。一些非常高流量、高可靠性的服务是需要几天时间、逐步推出(灰度发布),以减少由于未被之前的检测步骤所发现的、新引入的缺陷而造成任何停机/服务中断(outages)的影响。谷歌代码库已经有十几亿个文件,代码行数高达几十亿,包含了几千万代码提交(commits/check in)记录,每天以4万次提交在增长。谷歌的企业文化鼓励工程师跨越项目边界去修复他们认为受到破坏并知道如何修复的任何缺陷。这给了工程师更多授权,并促使达到高质量的基础设施,以更好地满足其使用需求。 谷歌使用一个被称为Blaze的分布式构建系统,此系统负责软件编译、链接及其测试。它提供了用来构建和测试软件的标准命令, 并适用于整个代码库。这些标准命令和高度优化的工具意味着任何Google工程师构建版本和测试软件通常是非常简单和快速的。这种一致性在帮助工程师能够跨越项目边界进行修改起着关键作用。构建结果缓存在“在云中”,还包括中间结果。如果另一个构建请求需要相同的结果, 构建系统将自动复用而不是进行重建,即使此请求来自于不同的用户。而且,构建系统一直驻留在内存中,因此可以仅仅针对上次构建之后修改过的文件来进行增量分析来完成新的构建。Google服务器与为正在运行的服务器进行调试的工具库是联系在一起的。一旦服务器崩溃,一个信号处理程序将堆栈跟踪信息自动存储到日志文件中,并保存其core文件。如果由于堆内存耗尽导致服务器崩溃的,服务器将保存一个堆对象的样本子集所在的那些站点的堆栈跟踪信息。也提供了Web的调试接口,允许检查传入和传出的RPC(包括时间、错误率、速率限制等)、改变命令行标志值(例如为特定模块增加日志冗长度)、资源消耗、分析等等。