高效的面試方式:結對編程

  有一定職業編程經驗的人一定都知道,業界標準的面試模式大致如此:進入面試房間後,給你一個白色寫字板(國內用紙卷做題應該也很常見),讓你在上面寫出每個問題所對應的代碼。

  這樣的面試大家都會覺得不爽。在平時的工作環境中,你可以訪問API,或者通過搜索引擎來尋求你的答案。但面對一張白板/白紙,這些都不可能。白板上的問題一般不會涉及到太多整體設計方法,往往局限於簡單的演算法問題,所以僅憑這一套面試題很難測試求職者的所有技能。說實話,一般程序員寫字都很糟,讓他們在一個大的白板上直接寫代碼感覺好不了。

  我們喜歡編碼。我們喜歡坐在電腦旁,喜歡和同事一起探討自己的想法,並通過編譯器來驗證。白板面試僅能幫助面試官了解求職者的很少信息,但求職者不會從面試中學到任何東西。簡言之,這種標準的面試方式還有許多需要改進的地方。

  我所在的公司(譯註:指Rally軟體公司,5月底作者剛剛離開,加入了時代華納有線)正在嘗試另一種更高效的技術面試方式:結對編程。

  新方式主要是在傳統面試基礎上增加了一些環節。求職者通過電話篩選後,會與團隊中的兩個開發者進行一個小時的直接面試(採用白板模式),隨後會安排應聘者和其中一個開發者坐在一起,讓他們去共同完成一個任務。

  我已經嘗試用這樣的方式面試了一些應聘者,新增加的這些面試環節取得了很好的效果,所以我希望在此稍詳細的介紹一下這個面試過程,並分享一下它帶來的好處。

  具體怎麼做?

  我們有一個名為「pairing」的git遠程倉庫,它包含一個基於IntelliJ的項目框架。其中包含Java、Ruby和JavaScript模塊,面試者可以從我們常用的語言中選擇自己最熟悉的。

  每個模塊都有一個基本的項目結構。比如,Java模塊包含一個maven pom.xml文件,和「main」和「test」目錄。這個pom文件也包含常見的庫以方便應聘者編程。還有很多commons-lang工具包,以及 Google Guava、JUnit、TestNG、Mockito和很多常用的庫。

  每個模塊還有一個「README.txt」文件,它列出了一些練習。在Java模塊里有5個練習。求職者可以從中挑選一個自己最感興趣的項目。這些練習項目在結對編程的情況下大概需要花費兩個小時,難度級別一樣。同時,它們廣泛覆蓋了開發者所要解決的各種不同的問題。有一些涉及到大量的字元串和文本操作,另一些本質上則是純粹的數學問題。

  比如,其中的一個問題是寫一個程序來分析一組撲克牌,並選出它最好的組合牌型(順子、滿堂紅即三帶兩、對子等)。起初,我們計劃採用兩組撲克牌,並從中選出一組獲勝者,但考慮到這樣會使難點加大,為了與其餘4個項目難度相當,我們最後又做了一些簡化。

  我嚮應聘者解釋說,他們並不是必須要完成練習(這點很重要)。「我們的目標不是完成這個任務,而是讓彼此感受一下對方喜歡如何工作。」但很多面試者仍試圖能儘快完成該任務,每當我察覺到他們這麼做時,我就開始問一些關於代碼的值得思考的問題,以便他們能慢下來。一旦應聘者意識到他(她)已沒有機會完成這個任務時,他們就會慢下來,停止衝刺。

  當面試者寫了一些代碼後,我會尋問他們計劃如何測試代碼的準確性。一些人喜歡經常運行所寫代碼,一些人會寫一個「public static void main」方法來驗證所寫代碼是否實現了正確的功能,還有一些人會通過單元測試來驗證。無論他們如何回答,我都會建議他們繼續做下去,並確保到目前為止,所寫的代碼是正確的。這是一個很好的建議。因為在練習過程中最糟糕的事情就是,直到面試臨近結束時,他們才運行自己所寫的代碼,結果發現了一堆的Bug,在剩下的時間裡很難調試完。如果某個應聘者喜歡寫測試代碼,那我將和他(她)一起做乒乓結對編程(譯註:結對編程的一種,在結對編程引入測試驅動開發,兩個人輪流編寫測試,由對方編寫能通過測試的代碼,能有效提高代碼質量)。

  很多時候,面試者都會問一些諸如「如果輸入無效,我們應該怎麼做?」之類的問題。我通常會反過來問他們,他們打算怎麼做。在練習中,並沒有所謂的完全錯誤的答案。有時,他們會提出想用Google搜索一些東西或查閱一些文檔,可能有人會覺得有作弊之嫌。但我會說,對他們使用何用工具、資源沒有任何限制。並反覆強調說,他們應該像在平常工作中解決問題那樣來完成這個任務。

  在練習的最後20分鐘左右時,我喜歡讓面試者停止編碼,並和他們一起討論他們編寫的代碼。應聘者為什麼採用了某種設計,而沒選用另一種;他(她)是否還有其他想做的事等相關問題。我也會問他們,「如果我們計劃和其他工程師一起對這些代碼進行代碼審查,在審查之前,你計劃對這些代碼做些什麼?」通常在短短的兩個小時內,面試者很難按他們所設想的去重構代碼,所以我也希望了解,如果還有時間,他們將會從何入手。

  當然,他們離開後,這就是我要做的事。其他的一些開發者和我一起審查這些代碼,問我一些相關的問題,並就諸如代碼風格等問題展開討論。

  有哪些好處?

  上述面試過程所帶來的反饋效果是相當不錯的。首要的是,應聘者也很喜歡這種面試方式。相比在一個安靜的屋裡拿著白板筆苦思冥想,他們感覺在實際的電腦旁寫代碼更舒服。他們覺得這種面試方式比傳統面試方式更輕鬆(剛開始面試者的反應讓我都有些驚訝)。每個經歷過這種面試過程的應聘者都表示很喜歡,我們今後的面試都將按這種方法來進行。而且,這種面試不再是單方面的了:應聘者感覺面試就好像在工作一樣,雙方可以很好地對彼此進行評估。

  另外,相比普通面試,面試官通過上述面試過程,能更好地了解應聘者的「軟技能」。他的交際能力如何?他和同事一起思考、解決問題的過程是怎樣的?他喜歡協作,還是喜歡獨立工作?他是否喜歡開玩笑?通過這些編碼實踐中,我對這些問題都能找到了很好的答案。

  最重要的是,你實際上正在他們每天實際工作的環境中面試他們。因為開發者一般不會在白板上編碼,所以白板面試只能測試應聘者在做白板面試時的好壞程度。他們可以用編譯器或解釋器,他們可以用測試工具,他們可以Google搜索,在結對編程練習中他們可以用所有這些輔助工具,但在白板面試過程中,這些都是不允許的。在熟悉的工作環境中測試開發者可以算是評審他們的一種極其高效的方法。

  因為這種面試長達2個小時,並且只關注一個任務,所以更有機會了解面試者是如何進行編碼設計的,比起「請寫出一隻雞的對象模型」這種類型的設計問題來得更加實在些。不必要求應聘者畫出UML,你就可以了解他的設計能力如何,因為他們在現實工作中可能並不總畫UML圖。

  在主要的開發領域,採用上述面試過程是很重要的,不是呆在一旁的房間里,而是開始結對編程實踐。面試者有機會看到他們將工作的環境,並有助於他們對文化環境做出評價。如果你工作在一個嘈雜、非正式的辦公環境中,開發者可隨時播放音樂和彼此開玩笑,當應聘者真正參與到此環境中時,面試官可以看到他們是如何融入到環境中的。

  還有一點很重要,它感覺並不像是在面試。它並不是由面試官來拷問,然後面試者寫下所有代碼來回答。這並不是現實生活中結對編程的工作方式,所以在結對編程練習中,它也不應該是這樣的。面試官也應該寫一些代碼,以顯平等,面試者也會感覺更舒服些(應聘者當然要更多地負責解決問題的任務)。

  基於應聘者和面試官都喜歡這種面試過程,目前我很難有理由去進行白板面試。就我個人而言,在和應聘者進行結對編程練習之前,我甚至都不看應聘者的簡歷。在結對編程之前,我覺得沒有必要了解應聘者的任何事情,我喜歡在和他們完成任務的2個小時里去了解面試者的一切。

  如果你在招聘優秀程序員的過程中有困難的話,可以嘗試一下這個面試過程。把結對編程作為面試過程的一部分,看看效果如何。

    【討論】

  此文引起了熱議。有人提醒,在結對編程面試中不要讓面試者在生產代碼中開發,會涉及法律問題。

  還有人認為這種面試會耗費更多資源,很多公司未必能效仿。這種說法當然引起了很多人的炮轟,很顯然,這是典型的磨刀不誤砍柴工,招到一個優秀的新同事會事半功倍。而作者回答說,其實資源與原來的方式相同,因為他們公司之前是三輪面試,第一輪電話篩選,第二輪是兩個考官進行的白板面試(1小時),第三輪本來是另一組1小時的兩考官白板面試,現在換成了一考官2小時結對編程。

  還有人質疑,為什麼非要結對編程呢?給面試者一台電腦,一個任務,讓他編代碼去,然後再問問問題,不也行嗎?作者回答,通過結對編程,很逼近實際的合作場景,可以全面了解面試者,這是另一種方式無法做到的。

  更多討論可以訪問:Reddit


推薦閱讀:

軟體測試面試題 - 怎麼測電梯?(測杯子/椅子/雨傘/電話)
深度解析某頭條的一道面試題
面試中會出現的項目問題
職場面試中,求職者以退為進的四大法寶 提高面試成功率90%
明天面試能過關嗎?(一戊午年生人問)

TAG:編程 | 面試 | 方式 | 高效 | 結對編程 |