离开谷歌之后,很难再享受到这些称手的开发工具了
博主 Beyang Liu 在多年以前曾在谷歌短暂任职,尽管时间不长,但谷歌内部工具还是给他留下了深刻的印象。在他看来,谷歌的内部开发工具在很多方面都堪称全球最强水平。谷歌不仅善于扩展自有软件系统,在探索如何高效大规模构建软件方面也一直号令群雄。谷歌以绝大部分其他公司无法企及的复杂程度,处理着海量代码库、代码可发现性、组织知识共享及多服务部署等现实难题。
但从另一方面来看,谷歌的内部工具其实数量不多,而且几乎都与谷歌内部环境紧密耦合。所以离开谷歌之后,很难再享受到这些称手的开发工具了。此外,在谷歌工作期间,大家已经习惯了谷歌内部的工作方式,离职后会有人感觉编程难度陡然提升,其实这也与大家失去了自己熟悉的工具有关。
Beyang Liu 结合自己和其他前谷歌员工的经验,总结出数个关于开发工具的使用心得,并编写出了这份谷歌以外的实用主义开发工具指南,帮助开发者设计开发工具常规路径,最终为自己和新团队探索出尽可能高效的工具。
离开谷歌加入其他公司多少会让人有些沮丧,因为没有多少企业能在工作效率上跟谷歌相提并论。但具体区别到底体现在哪里?首先,我们应该考虑自己每天在做什么,然后确定这种沮丧情绪的来源。
有一点可以确定的是,无论是否在谷歌工作,软件开发生命周期的一般形式都差不多:
想到一个想要构建的功能,或者一个需要修复的 bug。
读了一大堆代码、设计文档,并向同事提问。通过这种方式,我们建立起对问题的理解,并明确了解决方案该如何大致适应现有系统。
开始编写代码。开发的第一要务就是让编写出来的东西能跑。在此期间,我们可能会多次查找文档或者参阅更多原有代码。
能运行的成果已经出来了,但还不能直接使用。代码成果通不过某些测试,所以需要先行修复。经过更多测试、完成了代码重构,再降低代码设计的理解门槛,接下来就可以把成果发布到分支上了。到这里,我们就可以等待 CI 运行了,还可以引入一些额外的修复和小改动。
提交补丁以供审核。同事们当然会发表评论,我们再据此做出调整。在变更真正获批之前,这样的过程可能会反复几次。
合并补丁并实际部署。
现有监控系统将确定新补丁是否会引发生产问题。如果我们的补丁引发中断,我们自然有责任进行修复。在整个流程的各个阶段中,通常都会有一款工具来锚定开发者的实际体验。具体工具会塑造我们的工作周期,并对生产力产生巨大影响。
为了提高生产力,最好能在各个步骤中找到更好的工具。这里向大家推荐一个实用的 GitHub repo,能够识别谷歌内部几乎每款工具所对应的最相似外部工具:https://github.com/jhuangtw/xg2xg。
这份列表非常全面,但内容也确实太多了。那我们该从哪里入手呢?
先熟悉现有工具离开谷歌之后,在新公司入职的第一个月,先别急着做出改变,多听、多学习。
作为团队的新成员,大家还没有足够的影响力或者权限来变更团队使用的各种工具。另外,我们也缺乏实践知识,比如不清楚新团队如何工作、为何选择这种工作方式、为什么要使用当前工具集。
如果你简单地把谷歌内部工具复制过来,并不一定就能在新团队中实现良好效果。因此,你需要先摸索一下哪些工具适合新团队使用,哪些并不适用。
大家可以先从代码搜索起步。事实上,当一个程序员离开谷歌之后,他最怀念的往往就是代码搜索工具。
你可以自己尝试不同的代码搜索引擎,验证它们究竟效果如何,并在确定有效后再向同事推荐。千万别急着把自己都不熟悉的工具推荐给同事,或者提交给决策者进行审查。
同时,你也不必改变他人的原有工作习惯,毕竟新团队往往还没有用上代码搜索工具。即使已经在用,也就是分两种情况:比较差的情况是,他们选的工具效果一般、使用频率不高;比较好的情况是,他们选的工具已经非常出色,不用再费心。
如果你所在的新公司旗下拥有多支开发团队,那么需要处理的代码可能更多,作为新员工当然有必要去理解这些代码。而即使是在小而精的初创公司,也有可能通过依赖项的方式引入了大量开源代码。只有深入研究了这些代码,我们才能进行后面的新功能构建或关键 bug 跟踪等工作。
如今,几乎每位开发者都必须面对庞大的代码规模,所以如果代码搜索工具跟不上,绝对会大大降低你的开发速度。
在评估代码搜索引擎时,我们需要考虑以下几个重点:
查询语言:正则表达式是关键。我们需要保证代码搜索查询语言既富有表现力,又简单易用。字面搜索应该更直观,而且提供更高级的模式匹配功能。
规模:确保代码搜索引擎的规模适应性能够匹配你的代码库大小。如果你的代码库超过数 GB,那么代码搜索引擎是否支持三元组索引(https://swtch.com/~rsc/regexp/regexp4.html)就非常重要了,这也是我们以常规方式在大型代码库上实现表达式匹配的唯一方法。
代码浏览:作为谷歌代码搜索(Code Search)的用户,大家都知道搜索本身只是故事的一半。单击结果之后,我们当然希望能够继续点击、跳转至相应定义并找到引用部分,整个过程应该像签出代码并在 IDE 中设置开发环境一样轻松。如果没有出色的代码浏览体验作基础,我们就得经常在编辑器和代码搜索引擎之间来回切换。
权限:如果你所在的公司强制推行代码库权限,那就应该考虑代码搜索引擎是否支持这些权限。
总体成本:需要同时考虑代码搜索引擎的价格,与保持工具运行的维护开销。以下是我们平时常见的代码搜索引擎:
OpenGrok: 一款相当古老、但仍具生命力的代码搜索引擎,现由甲骨文负责维护。
Hound: 一款由 Etsy 工程师创建并开源的代码搜索引擎。
Livegrep: 一款由 Stripe 公司 Nelson Elhage 创建的代码搜索引擎。当然,还有我们自己开发的 Sourcegraph
另一个重要的早期目标,就是监控。每位工程师在特定情况下都需要处理生产问题。请注意,生产环境跟开发环境完全是两码事,我们不可能在生产环境下设置断点或添加 printf,并指望在几秒内就看到结果。另外,生产环境的更新对应着极高成本:计算资源、开发者时间,还有可能给客户带来的糟糕体验。
过去 5 到 10 年来,部署思路发生了很大变化。微服务、Kubernetes、云迁移等一系列新生事物,都标志着企业软件部署方式上的重大转变。不少企业开始采用这些新的范式和技术,但并没有更新自己的监控基础设施,所以很难在新型生产环境下开展调试。
幸运的是,近年来涌现出一些伟大的开源工具和厂商,他们用努力极大改善了谷歌之外的监控与可观察性工具选项。
Prometheus 是一款类似于 Borgmon 的时间序列指标跟踪器兼可视化器。它能帮助大家检测自己的应用程序,随时间推移持续跟踪 CPU 利用率、错误率及 90 百分位延迟等指标。
Grafana 是一款类似于 Viceroy 的仪表板工具。大家经常会将 Grafana 与 Prometheus 匹配起来,由此构建起包含一系列关键指标的单页视图,根据这些指标了解应用程序的整体健康状况。
谷歌率先使用了 Dapper 这一面向多服务架构的重要分布式跟踪工具。Dapper 的缔造者之一 Ben Sigelman 随后又打造出 Lightstep。分布式跟踪现已成为众多监控系统中的一项功能,包括 Honeycomb 和 Sentry 这类付费产品,以及由 Uber 工程师开发的 Jaeger 等开源项目。监控要比代码搜索更复杂一些,因为其必须要集成到生产环境当中。这往往涉及更改部署环境,所以必须要跟负责控制部署环境的团队协调并配合。另外,其中还可能涉及添加检测代码,也就是向持有被检测代码的各团队提交补丁。
但总体来讲,引入新工具并不需要改变其他同事的原有工作习惯,所以难度不算太高。人们可以自由选择使用或不使用新工具,所以前期推广压力不会太大。
代码搜索和监控的引入,并不会影响到任何团队成员的现有工作流程。但代码审查工具却不一样,它会实实在在影响到同事们的工作方式。
如果大家在谷歌工作过一段时间,那么离开谷歌后可能会觉得外面的代码审查方式有点奇怪。GitHub PR 就是最常见的代码审查工具,但谷歌员工还是能从中发现不少问题:
不太容易查看自上一轮审查之后出现的变更,有时候甚至根本查看不到。简单的路径只允许我们查看尚未完成部分的差异。
不支持堆叠 CR。
变更页面是把所有文件中的全部差异都集中在一起,很难弄清我们面对的到底是哪个具体部分。
GitHub PR 并没有设计出明确的审查路径。如果不添加额外的第三方集成,整个审查流程会显得非常松散。而即使有了第三方集成,其中仍然缺乏细粒度的审查与签署政策。
对于某些语言,GitHub PR 对模糊跳转至某定义或查找引用的支持效果很差,完全不能跟谷歌内部的 Critique 相提并论。在谷歌之外,我们能找到的跟 Critique 最接近的工具当数 Gerrit 了。Gerrit 最初属于 Rietveld 的一个分支,而 Rietveld 本身又是谷歌原始代码审查工具 Mondrian 的一个开源分支。因此,正是这种血脉传承让人们在 Gerrit 身上感受到了谷歌眼中的代码审查思路。
Phabricator 也是一款不错的代码审查工具,反正对前谷歌员工来说要比 GitHub PR 强不少。Phabricator 最初是 Facebook 的内部代码审查工具,随后被开源了出来。它的背后由 Phacility 公司负责运营,为其提供托管实例和支持,能为那些不愿自行维护实例的客户分担压力。
另一款值得关注的工具,则是由前谷歌员工 Piotr Kaminski 开发的 Reviewable。与 Gerrit 或者 Phabriactor 不同,Reviewable 只支持云环境,但换来的则是最接近于谷歌内部的代码审查体验。
在向团队其他成员介绍 Gerrit、Phabricator 或者 Reviewable 的优点时,请务必关注大家对于原有代码审查工具的感受。从 GitHub PR 等转向 Gerrit 之类的工具,可以有效解决以下几大常见痛点:
Gerrit 能够明确的签署机制,让审查流程的结构化水平更上一层楼。如果团队规模正在不断扩大,而且希望在组织内实施更严格的审查政策,那 Gerrit 绝对物有所值。
Gerrit 能够简化大规模差异的审查难度,允许我们逐一文件查看、查看自上轮审查以来的变更以及堆叠 CR,最终实现更快、更彻底的审查效果。Gerrit、Phabricator 和 Reviewable 都能让大家朝着谷歌内部的常规审查流程更进一步,但仍然缺失重要一环:代码智能。Sourcegraph 浏览器的扩展能够在代码审查期间提供工具提示、跳转至定义和交叉引用等,它适用于 GitHub PR、GitLab MR、Phabricator 以及 Bitbucket Server,对 Gerrit 的支持也正在开发当中。
软件开发生命周期当中,最棘手的部分往往就是 CI 和 build 系统。这是因为要想理解整个 build,就必须以非常具体的方式观察整个代码库的每一部分。随着时间推移,大家都希望加快构建速度,所以 build 代码也就积累了越来越多的调整和优化部分,导致投入大量人手也未必能实现无痛更新。
简而言之,build 系统就是最后的守关 Boss,所以在完成前面的“打怪升级”积累之前,千万不要轻易尝试。但它又时刻在诱惑在我们,毕竟跟现有工具相比,Blaze 实在是太强大了。谷歌甚至以 Bazel 的名号对 Blaze 进行了开源。但 Bazel 毕竟不是 Blaze,它缺少大规模分布式 build 集群,而且毕竟不是运行在谷歌内部。
所以先要承认,Bazel 绝不是什么万金油。当初刚刚发布时,Go 社区中就有很多开源项目转用它来支持标准 Go build 工具。但不到一年,由于使用太过复杂、Go 社区内很多成员对它不够熟悉,以及 Bazel 的构建速度似乎更慢等现实,大家又纷纷选择放弃。从那时起,Bazel 对 Go 语言的支持虽然实现了重大改进,但还是建议大家在使用之前认真做一番评估。
为了开展这项严格评估,我们先得把其他开发工具落实到位:包括出色的代码搜索,确保真正深入到代码库中各部分的 build 脚本当中,理解它们的作用和依赖关系。大家还需要出色的代码审查工具,确保 build 系统的变更能够在不同工程团队之间获得支持和协同。
在做好准备之后,还要明确一点。除 Bazel 之外,还有很多其他 build 工具能够在大型代码库中实现可扩展构建。具体包括:
Buck, 来自 Facebook。
Gradle, 在 Java 世界中很受欢迎。
Pants, 由前谷歌员工为 Twitter 和 Foursquare 所设计。
Please, 一款新型 build 工具,由前谷歌员工受 Blaze 启发创建而成。
还有 YourBase,它虽然不属于 build 工具,而是由前谷歌员工 Yves Junqueira 开发的 CI 服务,但确实能够提供超快且可扩展的构建体验,而且完全独立于实际底层 build 工具之外。谷歌拥有着不同于大多数其他公司的企业文化,包括优先考虑开发者体验的强大工具储备。谷歌前员工们曾经感受过这些最先进的开发工具,所以永远忘不掉这段能够充分发挥自身天赋和能力的经历。
在离开谷歌之后,大家的一大竞争优势,就是利用这些经历将出色的开发体验融入新的组织,借此提高自己和其他团队成员的工作效率。配合上述大规模软件开发最佳实践,各位完全可以将谷歌那极高的工程组织协同能力转化为新公司的底层实力。
大规模软件的构建过程相当复杂。有经验的朋友都知道,单靠堆人手是无法获得更好的软件的,我们还需要更好的工具。正如优秀的软件会成为最终用户的生产力放大器,出色的开发工具也是软件开发者的生产力放大器。因此,如果大家愿意作新公司的主人翁,不妨利用自己前谷歌员工的专业知识,将世界一流的开发者工具引入这片全新的天地。
原文链接:
https://about.sourcegraph.com/blog/ex-googler-guide-dev-tools
往期推荐