我最喜欢问工程候选人的面试问题之一,是告诉我有关以前公司的工程文化最喜欢和最不喜欢的一件事。我采访了 500 多人——其中许多人来自 Facebook、谷歌、亚马逊、Palantir 和 Dropbox 等顶级科技公司——随着时间的推移,这个面试问题让我了解了优秀的工程师在寻找什么以及他们试图避免什么。
回顾面试回答以及我过去七年在 Google、Ooyala 和 Quora 工作的经历,我总结了团队可以做的十件事来建立良好的工程文化。
一、优化迭代速度
快速迭代增加了工作动力和兴奋度。部署代码和发布功能时基础设施和官僚方面的障碍,是工程师在面试中提到的他们为什么离开目前公司的一些最常见和令人沮丧的原因。
- 在组织上,快速迭代意味着赋予工程师和设计师灵活性和自主权,无需征得许可即可做出日常决策。当我在 Google 时,任何用户可见的搜索结果更改,即使是低流量实验,都需要在每周一次的 UI 审查中获得 Marissa Mayer 的批准。毋庸置疑,虽然这让谷歌能够保护其搜索品牌,但它严重阻碍了创新。优化迭代速度还意味着有明确定义的产品发布流程,在投入大量时间后不会被意外取消。
- 在基础架构上,优化迭代速度意味着构建持续部署以支持快速验证、高测试覆盖率以减少构建和站点损坏、快速单元测试以鼓励人们运行它们,以及快速增量编译和重新加载以减少开发时间。持续部署,值得特别提及,即提交立即投入生产。在 Quora 使用它之前,我很难理解它为迭代速度提供的好处超过了站点损坏的风险,至少对于小型工程团队而言。人们对功能更感兴趣,同时也有动力修复错误,因为变更能够很快看到实时流量效果。
- 在团队方面,快速迭代意味着拥有一组强大的领导者来帮助协调和推动团队努力。决策中的关键利益相关者需要有效地做出决定并致力于他们的选择。借用曾执教 49 人队 3 次超级碗的领袖比尔沃尔什的一句话,强大的领袖需要“承诺、爆发、恢复”,这意味着承诺进攻计划,执行它,然后对结果做出反应。优柔寡断的团队只会使个人努力陷入困境。
二、不懈地推动自动化
在技术演讲“Scaling Instagram”中,Instagram 联合创始人 Mike Krieger 将“优化最小化运营负担”作为他的 13 人团队在将产品扩展到数千万用户时学到的重要一课。随着产品的增长,每个工程师的运营负担也随之增加,衡量标准是用户与工程师的比率或功能与工程师的比率。例如,Facebook 以推崇扩展指标而闻名,例如每个工程师支持超过 100 万用户。
自动化解决方案和编写重复性任务的脚本很重要,因为它们可以让工程团队腾出时间来处理实际产品。确保服务在发生故障时尽可能自动重启,并在高峰流量时轻松快速地复制服务,这是大规模管理复杂性的唯一明智方法。在短期内,手动应用快速补丁而不是自动化和测试长期修复是总存在的诱人权衡。
Etsy 的座右铭是“衡量任何事情,衡量一切” 及其对开源监控和图表工具(如graphite和statsd)的支持突出了自动化的一个重要方面——自动化必须由数据和监控驱动。如果没有监控和日志来了解出现问题的方式或原因,自动化就很困难。一个很好的后续格言是“衡量任何事情,衡量一切,并尽可能实现自动化”。
三、构建正确的软件抽象
我的麻省理工学院教授和本科生研究顾问 Daniel Jackson 很好地抓住了软件抽象的重要性:
“选择正确的,编程就会从设计中自然而然地流动起来;模块将具有小而简单的接口;新功能更有可能在不进行大规模重组的情况下适应。选择错误的,编程将是一系列令人讨厌的惊喜:界面将变得巴洛克式和笨拙,因为它们被迫适应意料之外的交互,即使是最简单的更改也很难做出。”
让成千上万的工程师在 Google 构建可扩展系统的部分原因是像 Jeff Dean 和 Sanjay Ghemawat 这样真正聪明的工程师构建了简单但通用的抽象,如MapReduce、SSTable、Protocol Buffers等。允许 Facebook 工程扩展的部分原因是专注于类似的核心抽象,如Thrift、Scribe和Hive。让设计师能够在 Quora 有效构建产品的部分原因是Webnode 和 Livenode相当容易理解和构建。
保持核心抽象的简单性和通用性可以减少对自定义解决方案的需求,并增加团队对通用抽象的熟悉程度和专业知识。Memcached、Redis、MongoDB 等系统的日益普及和可靠性降低了构建自定义存储和缓存系统的需求。将团队的注意力集中在少数核心抽象上,而不是将其分散在许多临时解决方案上,这意味着公共库变得更加健壮,监控变得更加智能,性能特征得到更好的理解,测试变得更加全面。所有这些都有助于简化系统并减少操作负担。
四、通过代码审查培养对高代码质量的关注
维护高质量的代码库可以提高整个工程团队的生产力。更简洁的代码更易于推理、开发更快、更易于更改且不易受错误影响。健康的代码审查过程使这成为可能。
建立及时的代码审查流程,无论是提交前还是提交后,都可以通过多种方式提高代码质量。首先,知道有人会审查你的代码,以及提交写得不好的代码可能会让你的队友失望的同行压力是对黑客、不可维护或未经测试的代码的强大威慑。其次,代码审查为代码审查者和作者提供了相互学习以编写更好代码的机会。
如果工程团队的其他成员可以轻松访问代码审查,那么审查还会带来以下好处:
- 增加及时审查代码的责任
- 允许团队成员(尤其是新成员)进行建模其他人的良好代码审查
- 加速最佳编码实践的传播
敏捷团队没有时间花在代码审查上的反驳忽略了技术债务,这些债务很容易因编写不当的代码而累积。Ooyala,在其早期的创业时期,过去常常通过优化来尽可能多地推出功能,而没有代码审查;结果是,虽然最初的产品可能更快地上市,但最终的代码修改起来很痛苦,我们花了一年多的时间来重写脆弱的代码以消除技术债务。
就其规模而言,谷歌确实对所有代码进行了预提交代码审查,但较小的团队不需要那么全面或严格,而且并非所有代码都需要以同样的严格性进行审查。当我在那里时,Ooyala 后来通过电子邮件对核心或有风险的更改进行了提交后审查。
在 Quora,我们在Phabricator 中进行了所有代码审查,主要是 post-commit,并对模型或控制器代码和视图代码应用不同的标准;对于敏感代码或新工程师的代码,我们要么进行预提交审查,要么尝试在代码提交后的几个小时内对其进行审查。
五、保持相互尊重的工作环境
同行之间的尊重构成了任何类型的开放式交流的基础。人们可以轻松地挑战彼此的想法的地方是通过辩论形成合理想法的地方。人们很容易被冒犯的地方是关键反馈被隐瞒的地方。
1948 年,亚历克斯·奥斯本 (Alex Osborn) 概述了过去几十年来在工作环境中流行的熟悉的头脑风暴方法,参与者聚集在一起,搁置批评和负面反馈,将创意汇集在一起,而不必担心受到评判。尊重地推迟判断是此类头脑风暴会议的关键。最近的心理学研究开始推翻奥斯本的方法,认为在头脑风暴会议中鼓励辩论实际上有助于避免群体思维并产生更有效的想法。根据这项研究,一个相互尊重的环境变得更加重要,因此攻击是针对想法而不是针对人的。
工程通常跨越广泛的领域(系统、机器学习、产品等),并不是每个人在每个领域都拥有相同的专业知识。事实上,一个强大的团队可能应该拥有在某些领域特别强大的人,即使他们最终在其他方面有所欠缺。这有时会让系统工程师很难评估产品工程师的熟练程度,但在健康的工程文化中,尊重这些差异而不是仅仅根据自己的优势进行判断很重要。
六、建立代码的共享所有权
虽然个人精通代码库或基础设施的各个部分是很自然的,但没有人应该觉得他们拥有或者自己是任何一个部分的唯一维护者。虽然让个人成为拥有某些领域一年或更长时间的专家可能会在短期内提高效率,但从长远来看,这种方法最终会产生巨大的伤害。
在组织上,共享代码所有权提供了三个好处。
- 首先,保持总线因子大于 1 可以减轻维护人员的压力,并在维护人员离开时降低团队的风险。这也让那个人很难无忧无虑地休假。我当然不会错过我是 Ooyala 日志处理器的唯一维护者的日子,并在我在夏威夷的火山上度假远足时被寻呼。
- 其次,共享所有权使在特定领域不够深入的工程师能够贡献新的见解。它让工程师们从被困在某些项目上的感觉中解脱出来,并鼓励他们从事多样化的项目,这有助于保持工作的趣味性并促进员工的学习和积极性。从长远来看,它降低了一些工程师感到停滞并决定离开的组织风险。
- 第三,共享所有权还为在需要更快完成战略目标时让多个团队成员聚集在一起(敏捷开发的一种技术)一起解决高优先级问题奠定了基础。对于孤立的所有权,负担通常落在一两个人身上。
许多工程组织过早犯下的一个错误是,在团队还很小的时候,将整个团队划分为由技术主管组成的子团队。子团队建立了所有权墙,从而减少了跨越这些墙的动机,因为个人可能会根据其子团队的目标进行评估。当我在那里时,Ooyala 有一些子团队,而我错过的一件事是与其他团队的一些人一起工作的机会;从那以后,他们采用了敏捷开发流程,更加注重共享代码所有权,我听说这在工作幸福感和生产力方面取得了长足的进步。我喜欢 Quora 早期的一个方面是我们强调项目而不是团队,我有机会从事从用户增长、机器学习、审核工具、推荐、分析网站速度。
七、投资于自动化测试
单元测试覆盖率和一定程度的集成测试覆盖率是管理具有大量人员的大型代码库而不会不断破坏构建或产品的唯一可扩展方式。自动化测试为提高代码质量所需的大规模重构提供了信心和有意义的保护。在没有严格的自动化测试的情况下,工程团队或外包测试团队手动测试所需的时间很容易变得令人望而却步,并且很容易陷入害怕改进一段代码的文化,因为它可能会产生破坏。
在实践中,随着团队的成长,自动化测试是持续部署工作的必要条件。随着产品的发展,代码库的大小会随着时间的推移而增长,但随着新人的加入,团队成员对代码库的平均熟悉度会下降。与那些在数月或数年后试图修改代码的人相比,当原始代码作者对代码记忆犹新时,他们最容易进行测试和验证。鼓励强大的单元测试文化将验证责任转移到作者身上。
八、分配20%的时间
Gmail 起源于 Paul Buchheit 的 20% 项目,他在一天之内开发了第一个版本。Google News、Google Transit 和 Google Suggest 也作为 20% 的项目开始并推出。我在谷歌用 20% 的时间来编写了一个 python 框架,这使得构建搜索页面演示变得更加容易。虽然谷歌现在 20% 的时间可能比公司早期的效率低,但让工程师将 20% 的时间花在产品地图上没有的事情上的想法仍然是小型工程组织创新的摇篮。
当我在那里时,Ooyala 官方并没有 20% 的时间,但我还是抽出了一些时间,并为 Flex 和 Actionscript 编写了一个命令行构建工具,加快了团队的构建时间。我在 Adobe 的 Flex Builder 工具链开始退化时完成了它,即使工程团队的规模增加了两倍多,该工具仍在使用中。Atlassian 在试验了一年后采用了 20% 的时间。Facebook 喜欢和 Ooyala 后来添加的 20% 时间的变化是定期黑客马拉松 - 通宵活动,其中的规则是您可以从事除正常项目之外的任何事情。
自上而下的产品规划方法虽然对于关注公司的整体方向是必要的,但无法解释更接近地面的工程师可能产生的众多想法。只要工程师对他们 20% 的时间负责并专注于可能具有高影响力的变化,这些项目就可以在进展中取得重大进展。如果没有 20% 的官方时间,工程师和设计师仍然有可能尝试疯狂的想法,但要困难得多——专职人员基本上必须找到周末或假期才能做到。
九、建立学习和持续改进的文化
学习和接受足够的挑战是心理学教授 Mihaly Csikszentmihalyi 所称的“心流”状态的要求,在这种状态下,一个人完全专注于他们正在做的事情并受到激励,以至于他们甚至忘记了时间。更快的迭代周期提供的直接和即时反馈循环是另一个要求。
每周的技术讲座为工程师提供了分享他们的设计或他们构建的内容的论坛,为工程师创造了一个机会,让他们为自己的工作感到自豪,并让团队在他们的直接工作范围之外学习更多。在内部记录流程,例如电子邮件服务的工作原理或如何对搜索服务进行排名更改,还使工程师能够自行学习和探索新事物,很好地补充了 20% 的时间。在 Quora,我们通过运行 Quora 的内部实例来解决这个问题,我们在其中询问与产品和开发相关的问题。
建立学习文化的必然结果是专注于指导和培训,以确保每个人都拥有成功所需的基本算法、系统和产品技能。工程组织发展得越多,在招聘(尤其是大学招聘)上花费的精力就越多,就需要在指导和培训上投入更多的精力。一位导师每天为新员工的前 4 周花一个小时似乎很繁重,但这项投资只占新员工一年中花费的总时间的不到 1%,并且在确定此人是否为成功做好准备。
十、聘用最优秀的人才
聘用最优秀的人才是列出的许多其他理念的基础。如果您认为某人是 B 级工程师,则很难尊重他们。如果您不相信他们的产品直觉,就很难在产品开发方面给予他们自主权。如果没有足够的工程经验,很难识别出正确的抽象来构建。如果没有其他聪明人来挑战您的想法并推动您走向简单,很容易陷入构建复杂事物的陷阱。
硅谷有句谚语,由史蒂夫·乔布斯创造,“A 级球员雇佣 A 级球员。B 球员雇佣 C 球员。” 专注于招聘和雇用合适的人很难,但对于有效发展工程组织至关重要。曾任 Facebook 工程经理和总监的 Yishan Wong 认为,招聘必须是工程组织中每个人的第一要务,不仅是经理,工程师也是如此。他还非常正确地指出了“雇用最好的”和“雇用你面试过的最好的候选人”之间的区别。
在 Ooyala 的早期,我们对入站客户工作的队列如此不堪重负,以至于我们几乎屈服于降低招聘标准,以便我们可以雇佣足够的人来完成我们所有的工作。我很高兴我们没有这样做,因为团队中较低质量的代码和较弱的工程师造成的技术债务最终会损害团队和产品。
建立良好的工程文化当然需要大量的工作,但由此产生的工作环境是非常值得的。
原文:http://www.effectiveengineer....
作者:Edmond Lau
译者:冬哥
其实......建立一个伟大的工程师文化还有一种更简单的方式~
那就是.......开黑马呀~
IDCF DevOps黑客马拉松,2021年度城市公开赛,11月6-7日,深圳站,企业组队参赛&个人参赛均可,一年等一回,错过等一年,赶紧上车~公众号回复“黑马”加入
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。