阅读 186

[译]造就优良的软件开发团队文化的要素有哪些?

原文 What Makes A Good Engineering Culture

Soft & Share 取得 The Effective Engineer 作者 Edmond Lau 授权翻译。

我最喜欢问面试的工程师的其中一个问题–告诉我各一件在他们以前上班的公司中,他们喜欢和不喜欢的软件开发团队(译注 : 原文为 engineering ,但是内文都是意指软件开发和团队管理)文化。我已经面试了超过500人– 其中许多来自顶尖高科技公司像 Facebook ,Google,Amazon,Palantir,和 Dropbox – 随着时间的演进,这个面试问题给了我了一种感觉让我知道优秀的工程师在寻找什么样的软件开发团队文化和避免什么样的软件开发团队文化。从这些面谈回应给我的反思和我自己从Google、Ooyala、 和 Quora 7年的工作经验,我精选了十件软件开发团队可以做的事用来创建一个良好的软件开发团队文化。

1. 最佳化重复步骤(iteration)的速度

快速地重复步骤速度增加工作的动机和令人感到兴奋。因为基础建设和官僚政治阻碍了代码部署和新的功能上线,这是工程师在面试时想起来最常见而且最令人感到挫折感的事情,而且也是他们想离开目前公司的理由之一。

以组织而言,快速地重复步骤速度用意是给工程师和设计师拥有弹性和自主性,不用获得允许而可以去做日常的决策。当我还在 Google 时,任何用户可以看到的搜索结果变更,即使是低流量的实验,都需要 Marissa Mayer(译注 : 后来去 Yahoo 当了 CEO ) 在每周的 UI 审查会议批准。不必多说,此举是要保护 Google 这块搜索的品牌,但是这种方式确显著地阻碍创新。最佳化重复步骤速度也意味着有一个定义明确的产品推出的流程,所以经过有意义的投资时间后,取消产品上线这件事并不会不可预期的发生。

以基础建设而言,最佳化重复步骤速度用意在创建了持续部署以支持快速验证,高测试覆盖率,减少建置和站台毁损的风险,快速的单元测试激励工程师去运行它们,快速并渐增式编译和重载以缩短开发时间。特别值得一提,持续部署,可承诺马上进入产品准备上线状态。在 Quora 用持续部署之前,这技术的好处曾经对我而言很难去内化,持续部署得到的好处对于提升重复步骤速度比起避免站台挂掉的风险还更有价值,至少以小型的工程团队是如此。人们对于功能增加了感到兴奋和有诱因去修复 bug ,因为变更很快的从实际的流量看到。相较于一周或数周建构一次,或是有更多的批次修改,持续部署也更明显而容易去推理并查明从有限的代码提交中找出错误的来源。

从团队的角度来看,快速的重复步骤速度也代表具有一群强而有力的领导者去帮助协调和推动团队的努力。关键项目利益相关者(stakeholders)在做一个需求决策,需要有效率地决定并且承诺他们的选择。借用Bill Walsh 的一句话,他是带领旧金山49人(译注 一个美式足球队)赢得 3 次超级杯的教练,优秀的领导者需要 “承诺(commit),引爆(explode)、回复(recover)”,这意味要承诺攻击计划,运行它,针对结果做出反应。(注1) 一个团队因犹豫不决而削弱其能力只会导致个人的努力举步维艰。

2. 毫不留情地推向自动化

Instagram 共同创办人 Mike Krieger 在他的技术演讲 “Scaling Instagram” 中,谈到 “为最小的操作负担做最佳化” 是他的13人开发团队在产品扩展到数千万用户时学到了关键的一课。(注2) 当产品成长时,每位工程师的操作负担也会增加,这可以用每多少用户需要多少工程师的比率来衡量或是多少功能需要多少工程师。例如,Facebook 以宣扬它的延展指针(scaling metrics)而闻名,像是每一位工程师支持超过100个万用户。(注3)

自动化解决方案和将重复性任务脚本化(scripting)是很重要的,因为这件事释放出了工程团队的时间可以用在实际产品开发的工作上。如果服务器失效,确保它们尽可能会自动重新启动,并且会在流量高峰时,简单而且快速地复制自己,这是在规模扩大时,唯一明智的方式去管理复杂度。以短期眼光,总是会有诱惑宁可采用快速匆忙拼凑的手动折衷方法,而不要用自动化和测试一个长期的修正。

Etsy 的座右铭–“度量任何事,度量一切” (注4) 这样的需求可以使用开放原代码的监控与图表工具像是 graphite 和 statsd 来达成,这句话强调了自动化的一个重要面向–自动化必须被数据和监控所驱动。如果没有监控和日志去了解发生什么事、有些事情是如何出错、或是为什么出错了,自动化变成是困难的一件事。一个好的遵循座右铭会是– “度量任何事,度量一切,尽可能自动化一切”。

3. 创建正确的软件抽象层

我的 MIT 教授和大学研究指导教师 Daniel Jackson 指出了良好的软件抽象层重要性 (注 5)

“选择对的抽象层设计, 编程将会从抽象层设计去自然地遵循, 模块将会有小而简单的接口 ; 不需要过度的重新组织代码,加入新的功能也很容易适应。然而选择错误的抽象层设计,编程将会出现一连串令人讨厌的意外 : 接口将会变成结构复杂而且笨拙的,程序员被迫去适应无法预期的交互作用, 甚至连最简单的变更都很难去进行。”

可以让数千名Google 工程师可以建置可延展性的系统其中一部分原因是 Google 拥有像是 Jeff Dean 和 Sanjay Ghemawat 这样真正聪明的工程师建构了像是 MapReduce, SSTable, Protocol Buffers 简单且多才多艺的抽象层,相同的,可以让 Facebook 工程师去延展他们的系统其中一部分原因是他们专注在相似的核心抽象层像是 Thrift,Scribe, 和 Hive。在 Quora 有一部分原因可以让设计师更有效率地建构产品是因为有建置在其上相当简单而且容易了解的 Webnode 和 Livenode 。

保持核心抽象简单而且通用减少了客制化解决方案的需要并且增加了团队的熟悉度与具备有共同抽象层的专门技术。逐渐普及和可靠的系统像是 Memcached, Redis, MongoDB, 等等已经减少需要自行创建客制化保存和缓存系统。宁可让开发团队像漏斗状,灌注注意力在少数的核心抽象层也不要分散注意力在特定的解决方案。这也意味共用的程序库会更稳健,监控变得更聪明,性能特征得到更好的理解,测试取得更多的全面性。所有这一切都有助于一个可以降低营运负担的简单系统。

4. 使用代码审查流程专注产出高品质代码

维护一个高品质的代码库,提高了整个工程团队的生产力。整洁的代码更容易理解,更快速去开发,更适应于变化,并且较不容易受 bug 交互影响。一个健康的代码审查流程让这一切成真。

创建及时的代码审查流程,无论是在 pre-commit 或是 post-commit 后,在几个方面提高了代码品质。首先,有人要审查你的代码的同侪压力和因为提交了设计不良的代码将会浪费同事的时间,这对于采用不当技巧的、无法维护的、未经测试的代码有吓阻的作用。其次,代码审查提供了代码审查者和作者交流的机会,彼此互相学习而写出更好的代码。

如果代码审查流程很容易被工程团队的其他成员容易接近使用,那么代码审查也顺便带来以下的好处 a) 增加对及时审查代码方式的责任感 b) 让团队成员–特别是新进的成员,从其他人好的代码审从中学习 c) 加快宣传最佳的编程实践。

反观,追求快速的开发团队没有把时间花费在代码审查,而忽略了不好的代码很容易累积技术债。Ooyala 在它非常早期公司刚开始的时候,习惯于最佳化尽可能地实作出越多的功能越好,却疏于做代码审查, 最后造成了结果–虽然最初的产品可以很快地推向市场,但是产生的代码变得修改起来很痛苦, 我们花了一年的时间也只是在改写脆弱的代码以消除技术债。

Google 在公司还很小的时候,对于所有的代码有做 pre-commit代码审查 但规模较小的团队并不需要那么全面或严格,而且所有代码不需要同样严格地审查。Ooyala,我在那里的时候 采用了 post-commit 方式通过电子邮件通知来审查核心或是高风险的代码变更。在 Quora,我们透过 Phabricator进行的所有代码审查,大部分透过 post-commit 方式,模型( model )或控制器( controller )代码和视图( view )代码采用了不同的标准; 敏感代码或从新进工程师产出的代码,我们使用 pre-commit 做代码审查或是试着在提交代码前花几个小时内做审查。

5. 维持一个彼此尊重的工作环境

同事之间的尊重形成了任何形式开放沟通的基础。一个让人们感到自在去互相挑战对方想法的地方,也是一个合理的概念会经由辩论而前进的地方。一个人们很容易被冒犯的地方,也是重要的回馈会被压抑的地方。

在 1948,Alex Osborn 介绍了知名的脑力激荡方法,这在过去的几十年工作环境中一直很受欢迎,参加者会聚在一起,抛开批评和负面回馈并且共同一起激荡出创造性的想法,不会有被批判的恐惧。(注 6) 这种形式的脑力激荡会议关键在它尊重任何潜在创意。最近的心理学研究已经开始推翻 Osborn 的做法,建议在脑力激荡会议鼓励辩论在实际上有助于避免群体思维,并产生更有效的思路。在这项研究中点指出,抨击是针对概念想法而不是做人身攻击,这在一个彼此尊重的环境中变得更加关键。(注 7)

工程往往跨越广泛的领域(系统,机器学习,产品等)而且不是每个人在每一个领域都同有同样的专业知识。一个强大的团队里面应该有一些人对特定领域专精,即使他们跟别人相较之下有不足之处。这样有时候说起来有点复杂,例如让系统工程师来评估产品工程师的专长, 但去尊重这些差异性在一个健康的工程师文化是很重要的,而且并不能完全根据自己的优势去评断。

6. 创建代码共享所有权

当很自然地每个人对于代码库不同部分的代码或是架构变得逐渐精通,就没有人会觉得他们是任何代码一部份的拥有者或是唯一的维护者。以短期而言,当一个人拥有特定范围的代码一年会成为专家或是更能增加工作性能,但是这种做法最终从长远看对团队而言是伤害的。

在组织中,共享代码所有权提供了三个好处。首先,让巴士因子(bus factor 见注 8)大于一使维护者释放压力并且帮团队降低了风险如果维护者离职了。对于一个人在放假中还不用担心工作是很困难的一件事。我肯定不会想念我在 Ooyala 是唯一维护日志处理器开发者的那段日子,当我在夏威夷度假爬火山时,竟然还会收到短信要求处理问题。

第二,共享代码所有权授权给那些没有深入特定区域代码的工程师贡献新鲜的见解。让工程师免于屈就于特定项目的感觉并且鼓励他们参与不一样的项目,这有助于维持工作的乐趣,并提升员工学习意愿和动机。从长远来看,它降低组织有些工程师感到成长停滞而定离开的风险。

第三,共享代码所有权,必要时要更迅速地完成战略目标,让多个团队成员共同协作(swarma together: 来自敏捷开发的技术)一起解决高优先级的问题殿定了基础。孤立代码的所有权(译注 谷仓效应),责任通常落在一个或两个人身上。

一个错误发生在许多任务程组织单位–当团队还在很小的时候,太早切割成许多子团队并有各自的技术领导者。子团队打造的所有权这道墙,并减少了动机去越过那道墙。因为个人可能只会以子团队的目标来评估。当我还在 Ooyala 公司 时还有子团队,我错过了与其他团队其中一些人一起工作的机会。他们已经采用了敏捷开发流程并且有更大的重点放在共享的代码所有权,我听说已在工作幸福感和生产力上有巨大的进步。在 Quora 工作的初期,让我乐在其中的一个原因是我们超越团队来强调项目,所以我有机会参与项目从用户增长、机械学习、调节工具、 推荐机制、分析、网站速度和垃圾消息检测。

7. 投资于自动化测试

单元测试的覆盖率和一定程度的集成测试覆盖率是唯一可以延展的方法来管理由大型开发团队维护的较大的代码基底(codebase),不会经常破坏了建置(build)或是产品。自动化测试提供了信心和针对了要提高代码品质而做大规模的重构有意义的保护。缺少了严格的自动化测试,需要由工程团队或外包测试团队做手动测试的时间是容易变成令人望而却步,而且很容易陷入一种恐惧去改善一段代码的文化,只是因为它有可能被破坏了什么。

在实务中,当团队成长时,自动化测试是让持续部署可以作业的需求。当产品成长时代码基底(codebase)的大小也随着时间成长,但是当新进工程师加入,团队成员对于代码基底(codebase)的平均熟悉度也随之下降。当代码在开发者的脑海里还记忆犹新的时候, 这时候测试和验证代码比较容易被原开发者来完成,相较于写完代码一个月后或是一年后再来修改。鼓励强大的单元测试的文化,将验证责任转移朝向原开发者。

8. 分配 20 %的时间策略

Gmail 发现它的根源是在 Paul Buchheit 的 20% 项目,而且他只花了一天的时间做出了第一版。(注10) Google 新闻、Google Transit 和 Google Suggest 也是从 20 % 项目发起的。在 Google ,我用 20% 的时间,写了一个 Python 框架,使得它来建置搜索页面演示显著更容易。虽然 Google 现在的 20% 时间跟公司刚开始的那段日子相较,产出是比较少的。(注11) 让工程师花 20 % 的时间做某件事情跟他们的负责产品路线(product map)无关的概念,依然是小型工程组织创新的摇篮。

我还在 Ooyala 工作时,没有正式有20%的时间策略。但我花了一些时间写了一个 Flex 和 ActionScript 命令行(command-line)编译工具,加速了团队的构建(build)时间。我完成这个工具的时候刚好 Adobe 的 Flex Builder 工具炼开始走下坡,该工具仍然在使用,即使当工程团队的规模较原本成长了三倍。经过一年实验,Atlassian 也采用了20%的时间策略。(注12) 一种受到 Facebook 的喜爱的 20% 时间策略变种,Ooyala 后来也采用了,就是定期的举办黑客松(hackathons)–一个通宵达旦的活动,其中的规则是除了你平常的项目,你可以做任何事。(注13)

自上而下的方法做产品规划,而且必须聚焦公司的总体方向,无法自最接近基层的工程师取得最多的创意。 只要工程师为他们 20% 的时间负责,并且专注于可产生高影响力的变更 ,这些项目可以跨出较大的脚步并往进步方向前进。没有正式的 20%的时间,这些事仍然是可能发生,但是对于工程师和设计师去尝试疯狂的概念是比较困难的。专注的人基本上必须利用周末的时间或是自己的假期来做这些尝试。

9. 创建一个持续学习和改善的文化

学习和充分的得到挑战是进入心理学教授 Mihaly Csikszentmihalyi 称之为“心流”状态(或是神驰状态)的需求,如果人进入这样的状态完全集中精神和被他们正在做的事所驱动,他们甚至忘了去追踪时间。(注14) 通过快速的重复步骤(iteration)周期得到直接和快速的回馈循环(feedback loop)是进入“心流”状态的另一种需求。

每周的技术讲座提供了论坛(forum)让工程师们分享他们的设计或是开发的作品,创造一个机会,让工程师以他们的工作感到骄傲和让团队学习到更多他们目前工作以外的技术。将内部流程文档化,像是 email 服务是如何运作的或是如何对搜索服务做排名变化,这也给予工程师权力自己主动去学习和探索新的技术,恰到好处跟 20 % 时间策略形成互补。在 Quora,我们在内部有自己的 Quora 服务器,在上面我们会问跟产品和开发相关的问题。

一个创建学习文化的必然结果是专注在师徒(mentoring)制和教育训练去确认每一个人有基本的算法、系统和为了确保产品成功所具备的开发技能。随着工程组织成长更大要花更多功夫投入在招募上(特别是学院招募),也需要花更多力气投注在师徒制辅导和教育训练。对于一位独立的导师(mentor),每天花一个小时在一位刚到职4周内的新进工程师的工作上,这似乎是一件沈重的工作,但是这个投入时间少于新进工程师一年内将会花费所有时间的 1% ,这有了很明显的杠杆作用在决定新进工程师是否成功融入团队。

10. 招聘最好的人

招聘最好的人,是上述我所提出的许多点论述的基础。要去尊敬一位你认为对方是B级工程师的专业能力是很困难的一件事。如果你不信任某人的产品直觉(product instincts) ,让他们在产品开发上有自主权是很困难的。如果没有足够的软件工程经验,要去识别正确的抽象层来创建是很困难的。如果没有其他聪明的工程师去挑战你的概念和驱使你朝向简单化,很容易掉入建构一个复杂软件架构的陷阱。

在硅谷流传一个 Steve Jobs 创造的说法 “A 级玩家聘请 A 级玩家。B 级玩家聘请 C 级玩家”。(注15 16) 专注在招募并且聘雇对的人是困难的但是对于一个工程组织有效率地成长是很关键的。Yishan Wong ,他先前在 Facebook 担任工程经理和主管,主张招聘已成为大家在工程组织的首要任务,并不仅仅针对管理者,还包含工程师。(注17) 他还准确地指出 “招聘最好的” 和 “招聘最好的候选者” 之间的区别。

Ooyala 的早期,我们因为客户排入的工作而如此不堪重负,我们几乎降低招聘的标准所以我们可以聘雇足够的工程师来完成所有的工作。我很高兴我们没有这样做,从较差品质代码和团队中的较弱工程师产生的技术债将不会停止伤害团队和产品。

创建一个良好的软件工程文化肯定要花费很多的功夫,但由此产生的工作环境是非常值得的。

这篇博客文章源自于 Edmond 在 Quora 上的回答。

如果要找 Edmond 演讲关于软件工程文化相关主题的演讲可以跟他联系 。

关于这篇文章作者

Edmond 目前教导软件工程师和技术经理如何有效率的创建有意义的影响力。

他是 Quip 早期的软件工程师,曾经在 Quora、Google和 Ooyala 带领软件开发团队。

关注下面的标签,发现更多相似文章
评论