編者按:Facebook 的工程師有哪些高效工作的經(jīng)驗(yàn)?zāi)??軟件工程師訪談了多位 Facebook 的高產(chǎn)工程師,總結(jié)了他們的共同經(jīng)驗(yàn)以及晉級(jí)之路,供各位參考。
成為高效開(kāi)發(fā)者這件事你可以通過(guò)經(jīng)驗(yàn)、書(shū)本、或者試驗(yàn)和錯(cuò)誤來(lái)學(xué)習(xí)。但成為高效開(kāi)發(fā)者的最有效方式之一是直接向高效開(kāi)發(fā)者學(xué)習(xí)。我訪談了 Facebook 的幾位最高產(chǎn)的工程師,想找到這些開(kāi)發(fā)者實(shí)現(xiàn)最高生產(chǎn)力的基礎(chǔ)結(jié)構(gòu)是什么。
第一級(jí):減少不必要的干擾
這一點(diǎn)似乎很明顯,但是正是這些累積起來(lái)的小事情最影響我們的生產(chǎn)力。
避免開(kāi)會(huì)
我盡量少開(kāi)會(huì)。例會(huì)我一般都不參加。這條未必適合每一個(gè)人,因?yàn)榻?jīng)理喜歡安排例會(huì),你也不想把經(jīng)理給惹毛了,但我建議給他看看開(kāi)會(huì)的成本:(10 工程師 x30 分鐘)/ 周 +10 分鐘任務(wù)切換開(kāi)支=浪費(fèi)工程師半天時(shí)間 / 周,這可不是小數(shù)。我總是努力爭(zhēng)取用有議題的討論或者站立會(huì)議來(lái)代替例會(huì)
—匿名
許多工程師都強(qiáng)調(diào)必要的時(shí)候會(huì)議是有用的。但是必須對(duì)開(kāi)會(huì)保持批評(píng)性的眼光,不開(kāi)不必要的會(huì)。
準(zhǔn)備好做小任務(wù)
在生成或者修訂的時(shí)候我會(huì)迅速清理郵箱保持收件箱為 0— Michael Novati
有時(shí)候在你完成手頭任務(wù)之后到開(kāi)會(huì)之前會(huì)有 5 到 15 分鐘的間隔,或者你進(jìn)行的試運(yùn)行可能需要花費(fèi) 1、5 或 15 分鐘的時(shí)間。對(duì)此通常的反應(yīng)是 “這種時(shí)間里面做不了什么大事的。” 這種說(shuō)法當(dāng)然沒(méi)錯(cuò),許多任務(wù)可能都要花 30 分鐘到 1 小時(shí)的時(shí)間才能集中注意力,但并不是所有任務(wù)都這樣。許多工程師提到自己會(huì)做一份小任務(wù)清單,這樣在每天稍微閑暇的時(shí)間里就能把那些事情處理掉。比如處理郵件、diff(參見(jiàn)附注)評(píng)審,回復(fù)內(nèi)部帖子,或甚至可以進(jìn)行小規(guī)模的 diff/ 重構(gòu),從而提高一天的工作效率。
戴上噪音消除耳機(jī)
如果你在成立時(shí)間不久的軟件公司呆過(guò),你就會(huì)注意到那里的辦公區(qū)域設(shè)置是如何的空曠。對(duì)于工程師來(lái)說(shuō)這是一把雙刃劍。一方面你跟團(tuán)隊(duì)的距離可以更加靠近。團(tuán)隊(duì)成員間的協(xié)作和友情可以一直保持很高水平,問(wèn)問(wèn)題很方便,跟同事關(guān)系也可以很融洽。不好的是你寶貴的專(zhuān)注度被環(huán)境噪音干擾了。當(dāng)你正在思考棘手問(wèn)題的時(shí)候,聲音很大的討論會(huì)贏影響到你的生產(chǎn)力。這時(shí)候噪音消除耳機(jī)就可以派上用場(chǎng)了。這種耳機(jī)的技術(shù)已經(jīng)非常先進(jìn)了,遠(yuǎn)不止是在你的耳邊豎起一道屏障,調(diào)大耳機(jī)音量。真正的噪音消除耳機(jī)能夠排除環(huán)境噪音并且抑制周邊低沉的交談聲。跟 Michael Novati 談過(guò)以后我也買(mǎi)了一副他推薦的耳機(jī),說(shuō)實(shí)話(huà)要沒(méi)了它我都沒(méi)法干活了。很顯然,戴上這樣一副耳機(jī)進(jìn)行對(duì)比之后,你就會(huì)知道辦公室的環(huán)境噪音有多大。
在別人沒(méi)法干擾你的時(shí)候工作
(關(guān)于如何應(yīng)對(duì)干擾)2年 前搬到紐約去可能對(duì)我的幫助很大
—Adam Ernst
我通常把更困難更復(fù)雜的任務(wù)留到星期三(那時(shí)候我可以在家工作不受干擾)
—Bob Baldwin
實(shí)際上 “正常” 工作時(shí)間內(nèi)我干不了什么事情,只有靠加班時(shí)間才能完成事情
—匿名
我通常在早上 6 點(diǎn)到 9 點(diǎn)間能夠干的事情比一天其他時(shí)間能干的都要多,長(zhǎng)時(shí)間的不受打斷至關(guān)重要
—匿名
我得承認(rèn),跟這幫工程師聊的最大發(fā)現(xiàn)之一是他們當(dāng)中許多都工作很長(zhǎng)的時(shí)間。為什么他們要干那么久呢?原因挺有趣的。因?yàn)橹挥性谠缟稀⑸钜?、周末這些時(shí)間才沒(méi)人打擾他們。通過(guò)尋找一天當(dāng)中受打斷最小的時(shí)間,這些人得以推進(jìn)自己的重大任務(wù),把代碼給弄出來(lái)。
減少煩人的郵件 / 通知
我會(huì)關(guān)閉所有非緊急的郵件提醒。只接受需要行動(dòng)的郵件,并且強(qiáng)迫自己按照合理的頻率來(lái)檢查任務(wù) / 郵件頁(yè),把其他東西當(dāng)成垃圾郵件實(shí)際上對(duì)我是有幫助的,我錯(cuò)過(guò)的東西反而更少了。
— Ari Chivukula
每次收到新郵件時(shí)都要停下來(lái)去看看的話(huà),你一整天都會(huì)被各種干擾打斷了。通過(guò)減少和過(guò)濾通知到只保留必要的那些,你就能在不受干擾的情況下工作更久。
不要失去狀態(tài)
我被打斷(或者必須去洗澡)的時(shí)候會(huì)在腦中 “保存狀態(tài)”,就像在 Gameboy 模擬器中保存狀態(tài)一樣,這樣回頭繼續(xù)的時(shí)候我就可以盡快恢復(fù)了。
— Michael Novati
永遠(yuǎn)要在一項(xiàng)相當(dāng)簡(jiǎn)單或機(jī)械的任務(wù)中結(jié)束一天。這讓你第二天很容易就可以撿回來(lái)恢復(fù)工作狀態(tài),而不是又要從頭開(kāi)始。
—Adam Ernst
對(duì)于我來(lái)說(shuō),當(dāng)我在認(rèn)真思考問(wèn)題時(shí)、被打斷時(shí)、忘記自己在想什么時(shí)就會(huì)在編程方面會(huì)失去狀態(tài),也就意味著我需要重新把整個(gè)思考過(guò)程再過(guò)一遍。
當(dāng)你在工作狀態(tài)時(shí)遇到干擾最好的辦法之一是推遲干擾。如果你在全神貫注的時(shí)候被干擾,那就告訴那個(gè)人你稍后會(huì)處理,速記一下此事,然后繼續(xù)工作直到你到達(dá)合理的停止點(diǎn)。一旦到達(dá)停止點(diǎn),馬上處理完堆積的那些事情。
如果干擾無(wú)法推遲,也有很多辦法可以 “保持狀態(tài)”。比如寫(xiě)下自己當(dāng)前的思考過(guò)程,寫(xiě)下失敗測(cè)試,或者簡(jiǎn)化正在思考的問(wèn)題。
第二級(jí):寫(xiě)出 “更好” 的 Diff
好代碼意味著很多東西。好代碼應(yīng)該是功能性的,容易評(píng)審的,經(jīng)得起時(shí)間考驗(yàn)的,等等。
寫(xiě)更小的 Diff
許多小的 diff 就像是在解決工程問(wèn)題時(shí) “展示你的工作”
—匿名
我訪談的每一位工程師都非常強(qiáng)調(diào)把代碼變更拆分為邏輯模塊,這樣可以讓其他人更容易理解,更快接受。通過(guò)減少 diff 帶來(lái)的認(rèn)知負(fù)荷,評(píng)審者對(duì)于接受變更會(huì)更有信心。此外,通過(guò)減少 diff 的規(guī)模,變更對(duì)于評(píng)審者來(lái)說(shuō)也沒(méi)那么令人望而生畏,這樣評(píng)審效率也會(huì)更高。
可以告訴你們的是,這篇文章問(wèn)到的工程師都是過(guò)去 6 個(gè)月Facebook 里面提交 diff 最多的人??赡軙?huì)有兩種風(fēng)格的工程師群體,一群是提交很多小的 diff 的,一群是提交數(shù)量較少但規(guī)模較大的 diff。
堆疊 diff 以及多任務(wù)處理
大多數(shù)工程師提到自己會(huì)將 diff 變更相互堆疊起來(lái),逐步建立 diff 間的邏輯依賴(lài):
有時(shí)候當(dāng)我做了一個(gè)規(guī)模很大的 diff 時(shí),我會(huì)回過(guò)頭把它拆分成一系列邏輯步驟,這樣我就能慢慢變更一些東西,然后代碼的總體質(zhì)量也會(huì)逐步得到改善
—匿名
我從來(lái)不堆疊 diff,相反,我會(huì)并行做幾樣獨(dú)立的事情,然后在等待評(píng)審的時(shí)候交替處理。把一項(xiàng)大的變更分解成獨(dú)立部分這種做法也很有效,比方說(shuō)增加界面,增加端結(jié)點(diǎn),把這些事情安插進(jìn)待辦事宜里面……這樣可以把事情堆起來(lái)交替做,不用在 diff 之間產(chǎn)生嚴(yán)重依賴(lài)。對(duì)代碼進(jìn)行結(jié)構(gòu)化,這樣就不必堆疊或者弄子分支出來(lái),評(píng)審、交付、還原都容易一些。
—Michael Novati
如果我覺(jué)得自己在把多個(gè) diff 放進(jìn)一個(gè) diff 的話(huà),我會(huì)拿出來(lái)放到堆棧上形成相互依賴(lài)關(guān)系。
—匿名
要做小的,至少是容易評(píng)審的 diff。這不僅是為了更容易更快地審核,也能讓我寫(xiě)出更好的代碼,因?yàn)槲艺J(rèn)為如果每次處理的東西邏輯分明的話(huà),浪費(fèi)的調(diào)試時(shí)間就非常少了。此外對(duì)堆疊 diff 的經(jīng)驗(yàn)可以可以讓小的 diff 可管理。
—Ari Chivukula
我大量使用堆疊 diff。這么做除了讓我可以在等待代碼評(píng)審時(shí)有事可做以外,把代碼分解更更小的 diff 往往能讓我從宏觀上考慮自己在做什么,甚至還能簡(jiǎn)化架構(gòu)。
—匿名
無(wú)論工程師是使用堆疊 diff 還是進(jìn)行 diff 的多任務(wù)處理,其生產(chǎn)力似乎都相當(dāng)出色,這說(shuō)明這兩種辦法對(duì)提高效率都很有效。
單元測(cè)試
測(cè)試規(guī)模要盡可能小,這樣我會(huì)感覺(jué)舒服一點(diǎn)。
—Michael Novati
大家對(duì)經(jīng)過(guò)單元測(cè)試的代碼更容易接受些。
—匿名
單元測(cè)試這個(gè)東西在一些技術(shù)公司會(huì)引起爭(zhēng)議,大多數(shù)團(tuán)隊(duì)和公司對(duì)于工程師要不要寫(xiě)測(cè)試都有自己的指導(dǎo)意見(jiàn)。不過(guò)有一件事可以肯定,如果你所在的公司別人可以修改你寫(xiě)的代碼的話(huà),確保某人不會(huì)搞砸你的代碼的最好辦法是在測(cè)試中強(qiáng)制功能要求。
溝通
對(duì)于比較棘手的 diff,我會(huì)適當(dāng)增加幾個(gè)評(píng)審人,把 diff 共享到合適的群里面。不管有沒(méi)有動(dòng)作,我每天都會(huì) ping 一個(gè) diff 出來(lái)。如果好幾天都沒(méi)有動(dòng)作,我會(huì)問(wèn)評(píng)審的對(duì) diff 有什么驚人的發(fā)現(xiàn),然后對(duì)結(jié)構(gòu)做出改變。最后我會(huì)盡可能跟對(duì)方多溝通。我總是以 “[產(chǎn)品 / 標(biāo)簽]” 作為標(biāo)題開(kāi)頭—這樣大家就能知道 diff 是做什么的,如果我想盡快得到接受,我會(huì)寫(xiě)上 “[product-ASAP]” 或者 “[product-PUSHBLOCKER]” 之類(lèi)的東西。
— Michael Novati
這一點(diǎn)似乎顯而易見(jiàn),但是就 diff 評(píng)審進(jìn)行溝通的方式有很多種。一般的經(jīng)驗(yàn)法則是按 diff 來(lái)進(jìn)行。如果審核你的 diff 的人平時(shí)不怎么跟你打交道的話(huà),你可能要在描述和標(biāo)題上面增加一些平時(shí)跟團(tuán)隊(duì)成員溝通時(shí)不需要的上下文信息。你還可以在需要?jiǎng)e人重點(diǎn)審查的地方做批注,如果相關(guān)邏輯比較復(fù)雜的話(huà)。
在設(shè)計(jì)會(huì)議上就提出期望還可以簡(jiǎn)化寫(xiě)代碼的過(guò)程,開(kāi)發(fā)出好的 API 和架構(gòu)等。
不要害怕提醒評(píng)審者注意你的 diff。如果他們不想審核你的 diff,他們可以退出或者建議其他人來(lái)做。如果讓 diff 一直留著待審查隊(duì)列,那無(wú)異于給將來(lái)埋下沖突。
第三級(jí):具備團(tuán)隊(duì)精神
編碼是一項(xiàng)團(tuán)隊(duì)運(yùn)動(dòng),就像所有的團(tuán)隊(duì)運(yùn)動(dòng)一樣,個(gè)人能實(shí)現(xiàn)的事情總是有限的。
評(píng)審他人的代碼
快速掃描,通讀,打補(bǔ)丁,測(cè)試,評(píng)論
—匿名
多進(jìn)行評(píng)審以便提高你的代碼產(chǎn)量,這句話(huà)聽(tīng)起來(lái)似乎有點(diǎn)矛盾。我們可以把 “多做評(píng)審” 解讀為 “清理別人的隊(duì)列”。當(dāng)你換個(gè)角度看問(wèn)題時(shí),情況就清楚多了,如果你清理了其他工程師的隊(duì)列,那別的工程師也就更有可能幫你清理掉你的隊(duì)列,替你解鎖。
與評(píng)審者 / 團(tuán)隊(duì)成員建立信任
我有一個(gè)核心工程師小組,跟里面的人維系著良好的信任關(guān)系,我們會(huì)一起努力迅速評(píng)審對(duì)方的代碼。
—匿名
這一點(diǎn)跟上一點(diǎn)有點(diǎn)類(lèi)似。如果你有一組核心的工程師,相互能夠信任對(duì)方能寫(xiě)出好代碼的話(huà),你就可以相對(duì)安全地做出變更,因?yàn)槟呐履澄还こ處煂?xiě)錯(cuò)了東西,大家也會(huì)在出現(xiàn)問(wèn)題時(shí)一起努力改好它。
對(duì)自己在做什么要透明
進(jìn)行新項(xiàng)目(greenfield development)開(kāi)發(fā)時(shí)應(yīng)該用 RFC(請(qǐng)求評(píng)論)diff。相對(duì)于在后面才改變方向,預(yù)先獲取 /header/ 提議 API 反饋所消耗的時(shí)間是值得的。
— Adam Ernst
如果大家不知道你在做什么,因?yàn)樵u(píng)審 diff 時(shí)需要的信息量不足會(huì)導(dǎo)致他們困惑。通過(guò)盡早把評(píng)審者 / 團(tuán)隊(duì)成員納入圈子里面,他們就能在一大塊工作完成前提供反饋,前進(jìn)道路的路障也就被解除了。
提供好的反饋
專(zhuān)注于提供高質(zhì)量的反饋而不是挑刺。如果你發(fā)現(xiàn) bug 了就指出來(lái),但是要相信工程師已經(jīng)測(cè)試過(guò)(并且相信他們會(huì)改正任何發(fā)現(xiàn)的 bug)
—Bob Baldwin
先略讀了解概況,如果有什么地方不清楚就批注一下或者提出改進(jìn)建議。如果總體感覺(jué)良好,再細(xì)讀看看是否存在最佳實(shí)踐問(wèn)題或者小細(xì)節(jié)問(wèn)題,沒(méi)有的話(huà)留幾條注釋接受變更就行了。
— Ari Chivukula
“評(píng)審 diff 的策略是什么” 這個(gè)問(wèn)題的常見(jiàn)回應(yīng)是首先從高層視角理解待評(píng)審的 diff。在理解了 diff 的基本結(jié)構(gòu)之后,再深入了解代碼風(fēng)格并進(jìn)行邏輯檢查。
請(qǐng)求變更
要頻繁使用請(qǐng)求變更—最糟糕的事情莫過(guò)于他們重新請(qǐng)求評(píng)審(當(dāng)然要鼓勵(lì)作者這么做,如果對(duì)方認(rèn)為你的請(qǐng)求變更是錯(cuò)誤的話(huà))
— Adam Ernst
如果我可以看出自己的問(wèn)題,那就請(qǐng)求單元測(cè)試或者重構(gòu),這樣出問(wèn)題的可能性會(huì)低一點(diǎn)。如果東西太大太復(fù)雜而且顯然沒(méi)人把心思放在這上面,那就請(qǐng)求他們結(jié)束評(píng)審,或者至少給出將來(lái)更好做法的建議。
—匿名
在一些非標(biāo)準(zhǔn)事情上對(duì) diff 提出請(qǐng)求變更可能會(huì)有點(diǎn)令人尷尬。但是從長(zhǎng)遠(yuǎn)看,鼓勵(lì)采取更好的編碼做法和校驗(yàn)是值得的,工程師以后會(huì)從錯(cuò)誤中吸取教訓(xùn)并作出改進(jìn)中得到回報(bào)。
不知道要承認(rèn)
如果我對(duì)代碼庫(kù)的一部分不太清楚我會(huì)直接說(shuō)然后跳過(guò)。
— Michael Novati
不懂裝懂是裝不了多久的,如果要評(píng)審的東西你不懂就坦白告訴別人,然后讓對(duì)方去找別的更懂的工程師評(píng)審。
第四級(jí):組織與推進(jìn)
待辦事宜
我會(huì)把日程表里面的個(gè)人事務(wù)先放到一邊,設(shè)置提醒稍后再辦。如果日程安排里面不設(shè)提醒我會(huì)忘了。
— Michael Novati
大多數(shù)情況下,我問(wèn)到的工程師每個(gè)人都會(huì)使用不同的任務(wù)跟蹤工具。同時(shí)要跟蹤管理的來(lái)源還包括紙、任務(wù)、郵件、日程、清單、高級(jí)目標(biāo)等。不過(guò)在確定接下來(lái)該干什么,在對(duì)任務(wù)、郵件的組織和分類(lèi)方面,許多工程師都有一個(gè) “層次化” 機(jī)制。
快速失敗與迭代
我會(huì)盡量快速調(diào)整代碼,哪怕自己不能確定那是(獲得注釋的)最優(yōu)方案。對(duì)于想法的嘗試,我寧愿快速失敗而不愿先 100%考慮清楚
—Ari Chivukula
代碼嚇不倒我,我可以很容易進(jìn)入狀態(tài) ,兵來(lái)將擋水來(lái)土掩
— Michael Novati
許多工程師(包括我自己在內(nèi))可能會(huì)隱瞞的一點(diǎn)是害怕失敗。馬上就要做出完美產(chǎn)品的想法是可怕的,會(huì)導(dǎo)致我們考慮太多的問(wèn)題。要養(yǎng)成在不知道結(jié)果會(huì)怎樣的情況下馬上寫(xiě)代碼的習(xí)慣,這樣我們就可以更快地迭代,更快看到結(jié)果。
工作 / 生活平衡
有一位比你還要努力的<重要他者>是有幫助的,不然的話(huà)你就得自己扛了。我的做法是張弛有度,有時(shí)候我會(huì)沖刺一段時(shí)間然后放松一下。大概是高強(qiáng)度 2 個(gè)月然后放松 1 個(gè)月這樣子。在我看來(lái),這要比 3 個(gè)月保持相同節(jié)奏更高效(不過(guò)這一點(diǎn)并不適合每個(gè)人),因?yàn)楣ぷ鞑皇蔷€(xiàn)性的。
—匿名
“洗澡的時(shí)候考慮問(wèn)題” 這個(gè)比喻還是有點(diǎn)道理的
— Adam Ernst
這些工程師的確干活非常努力。為了完成大量的代碼他們花費(fèi)了很多的時(shí)間。盡管我沒(méi)有具體詢(xún)問(wèn)工作 / 生活平衡的問(wèn)題,但是他們當(dāng)中很多人工作、生活是分得很清楚的,哪怕是 “全力以赴” 的工程師,這點(diǎn)挺讓我驚訝的。看起來(lái)這些人不僅可以高效工作,而且工作 / 生活平衡也能做得很好—如果愿意的話(huà)。
零星想法
你希望別人怎樣待你,你就該怎樣去對(duì)待別人。你得成為別人希望共事的那種工程師,而這大部分是通過(guò)反饋來(lái)了解的。要早點(diǎn)問(wèn),經(jīng)常問(wèn),被問(wèn)到的人會(huì)感覺(jué)自己受重視。
— Ari Chivukula
經(jīng)過(guò)這些訪談后,我感覺(jué)自己的開(kāi)發(fā)進(jìn)程正在一點(diǎn)一點(diǎn)地發(fā)生演變(同事要很努力才能引起我的注意,因?yàn)槲椰F(xiàn)在戴上去噪音耳機(jī)了)。拆分 diff,請(qǐng)求評(píng)審,待辦事宜清單,這些東西我之前也做,但現(xiàn)在我知道如何更有效地利用這些工具了。說(shuō)實(shí)話(huà),采取了上面的做法之后,我的效率提高了不少。
附注:
1、Diff:Facebook 工程師所謂的 diff 是指用開(kāi)源工具 phabricator 創(chuàng)建的代碼修訂(differentialrevision)。這些修訂是放進(jìn) phabricator 供其他工程師評(píng)審的代碼改動(dòng)。工程師可以評(píng)論、請(qǐng)求變更或者接受代碼變更,之后再轉(zhuǎn)給產(chǎn)品影響實(shí)際用戶(hù)。Facebook 編寫(xiě)的每一條代碼都要經(jīng)過(guò)這一驗(yàn)證步驟,確保工程師之間的不斷協(xié)作以及相互反饋。
2、堆疊 Diffs:是指 diff 的堆疊,上層 diff 邏輯依賴(lài)于下層 diff,其功能是基于所有下層 diff 的功能基礎(chǔ)之上開(kāi)發(fā)的。這使得工程師可以在方便評(píng)審的簡(jiǎn)單小規(guī)模的變更基礎(chǔ)上開(kāi)發(fā)功能,循序漸進(jìn)實(shí)現(xiàn)更大的目標(biāo)。