7個你需要知道的結對禮儀

結對編程遠遠不是兩個程序員坐在一起寫代碼那麼簡單。 — 魯迅(沒有說過)

7個你需要知道的結對禮儀

結對編程

結對編程可能算是比測試驅動開發更具有爭議的敏捷實踐了,事實上,僅有很少的團隊可以很好的實施它並從中受益,對於更多的團隊來說,即使在踐行敏捷的團隊中,也常常會分為旗幟鮮明的兩個陣營。提倡者往往會強調結對編程在“傳遞領域知識”,“減少潛在缺陷”,“降低信息孤島的形成”等方面的作用;而反對者則認為結對編程在很多時候都是在浪費時間:開發者在實踐中很多時候都難以聚焦,容易產生分歧,另外個人的產出往往也難以度量。

這篇文章不打算討論結對編程對效率的影響,也不討論要不要進行結對編程,當然也不會涉及以何種力度來執行結對。這裡的假設是團隊決定採用結對編程,但是對於如何實施存在一些疑慮;或者已經在採用結對編程的團隊裡,發現很多時候結對編程並沒有很好的發揮作用,需要一些更有實踐意義的指導。

結對編程遠遠不是兩個開發者坐在一起寫代碼那麼簡單。作為一種科學且充滿趣味性(才不是)的工程實踐,事實上它是有一些基本原則的,團隊裡的開發者需要正確的實施這些原則,結對編程才有可能為團隊帶來實際的受益。

7個你需要知道的結對禮儀

假設你找到了另一個程序員,並且已經準備好一起來編碼實現一個具體的業務需求。在開始著手開始結對之前,你首先需要setup環境。

硬件設置

工欲善其事,必先利其器。首先你和你的peer需要一個大的外接顯示器和有一個可以調節高度的桌子(當然也可以用紙箱子DIY一個低配版)。這一點往往被初學者忽視,而事實上它可以直接決定結對能不能作為一個可持續的團隊工程實踐。如果你的頸椎長時間處於不舒服的狀態,你的注意力很快會退散,精神會變得難以集中,而一個處於病態的身體是無法支撐長時間的編碼工作的。

在開始之前,請將屏幕調整到舒適的高度,以不仰頭不低頭為度(身高不一樣的兩個人可以通過調整椅子的高度達到基本一致)。此外還要注意看屏幕的角度,如果你需要抻著脖子才能看清楚屏幕,那麼當時間稍長一點時,你的頸椎也會非常吃力。因此,如果條件允許的話,你和你的peer可以使用雙屏來進行結對。

當然,還有一些常見的其他關於硬件準備的細節,比如:

  • VGA/HDMI轉接頭
  • 充足的電源
  • 鍵盤/鼠標轉接頭
  • 便籤和筆

紙和筆永遠是你(們)的好朋友,在實際動手寫代碼之前,請拿出紙筆來將要做的事情劃分成更細粒度,可以驗證的任務列表,貼在顯示器的下邊緣。最後,另外記得將手機調成震動模式,利人利己。

7個你需要知道的結對禮儀

軟件設置

硬件準備好之後就可以進行軟件的配置了。軟件問題遠比硬件複雜,因為大部分開發者都有自己鍾愛的工具集,小到curl/wget,大到Vim/Emacs,不要期望在這個問題上和peer達成一致,這是可遇而不可求,可望而不可即的。

根據我自己的經驗而言,高級一些的IDE比如JetBrains出品的Intellij,WebStorm等都可以隨意切換快捷鍵集合(keymap)。如果你和peer就快捷鍵的使用上無法達成一致,在輪到你輸入代碼的時候,你可以切換到自己熟悉的Keymap,反之亦然。

在Intellij/WebStorm裡,你可以通過ctrl+`來切換各種設置,比如選擇3就可以切換不同的Keymap,然後在下一步的窗口中按照自己的喜好進行切換預設的Keymap。某項目的王曉峰(Vim黨)和張哲(Emacs黨)尤其擅長此技,他們兩人結對時,可以做到在搶鍵盤的瞬間將keymap切換到自己的摯愛而對方無察覺的地步。

7個你需要知道的結對禮儀

這種技法事實上僅僅對於結對雙方都有很高超的鍵盤操作能力的前提下,也唯有這種場景下,雙發可以互不妥協。對於另一種場景(可能在實際中更為常見),比如結對一方鍵盤技巧和操作效率低下,影響結對流暢程度的場景,則需要效率低下的一方自己摒棄陋習(使用鼠標而不是鍵盤),快速趕上。

和別人結對之前,你需要至少熟悉一個IDE/編輯器,比如通過純鍵盤的操作完成

  • 按照名稱查文件
  • 按照內容搜索
  • 定位到指定文件的指定行/指定函數
  • 選中變量,表達式,語句等
  • 可以快速執行測試(可以在命令行,也可以在IDE中)

熟常基本Shell技能和常用命令行工具的使用,可以完成諸如

  • 文件搜索
  • 網絡訪問
  • 正則表達式的應用
  • 查找替換文件中的內容

等操作,這樣在結對時可以大大提高效率。這些都是稍加練習就可以掌握的技能,並沒有多少技術含量在內,而且學會了可以收益很久。

當知識不對等時

好了,鋪墊了這麼多,終於到了正題部分。最理想的結對狀態是,雙方的技能水平相當,知識儲備基本類似,可以非常流暢的進行交流,在結對過程中可以完全專注在需要解決的問題本身上,討論時思想激烈碰撞,編碼時鍵動如飛,不知日之將夕。這種場景下完全不需要任何技巧,隨心所欲,自由發揮即可。與此對應的另一種場景是雙方都沒有任何儲備,技能也無法勝任,這種情況我們需要在項目上完全避免。

這兩種極端的情況之外,就是不對等的場景了,這也是現實中最為常見的case:很多時候,結對雙方會有一個人比較有經驗,而另一個人則在某方面需要catchup。比如一個老手帶一個新手,或者一個擅長業務的開發和另一個該領域的新人結對等。

一般而言,需要雙方有一個人來做主導,另一個人來觀察,並在過程中交互,答疑解惑,共同完成任務。與傳統的教與學不同的是:結對需要的是兩個智慧頭腦的碰撞,而不是單方面的灌輸。因此觀察者不是單方向的被動接受,主導者也並非完全講述。事實上結對是一個會有激烈交互的過程。

主導者

對於主導者來說,千萬不要太投入,而無視peer的感受。這種場景非常常見,我自己有時候也會不自覺的忽略掉peer,自顧自的寫代碼,很多時候把peer當成了小黃鴨。這時候你的peer會有強烈的挫敗感,也很難跟上你的節奏,從而影響結對的效果。作為主導者,需要更耐心一些,不斷的和自己的peer交互。

7個你需要知道的結對禮儀

另一個極端是,主導者太熱心的coach,而忽視了給新人實際鍛鍊的機會。這時候需要主導者給peer更多的實踐機會:比如在帶著新人編寫了一個小的TDD循環(紅綠重構)之後,可以抑制住自己接著寫的衝動(我知道這個非常困難),然後將鍵盤交給你的peer,讓他模仿你剛才的做法來完成下一個。

有時候,當你看到peer正在用一個不好的做法來完成任務時,你可以即使讓他停下來,並通過問問題的方式來啟發他:

  • 還有更好的做法嗎?

如果peer仍然在遲疑的話,你可以進一步提示:

  • 你覺得XXX會不會更好?

一個實際的例子是,你們在寫一段JS代碼來迭代一個列表,你的peer正在用for循環來操作一個數組,而你可以提議使用Array.map。有些時候,你的peer會給你一些驚喜的回答!他的回答甚至比你預想中的更加出色,你也可以通過這種方式來向他學習。

觀察者

另一方面,作為觀察者而言,結對毋庸置疑是一種特別好的學習機會,你應該抓住一切可能的機會來向你的peer學習。包括快捷鍵的使用,命令行工具參數的應用,良好的編程習慣等等。保持你的專注力和好奇心,比如你看到peer神器的通過快捷鍵刪除了花括號(block)中的所有代碼,或者將curl的返回值以prettify過的樣式打印到控制檯,或者通過命令行merge了一個PR等等。

在實踐的時候,可以採取Ping-Pong的方式來互換主導者和觀察者的角色。比如,A寫一個測試,B來寫實現,A來重構,然後換B來寫測試,A來實現,B來做重構等等。開始時,可能會由一個人來主導,隨著合作越來越順暢,你們可以提高交換的頻次。

保持專注

在選定了要兩人一起解決的問題之後,你們需要一起完成任務劃分。這樣可以確保你們可以永遠關注在單一任務上,避免任務切換帶來的損耗。

在做完一項任務後,用mark筆輕輕將其從紙上劃掉(或者打鉤)。千萬不要小看這個小動作的威力,它既可以將你們的工作進度很好的表述出來,也可以在任何時候幫助你們回到正在做的事情上(特別是在吃完午飯之後),另外這個微小的具有儀式感的動作是對大腦的一個正向反饋,促進多巴胺的分泌(代碼寫的這麼開心,還要什麼女朋友?)。

7個你需要知道的結對禮儀

很多時候,我們需要暫時擱置爭議,保持前行。

無法統一的意見

如果你遇到了一個固執己見的同事,而不湊巧的是你也是一個難以被說服的人,那麼如何處理那些無法避免的爭論呢?特別是那些沒有對錯之分的技術問題。比如那種編程語言更適合Web開發,比如如何踐行TDD(比如自頂向下的TDD和自底向上的TDD)等等。

有時候,我們會非常堅持自己覺得對的東西,覺得那就是真理。挑戰這個真理的不是傻就是二,但是用不了多久,我們就會發現,換個角度好像也說得通,特別是在和其他人結對,並突然意識到以前的那個完全無法接受的做法似乎還是有幾分道理的。

在我剛做完的一個前端項目中,做技術選型時我自然的選了更早項目中使用的scss module,而團隊裡的另一個同事則提議使用styled-component。我們誰也沒有說服誰,最後寫代碼的時候就有兩種風格。直到有一天,我在代碼庫裡看到了用styled-component寫的很漂亮的組件,我自己嘗試著把相關的scss重寫成styled-componet,結果發現確實比單獨的scss文件要更好維護一些,而且也不影響既有的測試。

我突然意識到,我所堅持的只是一個假的“真理”,先前的堅持和做技術選型時的理由就變得很可笑:那隻不過是為了使用自己熟悉的技術而編造的理由而已。保持open mind是一件知易行難的事情,希望大家在爭辯時能念及這個小例子,可能會少一些無謂的爭辯。

對於這種難以統一意見的場景,我建議可以將其擱置,先按照某一種提議進行,知道發現明顯的,難以為繼的缺陷為止。往往你們會發現一條比較折中的路,或者一個人被另一個人說服。

7個你需要知道的結對禮儀

棘手的任務

即使很有經驗的程序員也會遇到新的領域,或者在熟悉的領域遇到新的困難。有些情況下,作為結對的兩個人都對要完成的主題沒有頭緒。這時候非要擠在一起反而會降低速度,無助於問題的解決。

一個好用的實踐是,兩人分頭研究,並嚴格控制時間。比如Time box 30分鐘。不過很可能在30分鐘後,你們中至少有一個人已經對要怎麼做有了頭緒,如果30分鐘還沒有頭緒,則可以求助團隊其他成員。

比如我在最近項目上遇到了Kerberos認證的問題,我和peer都沒有接觸過,在經過20分鐘的獨立spike之後,我發現了一篇細節很豐富的,看起來很靠譜的技術博客,而我的peer則在內部github上找到了另一個團隊的可以工作的代碼(雖然代碼質量不是很好)。我們最終決定copy+paste,然後做重構的方式繼續前進。而那篇技術博客則是一個很好的課後學習的資料。

張弛有度

注意力是一種非常稀缺的資源,普通人很難全神貫注在某件事情上超過30分鐘。一旦超過這個時間,大腦就開始偷懶,開小差。這時候一個短暫的break可以讓大腦得到很好的休息。人類的大腦有一個非常有趣的特性,就是它的後臺任務處理能力 — 而且後臺處理能力好像遠遠強大於前臺。你可能會在去衝咖啡的路上,突然靈光一閃,那個困擾你多時的問題有了思路,而此時此刻的你的大腦明明在想如何用咖啡機衝一份拿鐵。

如果遇到一個難以理解的bug,或者在設置測試環境是遇到了困難,休息一下很可能幫助你找到解決問題的新角度。為了避免長時間糾纏在冥思苦想中,你和你的peer可以採取比如番茄工作法之類的時間管理工具:

  1. 從Todo列表中找出下一個任務
  2. 設置一個不可中斷的25分鐘,開始工作
  3. 時間到了之後,休息5分鐘
  4. 重複2-3,4次之後休息15分鐘

這裡有一個在線工具可以直接使用 ,你也可以用手機的鬧鈴工具。

7個你需要知道的結對禮儀

結對輪換

如果結對的對象長期固定的話,pair本身又會變成新的信息孤島。比如A和B長期負責訂單模塊,而C和D則一直在寫門店管理,那麼毫無疑問,一段時間後,A和B就不知道C和D在做什麼了,不論是領域知識還是技術實踐,都很難得到有效的知識傳遞。當一個團隊規模變成10+之後,這還可能演化成更為嚴重的項目問題。

因此需要定期或者不定期的輪轉,比如一週輪換一到兩次,A和C來寫訂單,B和D來寫門店管理,這樣可以保證領域知識,工程實踐,工具的使用等等知識都很好的在團隊內部共享。

在一些場景下,團隊採取前後端分離的方式進行開發。前端和後端的技術棧選擇大相徑庭,每一端都有不同的約定和複雜的配置,這會對結對輪換的實施造成障礙,而且短期來看還會影響開發效率。如果團隊再大一些,DevOps可能會獨立出一個小組來負責,這將導致結對的輪換更加困難。

在實踐中,我發現讓不同角色的團隊成員輪換結對所帶來的好處(伴隨著短期陣痛的)遠勝過知識的隔離帶來的壞處。團隊中的前端開發如果花費一些時間和DevOps一起結對,他會對系統的整個架構更加清楚;而後端開發和DevOps結對則可能讓他意識到代碼中的潛在缺陷和解決方法(比如會話外置,緩存策略等)。

尊重

作為一個最小單位的團體活動,你常常要站在你的peer的角度來看問題。如果你不願意和某一特性的人結對,那麼首先不要讓自己成為那樣的人。比如你討厭只悶頭寫代碼,不理會peer有沒有跟上的那種結對方式;又或者你不喜歡和用鼠標完成又低效又彆扭操作的人一起寫代碼(我在和這樣的人結對的時候,都需要費很大力氣抑制自己,才不會從peer的手中把鼠標搶過來扔掉),那麼首先讓自己不是那樣的人。

除此之外,尊重還體現在很多其他細節中。當你不得不中斷結對而去做其他事情時,務必讓你的peer知道。而且在離開之前,你應該表示歉意,不要憑空消失,然後若干分鐘後又憑空出現,沒有人喜歡和一個不靠譜的人工作。比如10點30分的水果時間到了,你看到有人拿著你喜歡吃的桃子從廚房方向走了回來。你可以示意peer暫停一會,然後去廚房拿點水果,記得給你的peer也帶上一些。

另一方面,當你的peer回來之後,你需要及時和他catchup,告訴他你正在做什麼,已經做到了哪一步等等。快速的將他帶入到上下文中。

控制情緒

情緒是一件非常微妙的事情,它具有很強的傳染性。當你們的工作任務收到各種blocker,被各種其他事情干擾而導致進度難以推進時,一定要注意自己情緒的控制。如果你的peer一直在旁邊唉聲嘆氣,或者抱怨連連,你會變得非常沮喪,並且很難集中精力在積極解決問題上。

你可以通過積極的尋求外部幫助,或者將blocker更快的可視化出來,讓團隊瞭解,並提供可能的幫助。

課後練習

和你的peer完成了充實而卓有成效的一天之後,你需要總結一下自己記錄的知識點,這是一個絕佳的提升自己能力的方法。通過實戰,發現自己的缺點,並通過近距離觀察別人如何解決該問題,最終會以很深刻的印象記錄下來,這時候針對性的查漏補缺是可以取得非常好的效果。

比如你已經習慣使用grep來做搜索,結果你的peer嫻熟的awk技巧使你打開眼界,你可以在課後專門學習一下這個工具的各種選項,並嘗試熟練應用。或者你們在代碼庫中探索到webpack的一些特殊配置,它可以良好工作,但是你不是很明白背後的原理,這些都可以放在結對結束之後自己消化。花一些額外時間來更新你的技能可以讓你在第二天的結對中更加得心應手,也可以更好的融入到結對編程帶來的快樂中。

這些結對的基本禮儀,都是一些微小的細節,做好了可以讓和你一起工作的人比較舒服,也會幫助你自己建立一個更加高效的工作環境。

小結

在這篇文章中,我總結了一些有關結對編程的常見的問題和解決方法。在開始進行結對之前,首先需要確保硬件設施正確setup,這樣可以保證大家可以在很輕鬆舒適的環境中工作。在軟件設置上,保證效率的前提下,可以有不同的偏好設置。當能力不對等時,恰恰是結對編程最能發揮作用的場景,不但對於觀察者來說是絕好的學習過程,對於主導者而言,也可以從coach過程中看到一些不同的東西。

在結對編程過程中,你們需要始終保持專注,可以通過任務拆分的方式來幫助一直關注在單一事項上。此外,應該有定期的休息,讓緊張的情緒得到緩解。為了避免大尺度上的信息孤島,團隊還需要定期的進行Pair的輪換。

總而言之,通過這些方法的使用,可以有效的促進工作效率,促進個人成長為前提,並和可以形成很好的團隊氛圍。


原文:https://insights.thoughtworks.cn/seven-skills-about-pair-programming/


分享到:


相關文章: