Beyang Liu 2020 年 11 月 24 日
我曾在谷歌短暂工作过,尽管时光荏苒,但那段经历让我对谷歌的内部开发工具印象深刻。谷歌的开发工具在很多方面可谓世界领先。他们不仅在扩展自己的软件系统方面走在前沿,还在大规模高效软件开发方面颇有建树。谷歌处理了代码库规模、代码发现、组织知识共享和多服务部署等问题,这些在大多数公司看来都是高难度挑战。(参考资料:《谷歌的软件工程》)
但谷歌的内部工具也有其局限性,尤其是它们几乎完全依赖于谷歌的内部环境。遗憾的是,这意味着你离开谷歌后,这些工具就无法随身携带。
谷歌的员工离职后,他们带着在这家世界顶尖技术公司的宝贵经验,为许多其他组织注入了新鲜血液。然而,适应谷歌之外的编程环境可能颇具挑战,尤其是当你习惯了一些现在手头上没有的工具时。
多年来,我从自己和许多离开谷歌的同事的经历中汲取了不少教训。Sourcegraph 的早期客户中,很多人是因为离开谷歌后怀念代码搜索功能而来。我与这些前谷歌员工紧密合作,深入了解他们的需求,以便打造出满足他们需求的 Sourcegraph。随着时间的推移,我们发现前谷歌员工在引入新的开发工具到他们的新组织时,往往会遵循某些模式,这些模式受到他们在谷歌的经验的影响。有些尝试取得了成功,而有些则没有。
我想,为前谷歌员工撰写一份关于谷歌之外的开发工具指南,着眼于实用性和实际操作,会是个不错的主意。虽然许多前谷歌员工可能梦想着将谷歌的内部环境完全搬到新公司,但这并不现实。以下是我的一些建议,关于你应该从哪里开始,以及我认为前谷歌员工可以遵循的路径,以寻找那些能让他们及其新团队达到最高效率的工具。
在有无谷歌内部工具的情况下软件开发的生命周期
如果你刚从谷歌跳槽到另一家公司,你可能会感到一种挫败感,觉得自己的工作效率不如从前。你知道需要做出改变,但究竟该改变什么呢?首先,你得回顾一下自己的日常工作,找出问题的根源。
不管是在谷歌内部还是外部,软件开发的生命周期通常包括以下几个步骤:
- 想出一个新功能或需要解决的问题。
- 阅读大量代码和设计文档,向同事请教。这一过程中,你在理解问题本身及其解决方案如何适应现有系统。
- 开始编码。首先,你会努力让代码勉强能运行。这期间,你可能需要多次查阅文档或再次阅读代码。
- 代码能运行了,但还不能发布。你可能破坏了一些测试,现在需要修复它们,添加新的测试,重构代码,使其更清晰、易于他人理解。然后,你会将代码推送到一个分支,并等待持续集成(CI)的运行,期间可能还需要做一些额外的修复和小改动。
- 提交代码审查。团队成员会提出一些意见,你根据这些意见进行修改。在审查者最终批准之前,可能需要几轮的修改和讨论。
- 合并代码补丁,进行部署。
- 依靠现有的监控系统来检测是否有任何生产问题。如果是你的代码导致了系统宕机,那么解决问题的责任就落在了你的肩上。
在这个过程的每个阶段,都有一些关键工具支撑着开发者的体验。这些工具形成了你的工作流程,并对你的工作效率产生重大影响。
软件开发阶段 | 谷歌内部 | 谷歌外部 |
---|---|---|
确定功能或修复漏洞 | Issue Tracker | GitHub 问题追踪,Jira |
阅读代码 | 代码搜索工具 | 你的代码编辑器,OpenGrok, Hound, Sourcegraph |
编写代码 | Cider, IntelliJ, Emacs, Vim, VS Code | 同上,除了没有 Cider (编辑者更新:自发表以来,像 Gitpod 和 Codespaces 这样的云 IDE 变得更流行) |
测试代码 | Blaze | 有些混乱,但 Bazel 正在变得流行 |
代码审查 | Critique | GitHub 的 PRs, Gerrit, Phabricator, Reviewable |
部署 | Borg | Kubernetes |
监控 | Borgmon, Dapper, Viceroy | Prometheus, Grafana, Lightstep, Honeycomb, Sentry |
想要提升工作效率,挑选合适的工具至关重要。GitHub 上有一个非常实用的仓库,它详细列出了谷歌内部使用的各种工具及其在谷歌外部的相似替代品:https://github.com/jhuangtw/xg2xg。这份清单内容丰富,虽然看起来有些复杂,但你可以从这里开始探索。
首月工作:先别急着用新工具,学习现有的吧
在你刚加入团队的第一个月,不要急于做出改变。先静下心来,学习和观察。
作为新来的一员,你可能还没有足够的影响力或权限去更换团队正在使用的所有工具。更重要的是,你还需要了解——你的新团队为什么会以这种方式工作,为什么会选择现在这套工具。仅仅把谷歌的内部工具搬过来可能并不适合你的新团队。所以,先弄清楚什么工具确实适合你们团队,什么又不适合。
低悬果实策略
我认为,从代码搜索工具入手通常是个不错的选择。虽然我是一家代码搜索公司的联合创始人,可能会有所偏见,但以下是我的理由——如果你不认同,可以跳过这部分!
- 这是前谷歌员工们在日常工作中最怀念的工具之一。
- 你可以自己尝试不同的代码搜索引擎,找到一个好用的再推荐给同事。这样做,你无需先向管理层申请,也不用花费社交资本去说服别人尝试一个你自己还没用过的工具。
- 这不会迫使团队成员改变他们现有的习惯,因为你的新团队可能还没有使用代码搜索工具。如果他们已经有了,那么要么是不太好用的,大家不常用,要么就是已经很不错了,那你就可以跳过这部分内容了!
如果你的新公司有好几个团队,你可能需要处理的代码量超出了个人的合理理解范围。即使是在一个小公司工作,你也可能需要通过依赖关系处理大量的开源代码。这些都是你在开发新功能或追踪关键错误时必须深入了解的代码。
考虑到如今几乎每个开发者都要处理的庞大代码量,缺乏有效的代码搜索工具很容易让你的开发进度大幅放缓。
在评估代码搜索引擎时,你需要考虑几个关键点:
第一个月:先别忙着用新工具,学习现有的就好
刚加入团队的第一个月,不要急着去改变什么,先学会倾听,了解团队的运作方式。
作为新成员,你可能还没有足够的影响力或权限去改变团队使用的所有工具。更重要的是,你还需要了解——你的新团队为什么会以这种方式工作,为什么会选择现在这套工具。盲目地把谷歌的内部工具搬到新团队中并不一定行得通。所以,先弄清楚什么工具在你的新团队中有效,什么又不太适用。
容易上手的工具
我认为,代码搜索通常是个不错的起点。虽然我是一家代码搜索公司的联合创始人,自然会这么说,但我的理由是这样的——如果你不认同,可以跳过这部分内容!
- 这是前谷歌员工们日常工作中最怀念的工具之一。
- 你可以自己先尝试不同的代码搜索引擎,找到一个好用的再推荐给同事。这样做,你不需要先去求得领导的批准,也不用花费社交资源去说服别人尝试你自己还没用过的工具。
- 这不会迫使别人改变他们的现有习惯,因为你的新团队可能还没有使用代码搜索工具。如果他们用了,那么要么是不太好用的,他们很少使用;要么就是已经很好了,那你就不需要关注这一块了!
如果你加入的新公司有好几个团队,你可能需要处理的代码量超出了个人的合理理解范围。即使是在一个小公司工作,你可能也会通过依赖关系引入大量的开源代码。这些都是你迟早需要深入了解的代码,无论是为了开发新功能还是追踪某个关键的错误。
考虑到如今开发者必须处理的庞大代码量,缺乏有效的代码搜索工具很容易让你的开发进度大大放慢。
在评估代码搜索引擎时,你需要考虑几个要点:
- 查询语言:掌握正则表达式是基础。你需要的是一个既能精准表达又易于操作的代码搜索查询语言。简单的字面搜索应该直观易懂,同时也要提供更复杂的模式匹配功能。
- 规模适应性:确保你的代码搜索引擎能够应对你的代码库规模。如果你的代码库体积超过几 GB,一个重要的考量是代码搜索引擎是否采用了三元组索引 https://swtch.com/~rsc/regexp/regexp4.html,这是实现大规模代码库中的正则表达式匹配的关键。
- 代码浏览体验:作为 Google Code Search 的用户,你肯定明白搜索只是功能的一半。当你点击搜索结果时,你希望能像在 IDE 中一样,轻松跳转到定义处,查找引用。如果代码浏览功能不佳,你可能需要频繁在代码编辑器和搜索引擎之间切换。
- 权限管理:如果你的公司对代码库有权限设置,那么选择一个能够遵守这些权限的代码搜索引擎是必要的。
- 总体成本:在选择时,不仅要考虑代码搜索引擎的价格,还要考虑维护这一工具所需的成本。
以下是一些常用的代码搜索引擎:
- OpenGrok:一个由 Oracle 维护的经典且持久的代码搜索引擎。
- Hound:由 Etsy 的工程师开发并开源的代码搜索引擎。
- Livegrep:Stripe 的 Nelson Elhage 开发的代码搜索引擎。
- 当然,还有 Sourcegraph。
掌握有效的监控技巧
监控是一个早期就值得关注的领域。每个工程师迟早都会遇到生产环境的问题。生产环境和开发环境截然不同——你不能像在开发时那样简单地设置断点或添加打印语句,然后几秒钟内看到结果。在生产环境中进行更新代价高昂,不仅涉及计算资源和开发时间,最严重的可能是给用户和客户带来不便。
过去 5 到 10 年间,软件部署方式发生了巨大变化。微服务、Kubernetes、迁移到云端等都是重大的转变。许多公司已经采纳了这些新模式和技术,但他们的监控基础设施还未跟上,使得在这些新的生产环境中进行调试变得不那么容易。
幸运的是,近年来出现了一些优秀的新开源工具和公司,它们极大地改进了谷歌之外的监控和可观察性技术。
- Prometheus 是一个时间序列度量跟踪和可视化工具,类似于 Borgmon。它可以帮助你监控应用程序的各种指标,如 CPU 使用率、错误率和 p90 延迟等随时间变化的数据。
- Grafana 是一个类似于 Viceroy 的仪表板工具。一个常见的做法是将 Grafana 与 Prometheus 结合使用,从而创建一个展示多个关键指标的单页视图,这些指标反映了应用程序的整体健康状况。
- 谷歌在分布式追踪方面处于领先地位,这对于日益普遍的多服务架构至关重要,他们使用的是 Dapper。Dapper 的创造者之一 Ben Sigelman 后来创立了 Lightstep。现在,分布式追踪已成为许多监控系统的一个特性,包括像 Honeycomb 和 Sentry 这样的付费服务,以及 Uber 工程师开发的开源项目 Jaeger。
引入监控系统比代码搜索要复杂,因为它需要整合到生产环境中。这通常意味着需要改变部署环境,可能还需要说服负责部署环境的团队。此外,可能还需要添加一些监控代码,这就涉及到向负责相关代码的各团队提交修改。不过,从另一个角度来看,引入新工具并不要求人们改变现有习惯,他们可以自由选择是否使用新工具,这就减少了在部署新工具时可能遇到的强烈反对。
在你声誉良好之后:代码审查
当我们谈到引入代码搜索和监控时,这并不需要团队成员改变他们现有的工作方式。但是,更换代码审查工具就不同了。
如果你在谷歌工作过一段时间,你可能会觉得谷歌之外的代码审查方法有些不同寻常。GitHub Pull Requests 是最普遍的代码审查工具,但是前谷歌员工对它有一些常见的不满:
- 自上次审查以来所做的更改不容易查看,有时甚至无法查看。简单的方法只能让你审查整个待处理的差异。
- 它不支持分层的代码审查(CR)。
- 所有文件的整体差异会显示在一个巨大的页面上,这让人难以追踪已审查的部分。
- GitHub 的 Pull Requests 对审查的具体方式几乎没有明确指导。如果不加入额外的第三方工具,审查过程可能显得比较随意,即便加入了这些工具,也可能缺乏更细致的审查和认证政策。
- 对于某些编程语言,它提供了有限的模糊跳转到定义或查找引用的功能,但这远不及谷歌内部使用的 Critique。
在谷歌之外,最接近 Critique 的工具是 Gerrit。Gerrit 起初是 Rietveld 的一个分支,而 Rietveld 本身是谷歌最初代码审查工具 Mondrian 的开源版本。因此,Gerrit 会给人一种熟悉的感觉,因为它源于一系列专为谷歌的代码审查方式设计的工具。
Phabricator 是另一个前谷歌员工常用的代码审查工具,它通常被看作是 GitHub Pull Requests 的替代品。Phabricator 最初是 Facebook 的内部代码审查工具,后来被开源并推向了外部世界。如果你不想自己维护这样的系统,可以考虑 Phacility,这家公司提供托管服务和支持。
还有一个值得一提的工具是 Reviewable,由前谷歌员工 Piotr Kaminski 开发。与 Gerrit 或 Phabricator 不同,Reviewable 只提供云服务,但它可能提供一种最接近于谷歌内部当前使用的代码审查体验。
当你向团队成员介绍 Gerrit、Phabricator 或 Reviewable 的优势时,关键是要弄清楚团队在使用现有代码审查工具时遇到的问题。以下是从类似 GitHub 的拉取请求工具转向类似 Gerrit 工具时,如何解决一些常见问题:
- Gerrit 支持更加有条理的审查流程,并包含明确的审批环节。这对于团队规模扩大、希望在整个组织中实施更严格审查规则的情况特别有用。
- Gerrit 使得审查大量代码变化更加容易,你可以逐个文件检查,查看自上次审查以来的变化,并且可以堆叠代码审查请求(CR),从而实现更快速、更全面的审查。
Gerrit、Phabricator 和 Reviewable 能让你几乎完全模仿在 Google 内部使用的代码审查流程。但是,这两种工具都不提供代码智能功能。如果你觉得目前的代码审查工具缺乏代码智能,或者认为 GitHub PR 的代码智能功能不够强大,不妨试试 Sourcegraph 浏览器扩展。它可以连接到 Sourcegraph 实例,在代码审查过程中提供工具提示、定义跳转和交叉引用等功能。它适用于 GitHub PR、GitLab MR、Phabricator 和 Bitbucket Server,而且很快也会支持 Gerrit。
当你准备好迎接挑战
在软件开发的整个生命周期中,持续集成(CI)和构建系统常常是最棘手的部分。这是因为要理解构建过程,你几乎需要对整个代码库的每个部分都有深入的了解。随着时间的推移,不同的人试图加快构建速度,构建代码因此积累了越来越多的小技巧和优化。最终,真正能理解整个过程并能做出无负面影响改动的人寥寥无几。
简单来说,构建系统常常像一个庞大的混乱之球,你在试图解开这个混乱之前,最好先解决一些更容易的开发生产力问题。你可能会想尽早解决这个问题,因为 Blaze 远比你现在用的工具好,而且谷歌甚至还开源了一个基于 Blaze 的衍生产品——Bazel。但是,Bazel 并不等同于 Blaze——最明显的区别是,它没有一个大型的分布式构建集群作为免费附赠——而且谷歌之外的世界与谷歌本身也大不相同。
Bazel 并非灵丹妙药。Bazel 刚发布时,Go 社区中许多开源项目开始转用它,而不是标准的 Go 构建工具。但不到一年,由于使用上的复杂性、Go 社区对其不熟悉,以及构建速度实际上似乎更慢,许多项目又换回了原来的工具。尽管此后 Bazel 在支持 Go 方面有了重大改进,但如果你考虑切换到 Bazel,你需要仔细评估它带来的实际改进。
为了做出这种仔细的评估,你需要有一系列其他优秀的开发工具。特别是,你需要有一个强大的代码搜索工具,以便深入了解代码库各个部分的构建脚本及其细节。此外,你还需要一个高效的代码审查工具,因为更改构建系统是一个复杂的过程,需要多个工程团队的共同审批。
当你准备好迎接这一挑战时,你会发现除了 Bazel 之外,还有许多其他构建工具可用,这些工具旨在支持大型代码库中的可扩展构建。这些工具包括:
- Buck,Facebook 的产物
- Gradle,在 Java 领域广受欢迎
- Pants,最初由一位离开谷歌的员工为 Twitter 和 Foursquare 打造
- Please,一种较新的构建工具,由前谷歌员工开发,深受 Blaze 影响
此外,还有 YourBase。它并非构建工具,而是一项由前谷歌员工 Yves Junqueira 发起的 CI(持续集成)服务,目的是为谷歌之外的世界提供超快速和可扩展的构建服务,而且不受所用构建工具的限制。
像前谷歌员工一样工作
谷歌对开发者体验和开发工具的重视程度,与大多数其他公司截然不同。谷歌员工和前谷歌员工都亲身体验过一流的开发工具,这些工具极大地提升了他们的才能和技能。
离开谷歌后,你的一大竞争优势在于将这些宝贵经验应用于新的工作环境,引入卓越的新开发工具,以提升自己及团队的工作效率。通过推广这些工具,传播大规模软件开发的有效最佳实践,你可以将谷歌工程组织效率这一核心竞争力带入新公司。
大规模软件开发充满挑战。正如《神话般的人月》一书所述,仅靠增加工程师人数并不能打造更优秀的软件,关键在于更好的工具。软件能够提升终端用户的生产力,同样,开发工具也能成为软件开发者生产力的倍增器。因此,如果你真心投入到新公司的使命中,那么利用你作为前谷歌员工的独特知识,引入最佳开发工具,应成为你的首要任务之一。
试试 Sourcegraph。 你可以通过 自托管 Sourcegraph 免费为最多 10 名用户开始搜索代码。或者尝试 Sourcegraph Cloud,轻松搜索公共的、开源代码。
如果你有任何疑问,欢迎通过 Twitter @sourcegraph 发帖或发送电子邮件至 hi@sourcegraph.com 向我们咨询。
关于作者
Beyang Liu 是 Sourcegraph 的技术总监兼联合创始人。他在斯坦福大学攻读计算机科学,并在斯坦福 AI 实验室就概率图模型和计算机视觉领域进行了研究并发表了相关论文。你可以在 Twitter 上关注并与 Beyang 交流 @beyang,或加入我们的社区 Discord 讨论 Discord。
更多精彩内容
- 通过 Zoekt 内存优化,实现内存使用量大幅减少 5 倍
- 代码展示的改进:探索 17 位开发者的工作环境
- 如何避免破坏搜索引擎:我在平凡的工程学中学到的教训