Facebook 工程师是如何高效工作的?

发表于2016-03-10
评论0 1.3k浏览


  编者按:Facebook 的工程师有哪些高效工作的经验呢?软件工程师访谈了多位 Facebook 的高产工程师,总结了他们的共同经验以及晋级之路,供各位参考。
  成为高效开发者这件事你可以通过经验、书本、或者试验和错误来学习。但成为高效开发者的最有效方式之一是直接向高效开发者学习。我访谈了 Facebook 的几位最高产的工程师,想找到这些开发者实现最高生产力的基础结构是什么。

第一级:减少不必要的干扰
  这一点似乎很明显,但是正是这些累积起来的小事情最影响我们的生产力。
1、避免开会
尽量少开会。例会我一般都不参加。这条未必适合每一个人,因为经理喜欢安排例会,你也不想把经理给惹毛了,但我建议给他看看开会的成本:(10 工程师 x30 分钟)/ 周 +10 分钟任务切换开支=浪费工程师半天时间 / 周,这可不是小数。我总是努力争取用有议题的讨论或者站立会议来代替例会。—匿名
许多工程师都强调必要的时候会议是有用的。但是必须对开会保持批评性的眼光,不开不必要的会。
2、准备好做小任务
  在生成或者修订的时候我会迅速清理邮箱保持收件箱为 0— Michael Novati
  有时候在你完成手头任务之后到开会之前会有 5 到 15 分钟的间隔,或者你进行的试运行可能需要花费 1、5 或 15 分钟的时间。对此通常的反应是 “这种时间里面做不了什么大事的。” 这种说法当然没错,许多任务可能都要花 30 分钟到 1 小时的时间才能集中注意力,但并不是所有任务都这样。许多工程师提到自己会做一份小任务清单,这样在每天稍微闲暇的时间里就能把那些事情处理掉。比如处理邮件、diff(参见附注)评审,回复内部帖子,或甚至可以进行小规模的 diff/ 重构,从而提高一天的工作效率。
3、戴上噪音消除耳机
  如果你在成立时间不久的软件公司呆过,你就会注意到那里的办公区域设置是如何的空旷。对于工程师来说这是一把双刃剑。一方面你跟团队的距离可以更加靠近。团队成员间的协作和友情可以一直保持很高水平,问问题很方便,跟同事关系也可以很融洽。不好的是你宝贵的专注度被环境噪音干扰了。当你正在思考棘手问题的时候,声音很大的讨论会赢影响到你的生产力。这时候噪音消除耳机就可以派上用场了。这种耳机的技术已经非常先进了,远不止是在你的耳边竖起一道屏障,调大耳机音量。真正的噪音消除耳机能够排除环境噪音并且抑制周边低沉的交谈声。跟 Michael Novati 谈过以后我也买了一副他推荐的耳机,说实话要没了它我都没法干活了。很显然,戴上这样一副耳机进行对比之后,你就会知道办公室的环境噪音有多大。
4、在别人没法干扰你的时候工作
(关于如何应对干扰)2年 前搬到纽约去可能对我的帮助很大。—Adam Ernst
我通常把更困难更复杂的任务留到星期三(那时候我可以在家工作不受干扰)—Bob Baldwin
实际上 “正常” 工作时间内我干不了什么事情,只有靠加班时间才能完成事情。—匿名
我通常在早上 6 点到 9 点间能够干的事情比一天其他时间能干的都要多,长时间的不受打断至关重要。—匿名
  我得承认,跟这帮工程师聊的最大发现之一是他们当中许多都工作很长的时间。为什么他们要干那么久呢?原因挺有趣的。因为只有在早上、深夜、周末这些时间才没人打扰他们。通过寻找一天当中受打断最小的时间,这些人得以推进自己的重大任务,把代码给弄出来。
5、减少烦人的邮件 / 通知
我会关闭所有非紧急的邮件提醒。只接受需要行动的邮件,并且强迫自己按照合理的频率来检查任务 / 邮件页,把其他东西当成垃圾邮件实际上对我是有帮助的,我错过的东西反而更少了。— Ari Chivukula
  每次收到新邮件时都要停下来去看看的话,你一整天都会被各种干扰打断了。通过减少和过滤通知到只保留必要的那些,你就能在不受干扰的情况下工作更久。
6、不要失去状态
我被打断(或者必须去洗澡)的时候会在脑中 “保存状态”,就像在 Gameboy 模拟器中保存状态一样,这样回头继续的时候我就可以尽快恢复了。— Michael Novati
永远要在一项相当简单或机械的任务中结束一天。这让你第二天很容易就可以捡回来恢复工作状态,而不是又要从头开始。—Adam Ernst
  对于我来说,当我在认真思考问题时、被打断时、忘记自己在想什么时就会在编程方面会失去状态,也就意味着我需要重新把整个思考过程再过一遍。
  当你在工作状态时遇到干扰最好的办法之一是推迟干扰。如果你在全神贯注的时候被干扰,那就告诉那个人你稍后会处理,速记一下此事,然后继续工作直到你到达合理的停止点。一旦到达停止点,马上处理完堆积的那些事情。
  如果干扰无法推迟,也有很多办法可以 “保持状态”。比如写下自己当前的思考过程,写下失败测试,或者简化正在思考的问题。

第二级:写出 “更好” 的 Diff
  好代码意味着很多东西。好代码应该是功能性的,容易评审的,经得起时间考验的,等等。
1、写更小的 Diff
许多小的 diff 就像是在解决工程问题时 “展示你的工作”—匿名
  我访谈的每一位工程师都非常强调把代码变更拆分为逻辑模块,这样可以让其他人更容易理解,更快接受。通过减少 diff 带来的认知负荷,评审者对于接受变更会更有信心。此外,通过减少 diff 的规模,变更对于评审者来说也没那么令人望而生畏,这样评审效率也会更高。
  可以告诉你们的是,这篇文章问到的工程师都是过去 6 个月Facebook 里面提交 diff 最多的人。可能会有两种风格的工程师群体,一群是提交很多小的 diff 的,一群是提交数量较少但规模较大的 diff。
2、堆叠 diff 以及多任务处理
  大多数工程师提到自己会将 diff 变更相互堆叠起来,逐步建立 diff 间的逻辑依赖:
有时候当我做了一个规模很大的 diff 时,我会回过头把它拆分成一系列逻辑步骤,这样我就能慢慢变更一些东西,然后代码的总体质量也会逐步得到改善。—匿名
我从来不堆叠 diff,相反,我会并行做几样独立的事情,然后在等待评审的时候交替处理。把一项大的变更分解成独立部分这种做法也很有效,比方说增加界面,增加端结点,把这些事情安插进待办事宜里面……这样可以把事情堆起来交替做,不用在 diff 之间产生严重依赖。对代码进行结构化,这样就不必堆叠或者弄子分支出来,评审、交付、还原都容易一些。—Michael Novati
如果我觉得自己在把多个 diff 放进一个 diff 的话,我会拿出来放到堆栈上形成相互依赖关系。—匿名
要做小的,至少是容易评审的 diff。这不仅是为了更容易更快地审核,也能让我写出更好的代码,因为我认为如果每次处理的东西逻辑分明的话,浪费的调试时间就非常少了。此外对堆叠 diff 的经验可以可以让小的 diff 可管理。—Ari Chivukula
  我大量使用堆叠 diff。这么做除了让我可以在等待代码评审时有事可做以外,把代码分解更更小的 diff 往往能让我从宏观上考虑自己在做什么,甚至还能简化架构。—匿名
  无论工程师是使用堆叠 diff 还是进行 diff 的多任务处理,其生产力似乎都相当出色,这说明这两种办法对提高效率都很有效。
3、单元测试
测试规模要尽可能小,这样我会感觉舒服一点。—Michael Novati
大家对经过单元测试的代码更容易接受些。—匿名
  单元测试这个东西在一些技术公司会引起争议,大多数团队和公司对于工程师要不要写测试都有自己的指导意见。不过有一件事可以肯定,如果你所在的公司别人可以修改你写的代码的话,确保某人不会搞砸你的代码的最好办法是在测试中强制功能要求。
4、沟通
对于比较棘手的 diff,我会适当增加几个评审人,把 diff 共享到合适的群里面。不管有没有动作,我每天都会 ping 一个 diff 出来。如果好几天都没有动作,我会问评审的对 diff 有什么惊人的发现,然后对结构做出改变。最后我会尽可能跟对方多沟通。我总是以 “[产品 / 标签]” 作为标题开头—这样大家就能知道 diff 是做什么的,如果我想尽快得到接受,我会写上 “[product-ASAP]” 或者 “[product-PUSHBLOCKER]” 之类的东西。— Michael Novati
  这一点似乎显而易见,但是就 diff 评审进行沟通的方式有很多种。一般的经验法则是按 diff 来进行。如果审核你的 diff 的人平时不怎么跟你打交道的话,你可能要在描述和标题上面增加一些平时跟团队成员沟通时不需要的上下文信息。你还可以在需要别人重点审查的地方做批注,如果相关逻辑比较复杂的话。
  在设计会议上就提出期望还可以简化写代码的过程,开发出好的 API 和架构等。
  不要害怕提醒评审者注意你的 diff。如果他们不想审核你的 diff,他们可以退出或者建议其他人来做。如果让 diff 一直留着待审查队列,那无异于给将来埋下冲突。

第三级:具备团队精神
  编码是一项团队运动,就像所有的团队运动一样,个人能实现的事情总是有限的。
1、评审他人的代码
快速扫描,通读,打补丁,测试,评论。—匿名
  多进行评审以便提高你的代码产量,这句话听起来似乎有点矛盾。我们可以把 “多做评审” 解读为 “清理别人的队列”。当你换个角度看问题时,情况就清楚多了,如果你清理了其他工程师的队列,那别的工程师也就更有可能帮你清理掉你的队列,替你解锁。
2、与评审者 / 团队成员建立信任
我有一个核心工程师小组,跟里面的人维系着良好的信任关系,我们会一起努力迅速评审对方的代码。—匿名
  这一点跟上一点有点类似。如果你有一组核心的工程师,相互能够信任对方能写出好代码的话,你就可以相对安全地做出变更,因为哪怕某位工程师写错了东西,大家也会在出现问题时一起努力改好它。
3、对自己在做什么要透明
进行新项目(greenfield development)开发时应该用 RFC(请求评论)diff。相对于在后面才改变方向,预先获取 /header/ 提议 API 反馈所消耗的时间是值得的。— Adam Ernst
  如果大家不知道你在做什么,因为评审 diff 时需要的信息量不足会导致他们困惑。通过尽早把评审者 / 团队成员纳入圈子里面,他们就能在一大块工作完成前提供反馈,前进道路的路障也就被解除了。
4、提供好的反馈
专注于提供高质量的反馈而不是挑刺。如果你发现 bug 了就指出来,但是要相信工程师已经测试过(并且相信他们会改正任何发现的 bug)—Bob Baldwin
先略读了解概况,如果有什么地方不清楚就批注一下或者提出改进建议。如果总体感觉良好,再细读看看是否存在最佳实践问题或者小细节问题,没有的话留几条注释接受变更就行了。— Ari Chivukula
  “评审 diff 的策略是什么” 这个问题的常见回应是首先从高层视角理解待评审的 diff。在理解了 diff 的基本结构之后,再深入了解代码风格并进行逻辑检查。
5、请求变更
要频繁使用请求变更—最糟糕的事情莫过于他们重新请求评审(当然要鼓励作者这么做,如果对方认为你的请求变更是错误的话)— Adam Ernst
如果我可以看出自己的问题,那就请求单元测试或者重构,这样出问题的可能性会低一点。如果东西太大太复杂而且显然没人把心思放在这上面,那就请求他们结束评审,或者至少给出将来更好做法的建议。—匿名
  在一些非标准事情上对 diff 提出请求变更可能会有点令人尴尬。但是从长远看,鼓励采取更好的编码做法和校验是值得的,工程师以后会从错误中吸取教训并作出改进中得到回报。
6、不知道要承认
如果我对代码库的一部分不太清楚我会直接说然后跳过。— Michael Novati
  不懂装懂是装不了多久的,如果要评审的东西你不懂就坦白告诉别人,然后让对方去找别的更懂的工程师评审。

第四级:组织与推进
1、待办事宜
我会把日程表里面的个人事务先放到一边,设置提醒稍后再办。如果日程安排里面不设提醒我会忘了。— Michael Novati
  大多数情况下,我问到的工程师每个人都会使用不同的任务跟踪工具。同时要跟踪管理的来源还包括纸、任务、邮件、日程、清单、高级目标等。不过在确定接下来该干什么,在对任务、邮件的组织和分类方面,许多工程师都有一个 “层次化” 机制。
2、快速失败与迭代
我会尽量快速调整代码,哪怕自己不能确定那是(获得注释的)最优方案。对于想法的尝试,我宁愿快速失败而不愿先 100%考虑清楚。—Ari Chivukula
代码吓不倒我,我可以很容易进入状态 ,兵来将挡水来土掩。— Michael Novati
  许多工程师(包括我自己在内)可能会隐瞒的一点是害怕失败。马上就要做出完美产品的想法是可怕的,会导致我们考虑太多的问题。要养成在不知道结果会怎样的情况下马上写代码的习惯,这样我们就可以更快地迭代,更快看到结果。
3、工作 / 生活平衡
有一位比你还要努力的<重要他者>是有帮助的,不然的话你就得自己扛了。我的做法是张弛有度,有时候我会冲刺一段时间然后放松一下。大概是高强度 2 个月然后放松 1 个月这样子。在我看来,这要比 3 个月保持相同节奏更高效(不过这一点并不适合每个人),因为工作不是线性的。—匿名
“洗澡的时候考虑问题” 这个比喻还是有点道理的。— Adam Ernst
  这些工程师的确干活非常努力。为了完成大量的代码他们花费了很多的时间。尽管我没有具体询问工作 / 生活平衡的问题,但是他们当中很多人工作、生活是分得很清楚的,哪怕是 “全力以赴” 的工程师,这点挺让我惊讶的。看起来这些人不仅可以高效工作,而且工作 / 生活平衡也能做得很好—如果愿意的话。
4、零星想法
你希望别人怎样待你,你就该怎样去对待别人。你得成为别人希望共事的那种工程师,而这大部分是通过反馈来了解的。要早点问,经常问,被问到的人会感觉自己受重视。— Ari Chivukula
  经过这些访谈后,我感觉自己的开发进程正在一点一点地发生演变(同事要很努力才能引起我的注意,因为我现在戴上去噪音耳机了)。拆分 diff,请求评审,待办事宜清单,这些东西我之前也做,但现在我知道如何更有效地利用这些工具了。说实话,采取了上面的做法之后,我的效率提高了不少。

附注
1、Diff:Facebook 工程师所谓的 diff 是指用开源工具 phabricator 创建的代码修订(differentialrevision)。这些修订是放进 phabricator 供其他工程师评审的代码改动。工程师可以评论、请求变更或者接受代码变更,之后再转给产品影响实际用户。Facebook 编写的每一条代码都要经过这一验证步骤,确保工程师之间的不断协作以及相互反馈。
2、堆叠 Diffs:是指 diff 的堆叠,上层 diff 逻辑依赖于下层 diff,其功能是基于所有下层 diff 的功能基础之上开发的。这使得工程师可以在方便评审的简单小规模的变更基础上开发功能,循序渐进实现更大的目标。

  加入GAD的核心用户QQ群:484290331,各类活动奖励任你拿,最新资讯任你读,众多教学任你免费学,如此好地方赶紧加入吧!另VR专属群:476511561,专业VR技术分享,专业导师指导为你答疑解惑,大型小型活动奖励等你拿,免费学习赚奖励的天地,欢迎你加入哟!

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引