原文 What Makes A Good Engineering Culturenode
Soft & Share 取得 The Effective Engineer 做者 Edmond Lau 受权翻译。程序员
我最喜欢问面试的工程师的其中一个问题–告诉我各一件在他们之前上班的公司中,他们喜欢和不喜欢的软件开发团队(译注 : 原文为 engineering ,可是内文都是意指软件开发和团队管理)文化。我已经面试了超过500人– 其中许多来自顶尖高科技公司像 Facebook ,Google,Amazon,Palantir,和 Dropbox – 随着时间的演进,这个面试问题给了我了一种感受让我知道优秀的工程师在寻找什么样的软件开发团队文化和避免什么样的软件开发团队文化。从这些面谈回应给个人反思和我本身从Google、Ooyala、 和 Quora 7年的工做经验,我精选了十件软件开发团队能够作的事用来建立一个良好的软件开发团队文化。web
快速地重复步骤速度增长工做的动机和使人感到兴奋。由于基础建设和官僚政治阻碍了代码部署和新的功能上线,这是工程师在面试时想起来最多见并且最使人感到挫折感的事情,并且也是他们想离开目前公司的理由之一。面试
以组织而言,快速地重复步骤速度用意是给工程师和设计师拥有弹性和自主性,不用得到容许而能够去作平常的决策。当我还在 Google 时,任何用户能够看到的搜索结果变动,即便是低流量的实验,都须要 Marissa Mayer(译注 : 后来去 Yahoo 当了 CEO ) 在每周的 UI 审查会议批准。没必要多说,此举是要保护 Google 这块搜索的品牌,可是这种方式确显著地阻碍创新。最佳化重复步骤速度也意味着有一个定义明确的产品推出的流程,因此通过有意义的投资时间后,取消产品上线这件事并不会不可预期的发生。算法
以基础建设而言,最佳化重复步骤速度用意在建立了持续部署以支持快速验证,高测试覆盖率,减小建置和站台毁损的风险,快速的单元测试激励工程师去运行它们,快速并渐增式编译和重载以缩短开发时间。特别值得一提,持续部署,可承诺立刻进入产品准备上线状态。在 Quora 用持续部署以前,这技术的好处曾经对我而言很难去内化,持续部署获得的好处对于提高重复步骤速度比起避免站台挂掉的风险还更有价值,至少以小型的工程团队是如此。人们对于功能增长了感到兴奋和有诱因去修复 bug ,由于变动很快的从实际的流量看到。相较于一周或数周建构一次,或是有更多的批次修改,持续部署也更明显而容易去推理并查明从有限的代码提交中找出错误的来源。编程
从团队的角度来看,快速的重复步骤速度也表明具备一群强而有力的领导者去帮助协调和推进团队的努力。关键项目利益相关者(stakeholders)在作一个需求决策,须要有效率地决定而且承诺他们的选择。借用Bill Walsh 的一句话,他是带领旧金山49人(译注 一个美式足球队)赢得 3 次超级杯的教练,优秀的领导者须要 “承诺(commit),引爆(explode)、回复(recover)”,这意味要承诺攻击计划,运行它,针对结果作出反应。(注1) 一个团队因犹豫不决而削弱其能力只会致使我的的努力举步维艰。缓存
Instagram 共同创办人 Mike Krieger 在他的技术演讲 “Scaling Instagram” 中,谈到 “为最小的操做负担作最佳化” 是他的13人开发团队在产品扩展到数千万用户时学到了关键的一课。(注2) 当产品成长时,每位工程师的操做负担也会增长,这能够用每多少用户须要多少工程师的比率来衡量或是多少功能须要多少工程师。例如,Facebook 以宣扬它的延展指针(scaling metrics)而闻名,像是每一位工程师支持超过100个万用户。(注3)服务器
自动化解决方案和将重复性任务脚本化(scripting)是很重要的,由于这件事释放出了工程团队的时间能够用在实际产品开发的工做上。若是服务器失效,确保它们尽量会自动从新启动,而且会在流量高峰时,简单并且快速地复制本身,这是在规模扩大时,惟一明智的方式去管理复杂度。以短时间眼光,老是会有诱惑宁肯采用快速匆忙拼凑的手动折衷方法,而不要用自动化和测试一个长期的修正。架构
Etsy 的座右铭–“度量任何事,度量一切” (注4) 这样的需求可使用开放原代码的监控与图表工具像是 graphite 和 statsd 来达成,这句话强调了自动化的一个重要面向–自动化必须被数据和监控所驱动。若是没有监控和日志去了解发生什么事、有些事情是如何出错、或是为何出错了,自动化变成是困难的一件事。一个好的遵循座右铭会是– “度量任何事,度量一切,尽量自动化一切”。框架
个人 MIT 教授和大学研究指导教师 Daniel Jackson 指出了良好的软件抽象层重要性 (注 5)
“选择对的抽象层设计, 编程将会从抽象层设计去天然地遵循, 模块将会有小而简单的接口 ; 不须要过分的从新组织代码,加入新的功能也很容易适应。然而选择错误的抽象层设计,编程将会出现一连串使人讨厌的意外 : 接口将会变成结构复杂并且笨拙的,程序员被迫去适应没法预期的交互做用, 甚至连最简单的变动都很难去进行。”
可让数千名Google 工程师能够建置可延展性的系统其中一部分缘由是 Google 拥有像是 Jeff Dean 和 Sanjay Ghemawat 这样真正聪明的工程师建构了像是 MapReduce, SSTable, Protocol Buffers 简单且多才多艺的抽象层,相同的,可让 Facebook 工程师去延展他们的系统其中一部分缘由是他们专一在类似的核心抽象层像是 Thrift,Scribe, 和 Hive。在 Quora 有一部分缘由可让设计师更有效率地建构产品是由于有建置在其上至关简单并且容易了解的 Webnode 和 Livenode 。
保持核心抽象简单并且通用减小了客制化解决方案的须要而且增长了团队的熟悉度与具有有共同抽象层的专门技术。逐渐普及和可靠的系统像是 Memcached, Redis, MongoDB, 等等已经减小须要自行建立客制化保存和缓存系统。宁肯让开发团队像漏斗状,灌注注意力在少数的核心抽象层也不要分散注意力在特定的解决方案。这也意味共用的程序库会更稳健,监控变得更聪明,性能特征获得更好的理解,测试取得更多的全面性。全部这一切都有助于一个能够下降营运负担的简单系统。
维护一个高品质的代码库,提升了整个工程团队的生产力。整洁的代码更容易理解,更快速去开发,更适应于变化,而且较不容易受 bug 交互影响。一个健康的代码审查流程让这一切成真。
建立及时的代码审查流程,不管是在 pre-commit 或是 post-commit 后,在几个方面提升了代码品质。首先,有人要审查你的代码的同侪压力和由于提交了设计不良的代码将会浪费同事的时间,这对于采用不当技巧的、没法维护的、未经测试的代码有吓阻的做用。其次,代码审查提供了代码审查者和做者交流的机会,彼此互相学习而写出更好的代码。
若是代码审查流程很容易被工程团队的其余成员容易接近使用,那么代码审查也顺便带来如下的好处 a) 增长对及时审查代码方式的责任感 b) 让团队成员–特别是新进的成员,从其余人好的代码审从中学习 c) 加快宣传最佳的编程实践。
反观,追求快速的开发团队没有把时间花费在代码审查,而忽略了很差的代码很容易累积技术债。Ooyala 在它很是早期公司刚开始的时候,习惯于最佳化尽量地实做出越多的功能越好,却疏于作代码审查, 最后形成告终果–虽然最初的产品能够很快地推向市场,可是产生的代码变得修改起来很痛苦, 咱们花了一年的时间也只是在改写脆弱的代码以消除技术债。
Google 在公司还很小的时候,对于全部的代码有作 pre-commit代码审查 但规模较小的团队并不须要那么全面或严格,并且全部代码不须要一样严格地审查。Ooyala,我在那里的时候 采用了 post-commit 方式经过电子邮件通知来审查核心或是高风险的代码变动。在 Quora,咱们透过 Phabricator进行的全部代码审查,大部分透过 post-commit 方式,模型( model )或控制器( controller )代码和视图( view )代码采用了不一样的标准; 敏感代码或重新进工程师产出的代码,咱们使用 pre-commit 作代码审查或是试着在提交代码前花几个小时内作审查。
同事之间的尊重造成了任何形式开放沟通的基础。一个让人们感到自在去互相挑战对方想法的地方,也是一个合理的概念会经由辩论而前进的地方。一我的们很容易被冒犯的地方,也是重要的回馈会被压抑的地方。
在 1948,Alex Osborn 介绍了知名的脑力激荡方法,这在过去的几十年工做环境中一直很受欢迎,参加者会聚在一块儿,抛开批评和负面回馈而且共同一块儿激荡出创造性的想法,不会有被批判的恐惧。(注 6) 这种形式的脑力激荡会议关键在它尊重任何潜在创意。最近的心理学研究已经开始推翻 Osborn 的作法,建议在脑力激荡会议鼓励辩论在实际上有助于避免群体思惟,并产生更有效的思路。在这项研究中点指出,抨击是针对概念想法而不是作人身攻击,这在一个彼此尊重的环境中变得更加关键。(注 7)
工程每每跨越普遍的领域(系统,机器学习,产品等)并且不是每一个人在每个领域都同有一样的专业知识。一个强大的团队里面应该有一些人对特定领域专精,即便他们跟别人相较之下有不足之处。这样有时候提及来有点复杂,例如让系统工程师来评估产品工程师的专长, 但去尊重这些差别性在一个健康的工程师文化是很重要的,并且并不能彻底根据本身的优点去评断。
当很天然地每一个人对于代码库不一样部分的代码或是架构变得逐渐精通,就没有人会以为他们是任何代码一部份的拥有者或是惟一的维护者。以短时间而言,当一我的拥有特定范围的代码一年会成为专家或是更能增长工做性能,可是这种作法最终从长远看对团队而言是伤害的。
在组织中,共享代码全部权提供了三个好处。首先,让巴士因子(bus factor 见注 8)大于一使维护者释放压力而且帮团队下降了风险若是维护者离职了。对于一我的在放假中还不用担忧工做是很困难的一件事。我确定不会想念我在 Ooyala 是惟一维护日志处理器开发者的那段日子,当我在夏威夷度假爬火山时,居然还会收到短信要求处理问题。
第二,共享代码全部权受权给那些没有深刻特定区域代码的工程师贡献新鲜的看法。让工程师免于屈就于特定项目的感受而且鼓励他们参与不同的项目,这有助于维持工做的乐趣,并提高员工学习意愿和动机。从长远来看,它下降组织有些工程师感到成长停滞而定离开的风险。
第三,共享代码全部权,必要时要更迅速地完成战略目标,让多个团队成员共同协做(swarma together: 来自敏捷开发的技术)一块儿解决高优先级的问题殿定了基础。孤立代码的全部权(译注 谷仓效应),责任一般落在一个或两我的身上。
一个错误发生在许多任务程组织单位–当团队还在很小的时候,太早切割成许多子团队并有各自的技术领导者。子团队打造的全部权这道墙,并减小了动机去越过那道墙。由于我的可能只会以子团队的目标来评估。当我还在 Ooyala 公司 时还有子团队,我错过了与其余团队其中一些人一块儿工做的机会。他们已经采用了敏捷开发流程而且有更大的重点放在共享的代码全部权,我据说已在工做幸福感和生产力上有巨大的进步。在 Quora 工做的初期,让我乐在其中的一个缘由是咱们超越团队来强调项目,因此我有机会参与项目从用户增加、机械学习、调节工具、 推荐机制、分析、网站速度和垃圾消息检测。
单元测试的覆盖率和必定程度的集成测试覆盖率是惟一能够延展的方法来管理由大型开发团队维护的较大的代码基底(codebase),不会常常破坏了建置(build)或是产品。自动化测试提供了信心和针对了要提升代码品质而作大规模的重构有意义的保护。缺乏了严格的自动化测试,须要由工程团队或外包测试团队作手动测试的时间是容易变成使人望而却步,并且很容易陷入一种恐惧去改善一段代码的文化,只是由于它有可能被破坏了什么。
在实务中,当团队成长时,自动化测试是让持续部署能够做业的需求。当产品成长时代码基底(codebase)的大小也随着时间成长,可是当新进工程师加入,团队成员对于代码基底(codebase)的平均熟悉度也随之降低。当代码在开发者的脑海里还记忆犹新的时候, 这时候测试和验证代码比较容易被原开发者来完成,相较于写完代码一个月后或是一年后再来修改。鼓励强大的单元测试的文化,将验证责任转移朝向原开发者。
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%的时间,这些事仍然是可能发生,可是对于工程师和设计师去尝试疯狂的概念是比较困难的。专一的人基本上必须利用周末的时间或是本身的假期来作这些尝试。
学习和充分的获得挑战是进入心理学教授 Mihaly Csikszentmihalyi 称之为“心流”状态(或是神驰状态)的需求,若是人进入这样的状态彻底集中精神和被他们正在作的事所驱动,他们甚至忘了去追踪时间。(注14) 经过快速的重复步骤(iteration)周期获得直接和快速的回馈循环(feedback loop)是进入“心流”状态的另外一种需求。
每周的技术讲座提供了论坛(forum)让工程师们分享他们的设计或是开发的做品,创造一个机会,让工程师以他们的工做感到骄傲和让团队学习到更多他们目前工做之外的技术。将内部流程文档化,像是 email 服务是如何运做的或是如何对搜索服务作排名变化,这也给予工程师权力本身主动去学习和探索新的技术,恰到好处跟 20 % 时间策略造成互补。在 Quora,咱们在内部有本身的 Quora 服务器,在上面咱们会问跟产品和开发相关的问题。
一个建立学习文化的必然结果是专一在师徒(mentoring)制和教育训练去确认每个人有基本的算法、系统和为了确保产品成功所具有的开发技能。随着工程组织成长更大要花更多功夫投入在招募上(特别是学院招募),也须要花更多力气投注在师徒制辅导和教育训练。对于一位独立的导师(mentor),天天花一个小时在一位刚到职4周内的新进工程师的工做上,这彷佛是一件沈重的工做,可是这个投入时间少于新进工程师一年内将会花费全部时间的 1% ,这有了很明显的杠杆做用在决定新进工程师是否成功融入团队。
招聘最好的人,是上述我所提出的许多点论述的基础。要去尊敬一位你认为对方是B级工程师的专业能力是很困难的一件事。若是你不信任某人的产品直觉(product instincts) ,让他们在产品开发上有自主权是很困难的。若是没有足够的软件工程经验,要去识别正确的抽象层来建立是很困难的。若是没有其余聪明的工程师去挑战你的概念和驱使你朝向简单化,很容易掉入建构一个复杂软件架构的陷阱。
在硅谷流传一个 Steve Jobs 创造的说法 “A 级玩家聘请 A 级玩家。B 级玩家聘请 C 级玩家”。(注15 16) 专一在招募而且聘雇对的人是困难的可是对于一个工程组织有效率地成长是很关键的。Yishan Wong ,他先前在 Facebook 担任工程经理和主管,主张招聘已成为你们在工程组织的首要任务,并不只仅针对管理者,还包含工程师。(注17) 他还准确地指出 “招聘最好的” 和 “招聘最好的候选者” 之间的区别。
Ooyala 的早期,咱们由于客户排入的工做而如此不堪重负,咱们几乎下降招聘的标准因此咱们能够聘雇足够的工程师来完成全部的工做。我很高兴咱们没有这样作,从较差品质代码和团队中的较弱工程师产生的技术债将不会中止伤害团队和产品。
建立一个良好的软件工程文化确定要花费不少的功夫,但由此产生的工做环境是很是值得的。
这篇博客文章源自于 Edmond 在 Quora 上的回答。
若是要找 Edmond 演讲关于软件工程文化相关主题的演讲能够跟他联系 。
Edmond 目前教导软件工程师和技术经理如何有效率的建立有意义的影响力。
他是 Quip 早期的软件工程师,曾经在 Quora、Google和 Ooyala 带领软件开发团队。