@程式設計師,拒絕無聊的程式碼面試!
要判斷一個人是不是優秀的程式員,不一定非要看他的程式碼。

過去十多年裡,我面試了許多工程師。在那段時間裡,我總結了一系列的方法,可以在不看程式碼的情況下快速準確地評價一名開發人員。
而我現在認為,這些方法不僅可行,而且客觀上比程式碼面試更好。
什麼是“程式碼面試”?
“程式碼面試”指所有直接測試候選人的技能,或審查他們編寫的程式碼或虛擬碼的方法。這些方法包括:
審查程式碼片段,或GitHub的個人頁面;
程式設計測試(Codility等);
程式設計挑戰,或在個人時間裡自由完成的題目;
現場程式設計,或結對程式設計;
在白板上實現演算法。
說到這裡,也給大家推薦一個架構交流學習群:835544715,裡面會分享一些資深架構師錄製的視訊錄影:有Spring,MyBatis,Netty原始碼分析,高併發、高效能、分散式、微服務架構的原理,JVM效能優化這些成為架構師必備的知識體系。還能領取免費的學習資源,相信對於已經工作和遇到技術瓶頸的碼友,在這個群裡會有你需要的內容。
程式碼面試的目的
這些方法的出現絕非偶然,而是為了取代那些更差的面試手段,比如:
腦筋急轉彎:一架波音747中能裝多少個網球?
咬文嚼字:Java中介面和子類的區別是什麼?
白板程式設計:至少在這些中不是最差的......
發現式測試:“怎樣檢測連結串列中是否存在環?”
我們認為,這一切都是非常愚蠢的面試手段,因為它們無法反映軟體開發者在日常工作中所需的技能。因此,我們在面試過程中,試圖通過程式碼面試重現日常的工作。
然而問題在於:這種方法也根本不管用。因為真相是: 程式碼面試根本不能重現真實的工作 。當然,程式碼面試能讓候選人展示工作所需的部分技能——但程式碼面試的環境和真正的工作環境完全不同。
程式碼面試的問題
程式碼面試能減少候選人的數量,但也能拒絕真正優秀的候選人,還能對差的候選人做出虛假的判斷。
程式碼測試會佔用面試者和候選人雙方大量的時間。如果能產生效果,也許前者還可以接受,但後者會導致很難在買方市場上尋找到好的工程師。
由於隨時更新程式碼測試題很困難,結果就導致面試體驗很差。如果候選人對現有的工作滿意,那麼他們根本不會做你的程式碼測試題。這些題目也會增加面試的時間,從而延長整個僱傭過程。但這一切都不能增加候選人的數量。
更重要的是,程式碼面試並不能很好地模擬真實工作。
Google的研究發現,優秀的團隊都擁有一項特質,叫做“心理安全”(https://rework.withgoogle.com/blog/five-keys-to-a-successful-google-team/)。只有當團隊的所有人都願意承擔風險、願意身處弱勢時,團隊才能達到最佳狀態。
這跟程式碼面試完全不一樣。候選人通常會感到焦躁、感到壓力,擔心一個小錯誤就會丟失這份工作。因此你沒辦法獲得候選人的最佳狀態。
更糟糕的是,這些題目會刷掉那些沒有太多自由時間的候選人。通過這些題目只會讓你篩選出那些有空閒時間的人。因此你的候選人會更年輕、更沒有經驗。你還會錯過一些其他人,如未婚父母或需要照顧家中病人的人。
有更好的辦法嗎?
雖說忠言逆耳,但是你必須去和你的候選人談話。你需要去了解他們,需要和他們對話。也許這很難,但從整體來看這種方法更容易。
作為面試官你必須提高技術力。
面試技巧:前提條件
程式碼面試是空中樓閣,看起來很美好,唯一的缺點是無法篩選出好的候選人。你需要思考什麼樣的技術力和品質對你的團隊最有價值,而程式碼面試只不過是你偷懶的藉口而已。
招聘很難,想做好招聘可能需要掌握一系列的技巧。但是,有些技巧可以立即提升你的面試水平:
事先規定你需要的候選人的特徵,該規定需要做到具體、詳細;
詢問候選人一系列固定的問題;
在面試之後、徵求他人意見之前,記下所有面試的反饋;
練習,練習,再練習。
不需要程式碼的方法
不需要寫程式碼就能衡量候選人的方法可能有一萬種。我常用的三個主要方法可以覆蓋許多不同的技能。在面試過程中,我們會談論候選人的經驗,要求他們做一些程式碼審查,並與別人合作設計一個系統。
下面我會詳細解釋這個過程。
我試圖通過這些方法找到真正能夠勝任技術工作的候選人,並且他們必須能在單純的程式設計技能之外給團隊帶來價值。通常在一次面試中我能在大約一個小時內覆蓋所有三個部分。我有信心這些資訊能讓我找到好的候選人。
深入挖掘他們的經驗
許多團隊已經這樣做了。他們會在面試一開始花幾分鐘,詢問候選人之前的工作,他們對工作的態度,等等。大多時候這就像隨意談話一樣。
但這是不對的。
記住這是面試。你需要儘可能地理解他們構建系統時使用的技術。
為了做好這一點,你需要在面試開始之前仔細閱讀他們的簡歷。這不是開玩笑,在面試開始之前至少花上10分鐘仔細閱讀(不是略讀)簡歷,如果花30分鐘時間則最好。要從簡歷中儘可能多瞭解些他們之前的專案,Google一下看看能否找到他們專案的公開資訊。面試時挖掘背景資訊所花的時間越少,就越能獲得好的效果。
在面試中,要求候選人談談他最近最感興趣的專案。要練習主動的傾聽,要學會參與。假裝你是他團隊中的一員,或者假裝你們是在做架構審查。你要努力瞭解他們構建的東西以及構建的方法。這樣做的好處和壞處是什麼?要讓候選人知道,不知道答案無所謂,但重要的是能勾起你的好奇心。
下面是我認為能獲得好的答案的問題:
你在專案中的職責是什麼?這個問題本身並不是決定性的。即使在專案中承擔的職責很小,他們也可能很適合你們的團隊。你的候選人也許正是因為沒能獲得重要的職責而在尋找新的機會。因此,知道他們過去的職責會很有幫助。
你從他人那裡獲得了什麼幫助?無法感受他人的幫助是個極其危險的訊號。即使是個人專案,也一定需要別人的幫忙。你肯定不想要一個以自我為中心的同事。
給我介紹下那個功能的工作原理。解釋下資料的來源和去向、儲存方式以及這一切能帶給終端使用者的好處。這個問題的答案足以吸引你的好奇心。
這個專案中最糟糕的技術債務是什麼?好的工程師必須理解他們做出決定時需要付出的代價。問完這個問題,可以繼續詢問他們怎樣改正這些問題,或者尚未改正的理由。
有沒有出過生產環境下的bug或服務中斷?測試下他們是否理解bug的原因,以及團隊解決bug的方法。他們是否提前預期到了bug?下次怎樣才能避免同樣的問題發生?
這一部分面試能讓你直接瞭解候選人的經驗。做好這一部分還能讓你瞭解他們如何感謝別人或責備別人。你將會了解到他們如何在兩難的工程問題上做出抉擇,他們會與你分享最近的教訓,他們與別人溝通技術的能力應該也很明顯。
如果他們選擇了不太適合的專案,可以考慮談論其他專案。所謂不太適合的意思是專案不夠複雜或他們記不清的情況。
注意,這一步要避免詢問類似於“告訴我你解決過的最難的bug”之類的問題。要求別人回憶系統的某一部分的具體原理會帶來大量的虛假負面判斷。人們不可能擁有他們修復的bug相關的一切知識,這種問題會給面試過程帶來很大壓力。
讓他們審查你們的程式碼
這項活動一半是程式碼審查一半是角色扮演。你可以藉此篩選出那些能夠提升團隊整體程式碼質量並促進辦公室氛圍的人。
下面是程式碼審查過程中需要關注的一些方面:
他們怎樣與程式碼的“作者”交流?交流是否有用?是否高效?是否友善?
他們會著重哪些問題?是否能明確表達出他們的疑問?他們是否會立即指出哪些無關緊要的問題?
他們是否善於閱讀自己不熟悉的程式碼?
這個方法需要提前準備很多東西。你需要找到或編寫一段程式碼供候選人審查。你還需要為你希望候選人找出的問題建立一個優先順序列表。不要讓面試管當場出題,一定要事先準備好。
在選擇需要審查的程式碼時,不要選擇產品程式碼。你的候選人沒有你所擁有的背景知識,這樣做實際上是將候選人與你的同事比較,而不是與其他候選人比較。
努力降低程式碼示例中的複雜度。面試的時候,候選人沒有太多時間閱讀程式碼,而且很可能他們並沒有想到會做程式碼審查。熱身就要花很長時間。
在程式碼中加入一兩個真實的bug,但不要強調找bug。一般來說,程式碼審查並不是個好的找bug方法,特別是審查者從來沒有見過程式碼的情況下。能自證的bug(如給需要陣列的函式傳遞字串)最好。在你的優先順序列表中,bug的優先順序應該是最低的,bug應該是給極其優秀的人的加分項。
最後,程式碼應該做一些實際的事情。如果你的公司很出名,那可以選擇你的產品簡化版本。但如果你需要花大量時間為候選人提供背景資訊的話還是算了。
最好的選擇要麼是虛構的程式碼(也許可以選擇本文竭力避免的程式碼面試中用到的程式碼),要麼是開原始碼中的一個拉取請求。
一旦決定了要審查的程式碼,你應該期待候選人找出下面這些東西:
過於糟糕的拉取請求的描述或提交資訊;
能用但無法自洽的程式碼;
過於複雜的程式碼(需要重構的程式碼);
混亂的變數或方法名;
過度設計的程式碼(即實際上永遠不會用到的功能)。
如果程式碼中沒有足夠的問題,就多加一些。
這裡有個潛在的問題,我還沒有確定的答案。這個問題是:你是否應該提前將程式碼發給候選人?
如果你這樣做,就又給那些有空閒時間的人以巨大的優勢。如果不這樣做,就要面臨增加面試壓力的風險。
我傾向於後者。好的面試官可以減輕壓力,方法之一就是讓面試者提前知道他們將做程式碼審查,你也可以在審查開始之前介紹你的期望。
共同設計系統
作為面試官,你最重要的任務之一就是判斷候選人是否能完成要求他們完成的技術工作。好的評價方法應當儘可能避免虛假的正面和負面判斷,同時在更廣泛的技術水平範圍內區分候選人。
即使是新手也應當能針對問題取得一些進展。最高階的候選人應當能快速找出他們無法立即解決的問題。
這種方法我從大學時代就開始使用,後來在業界用了二十多年。這種方法非常有效。
這種方法是什麼?
協同設計系統的意思是與你的候選人共同設計一個工具、平臺或專案。不需要寫程式碼或虛擬碼,只需要討論系統的設計思路和做出的取捨,還要提出這些取捨可能帶來的問題,以及解決問題的方案。
這種方法之所以有效,是因為新手工程師和高階工程師之間的主要區別就是他們能預見到的問題的數量。憑藉經驗可以造就更強壯的系統設計,也能隨時解決新問題。
怎樣使用這種方法?
首先你的團隊需要選擇一個希望候選人“構建”的專案(所有候選人應當使用同一個專案。長時間這樣做,面試官就能做出更好的評價),自己做一次練習並計時。面試時要讓候選人知道系統設計大概要花多少時間,並告訴他們不可能完成所有設計。他們應當提前瞭解預期的產出。
花上幾分鐘解釋基本的需求。如果需求無法用幾句話解釋清楚,那可能不是個好專案。例如,你的專案可以是構建一個與某個著名的社交媒體平臺相似的東西,比如你無需解釋Instragram的工作原理。
事先提供一切你認為價值不大的東西。然後詢問候選人他們希望首先構建的部分。然後繼續討論新功能,直到時間用完。
如果候選人很容易就完成了這一切,那麼可以提高複雜度。如果他們表現得很困難,就降低複雜度。
專案的難度可變,這樣就能深入瞭解候選人的技能水平。就像是對候選人水平做二分查詢一樣!
選一個專案
這項活動的關鍵就是需求必須易於理解。如果你公司的產品很出名,可以利用它做為起點。否則,選一個知名的網站(如Facebook)。專案應當與候選人入職後要做的工作相關。拿我們來說,我們有兩個專案,一個用於後端招聘,一個用於前端招聘。
後端專案的主要關注點是流行社交網路的底層系統。前端專案會提供一些簡化了的產品功能截圖,並詢問候選人如何構建(元件怎麼定義、元件間互動用什麼方法等)。
示例:構建Facebook
首先,我們會介紹任務。告訴候選人我們要構建一個類似於Facebook的網站。我們假設現在這個網站包含了使用者、認證和一些其他功能。
此時,我會詢問候選人怎樣才能構建最小功能的Facebook。我們喜歡這個問題,因為這個問題能看出候選人怎樣考慮產品上的需求,也可以給之後的決策和取捨的討論提供基礎。
此時,我會使用白板記錄下他們的想法。這樣能使我參與其中,保證我之後能理解他們的設計。如果我理解錯了,他們會立即注意到並糾正。
候選人可能會告訴我,最小功能集合包含好友、狀態更新、新聞源,以及點讚的功能。問問他們挑選這個功能列表時的原則。是否漏掉了什麼明顯的功能?是否包含了不必要的功能?他們的思考過程比功能列表本身更重要。然後,問問他們打算先做哪個。假設候選人決定先做“好友”功能。
候選人會有不同的想法。一些候選人可能會提出不可行工作的方案,但不應該剝奪他們的機會。最優秀的候選人應該能很快就完成這個階段。
我們假設候選人告訴我,他要建一個表來儲存好友關係。這個表應該包含好友關係的發起人和接收者。
然後繼續挖掘。在Facebook中的好友關係是雙向的。怎樣才能在資料庫中表示?這種表示方法對系統設計有什麼影響?
選擇之一就是不需要做任何特別處理。查詢給定使用者的好友時用兩列同時查詢。另一個選擇是在好友資料庫中儲存兩份資料,每個資料表示一個方向。如果這樣做,那麼刪除好友時要同時刪掉兩條資料。討論兩者的取捨。
下個話題可能是如何處理好友請求。他們可能會選擇在“好友”一欄新增一個“接受”按鈕。他們可能會建立新的表儲存好友請求。接下來可以討論黑名單和垃圾請求等話題。
此時好友的話題基本上說完了,可以繼續討論下一個功能。隨著新的功能不斷加入系統,討論各個功能之間的互動是件很有意思的事情。
假如候選人無話可說也沒關係!你可以提出一種解決方案,問問他們的想法。這種方案的優缺點是什麼?要是他們還是不理解,可以試著討論其他的功能。
這項活動中我最喜歡的地方就是它很有意思。如果面試官表現很好,候選人也積極參與,那麼最終整個面試過程可能不怎麼像面試,而更像是一次與同事間就新專案進行的談話。
而這正是候選人即將擔任的角色。完美。
什麼時候應該用程式碼面試?
儘管我很不喜歡程式碼面試,但有時候也有用:
確定入門級程式設計師是否能夠程式設計;
如果你的公司強制進行結對程式設計,那麼在面試中進行結對程式設計可以當做是以後工作的預演;
一個角色需要許多特定的程式設計技能,而你沒有太多時間去教他們,當你在兩個高階職位名稱之間猶豫不定時尤為如此;
從程式碼面試到無程式碼面試的轉變過程中不要突然轉變,給自己一段轉變的時間,可以幫你建立無程式碼面試的技能。
最後,如果團隊的面試技能欠缺,就需要利用程式碼面試。程式碼面試的效果不太好,而且也有許多缺點。但是,它非常容易實施。即使是沒有經驗的面試官也可以很好地處理程式碼面試。
如果你正是這樣的人,那麼培養自己的面試能力應該是最優先的——僱傭錯誤的人是最昂貴的錯誤。
結論
只要一點點練習,你的團隊就能在這種無程式碼面試中做得很好。他們能在較短的時間內做出更好的僱傭決策,而且面試也能招來更多的候選人。
我希望這篇文章對你有幫助。如果有問題,請在評論區留言。希望你能在下一次面試中幹掉程式碼面試!
想要學習Java高架構、分散式架構、高可擴充套件、高效能、高併發、效能優化、Spring boot、Redis、ActiveMQ、Nginx、Mycat、Netty、Jvm大型分散式專案實戰學習架構師視訊免費獲取 架構群:835544715
ofollow,noindex">點選連結加入群聊【JAVA高階架構】:https://jq.qq.com/?_wv=1027&k=5dbERkY