每日最新頭條.有趣資訊

程序員最愛吐槽的現場編程面試,真的一無是處嗎?

作者 | Mike Hearn

編譯 | 楊志昂

編輯 | Linda

不久前,InfoQ 官網一篇 《華為面試改革:增加 90 分鐘網上編程 30 分鐘當面編程環節,充分考察實際動手編程能力》 的文章,受到很多程序員的關注。對於程序員來說,現場編程測試可能是考核編程能力的最好方法,但是如果用人部門沒有考慮清楚考核題目和考核標準,可能彼此都會浪費時間。今天這篇文章,是一位有著豐富招聘經驗的作者,給出的他在現場編程面試程序員時候的一些經驗,當然他也澄清了幾個被求職者吐槽的問題。

Reddit上的編程分類內容 有大約 200 萬用戶,其中大多數帖子只有很少的評論,熱門一點兒的話題一般也就 100 到 200 條評論。但是如果你在上邊搜索“面試”這樣的關鍵詞,你看到的熱門帖子數可是超越想象。

許多開發人員對編程面試都感觸頗深。上面所有的帖子都在哀歎:如今的趨勢是將現場編程測試當成獲得軟體工作的必要條件了。但卻從來沒有一個人為這種編程面試做出一番辯護。

在今天的文章中,我想做的是:

為編程測試提出充分理由。

列舉一些最好避免的常見做法。

解釋為什麽面試總是涉及毫無意義的算法謎題,而不是“真正的”編程。

我寫這篇文章的原因,是因為在我的職業生涯中,我有過 300 多次面試別人的經歷,並且設計了我當前雇主所使用的面試流程。我所雇傭的團隊每天都要進行開發人員面試。一個好的招聘流程是有價值的,本文不是關於如何設計一個完整成熟流程的教程,只是提到了一些求職者在合理情況下非常討厭的事情,對於聰明的雇主來說,會盡量去避免做這些事情。

首先說說我們如何在 R3 招聘。R3 為了建造一個 受比特幣啟發的分布式開源數據庫,我們正在世界各地招募技術人員。開發人員的面試過程一般包括以下內容:首先,閱讀一段代碼,要求面試者在大約 5 分鐘的時間內,快速地發回對代碼的評審意見;其次,是一個 30 - 60 分鐘時長的視頻聊天 + 共享螢幕面試,面試者可以從家中接入,在編輯器中進行編程,可以自選熟悉的編程語言,只要編程語言足夠主流,面試官就能讀懂;最後,邀請面試者到辦公室與團隊和高管進行面談。

根據候選人的個人特質和具體的工作角色,編程測試有時還包括設計部分和“談話”式問題,因為面試者的工作不僅僅只是編程。我們發現,這樣的一個面試流程其實還是很科學的;而且,至少與其他一些招聘流程相比,這個流程還是相當輕量化的。

面試官應該避免什麽

既然這樣,讓我們從盡量避免的面試風格開始談起。

我不推薦某些公司采取以下做法:

“機器人面試”與自動化評估。沒有人喜歡做面試官,所以你的團隊經常會要你看是否能把面試工作外包出去。我們曾經對這種機器面試有一段非常短暫的體驗,卻發現其結果與人為主導的評估結果並不相符。更重要的是,邀請應聘者參加面試是對佔用他們寶貴時間提出的禮貌要求,如果我們要求某人免費為公司奉獻時間,而公司不做出對等的奉獻,這是很不禮貌的。面試官花一個小時和你通電話,表明他們和重視自己的時間一樣重視你的時間。用一個冷冰冰的 web APP 來實現自動化的“作業”會帶來截然不同的結果。尤其是高級工程師,他們一定會拒絕接受這種面試。

白板面試。雖然很多年前這種做法是可以理解的,但現在筆電電腦和螢幕共享無處不在,編寫程序最自然的方法當然是使用編輯器、鍵盤、搜索引擎和編譯器這些工具來輔助面試者。另外,視頻電話面試允許應聘者在家裡用自己熟悉的電腦和工具編程,這比讓一個人站在一個小會議室裡,用一支粗胖的馬克筆在白板上寫代碼要好得多。

面試一整天。許多公司都希望對開發人員進行一整天的面試,這通常需要 5 到 8 次的單獨面試。這使得那些已經有工作的開發人員很難參加一整套面試,而這些人可能正是你最想雇傭的。如果先進行遠程面試,然後利用午休時間進行一些回訪,可以讓求職者避免請假,這意味著他們更有可能完成整個面試過程。我個人發現:8 次較之 2 次面試反饋而言,並不能顯著提高團隊的招聘質量。

大規模的“作業”。雖然我們最近開始要求應聘者面試前做一個簡單的的任務,但這個任務不需要編寫任何代碼,而且可以在幾分鐘內就完成。我聽說有些公司要求應聘者在面試時間之外編寫完整的、真實的程序。同樣,這也是對面試者時間的不尊重,許多人會明確地提出拒絕。

慌忙中隨意編造問題。問題設計並不容易,你希望候選人事先做好準備對吧?所以作為面試官,你也應該提前做好充分的準備。

修複一個真正的 bug 或實現一個真正的功能。這樣做除了會帶來明顯的版權問題之外,這也並不是一個保證面試過程可重複執行的好辦法,也並沒有辦法確保你在這個過程中觀察到各種優秀的編程技巧,比如,特性的實現可能僅僅涉及複製 / 粘貼,對現有的代碼做出一些細微的調整。這樣的面試過程還假設,你在為 Java 代碼庫雇用 Java 開發人員,或者為 Ruby 代碼庫雇用 Ruby 開發人員,如果你只是想雇用熟練的開發人員,並讓他們在工作中學習你的本地工具,那麽這種類型的面試並不奏效。

這裡我已經討論了一些需要避免的事情,但是我們應該要求程序員在面試中進行現場編程的基本前提仍然是成立的。現在讓我們來思考一下,儘管它並不受面試者歡迎,為什麽仍然是一個如此普遍的需求?

許多候選人不喜歡接受編程測試。面試者常常覺得招聘流程設計得不好,這些帶來了大量的錯誤否定,導致人們充滿憤怒和怨氣。愚蠢的面試流程阻礙了他們自我能力的展現,因為這樣的原因錯過了一份工作,沒人會為之高興。

你自己覺得能勝任一份工作,卻被面試拒之門外,這是一種糟糕的經歷,尤其是當這個招聘流程貌似含蓄地宣稱其科學、準確時。

因此,雇主們似乎可以不這樣做,而是依靠更傳統的面試形式,比如在面試中談談過去的從業經歷。然而,多年來,編程測試這樣的形式已經從微軟等公司流傳開來,幾乎成了所有地方的行業標準。現在,很少有軟體公司願意只是進行一次友好的電話交談就敲定錄取。這是為什麽呢?

編程測試是必要的

看著實習生帶著心理陰影走出他們人生第一次編程面試,總令人感到那麽”享受“。他們走出來時,先是帶著一種呆滯的眼神,略帶震驚的表情。然後,開始咆哮。

這些應聘者是如何開始先用一種編程語言編寫代碼,然後又覺得實際上他們並不熟悉這種語言,應該從頭開始用另一種編程語言呢?一個簡歷上有 10 年工作經驗的人,怎麽就做不到在自己的編輯器中開始一個新項目呢?面試者怎麽可能花 30 分鐘試圖生成一個隨機數卻仍然以失敗告終呢?這真是太瘋狂了!

老人們咯咯竊笑著,十分享受這個古老的入會儀式。“啊,這並不瘋狂。讓我告訴你大約要花多少時間……”

20 世紀 90 年代,微軟在科技行業推廣了結構化面試,這一面試過程以刁鑽的腦筋急轉彎式智力題而聞名,比如著名的“為什麽井蓋是圓的?”還有一些編程難題,比如“在白板上用 C 語言對一個鏈表進行反轉”。支持這種面試形式的文章是 Joel Spolsky 的經典著作 《遊擊隊面試指南》(Guerilla Guide to interview)。當這本書在 2000 年出版時,很快就被創業公司大量採用,比如一家剛成立兩年的小公司,谷歌。

在一次採訪中,Joel Spolsky 回顧了他向世界輸出的源自微軟的面試趨勢。從當時的非結構化的面試出發,這是一個很大的進步,但如今他已不再滿意於此。遺憾的是,他提出的替代方案是讓公司隻從實習生中雇傭正式員工。

但是我認為這項面試技術最著名的例子是 Imran Gohry 的 FizzBuzz 問題,2007 年 Jeff Atwood 的一篇博文 “為什麽程序員不能編程?” 引起了公眾的注意。Jeff 在他的部落格中寫道:

每個人都是從頭學起的。但令我感到不安和震驚的是,任何所謂的”程序員“都要找一份工作,但其中有些人卻不能編寫最簡單的程序。這對任何以編寫軟體為生的人來說,都是一記響亮的耳光。

Dan Kegel 是我在谷歌和 Wine 項目中,一位受人尊敬的前同事。2006 年,他在談到招聘開發人員時,曾這樣說:

令人驚訝的是,在要求執行基本編程任務的面試中,有很大一部分求職者都失敗了,即使是那些擁有計算機科學碩士和博士學位的求職者也是如此。例如,我曾經親自面試過一些應屆畢業生,他們無法答出“如何寫出一個從 1 到 10 的循環”或“十六進製中 F 後面的數是多少”?

在面試中識別那些急於證明自己優勢的偽程序員,戳穿他們誇大其詞或虛張聲勢的故事,似乎聽起來是件美好的事情。但我告訴你,事實並非如此。每個組建開發團隊的人,真的是每個人,都會開始習以為常,面試官總是在面試中遇到沒有實際編程能力的人,即使“編程”已經很寬容。

人們普遍認為,企業進行編程測試,是因為這些公司裡充斥著癡迷於算法的書呆子,他們都試圖挑出知識盡可能淵博的候選人,希望公司成為下一個谷歌,事實並非如此。公司會進行編程測試,是因為他們遇到了很多候選人,他們的簡歷看起來都很不錯,甚至能對計算機行業侃侃而談,但在被要求編程時,實際上卻無法寫出程序。真的不誇張,一點程序都寫不出來。

如果你是一名求職者,能夠達到下列條件,已足夠讓你脫穎而出:

如果你聲稱自己懂一門編程語言,那就應該樂意在面試中使用它。我猜測,在簡歷中列出 C++ 技能的求職者中,至少有 50% 的人在被問及 C++ 技能時,拒絕用 C++ 編寫程序。

熟悉你的工具。如果你是 Java 開發人員,這意味著你知道如何在你所選擇的 IDE 中創建一個新項目,編寫一些代碼,並運行它,然後定位程序所創建的任何輸出。你還應該知道如何編寫和運行測試,以及使用調試器。

如果面試官要求自帶工具,那就帶著平日所用的工具去面試吧。不要試圖在面試過程中現場安裝東西。

熟悉一些基本編程要素:比如集合、IO、字元串操作、循環、數據類型,等等。如果你是一個函數式程序員,那麽你應該了解如何在適當的位置對列表進行實際修改。我就看到過 Scala 程序員 100% 都敗在了一個肯定有著明確解決方案的問題上。

了解你將要嘗試使用的語言。不要被語法或類型安全方面的常見錯誤搞迷糊了。

如果這些對你來說都很基本,那麽歡迎來到程序員面試的世界。

編程測試之所以重要還有一個原因。那些經驗豐富、技術嫻熟的工程師,也就是你想要雇傭的那種人,也會意識到這個門檻問題,他們也不想在一個隨便什麽人都招的團隊中工作。一個強大的招聘流程不僅是求職者給面試官留下深刻印象的機會,也是面試官給求職者留下深刻印象的機會。我遇到過的最棒的同事,都因為公司面試很難而吸引了他們。在效率和誤判之間取得正確平衡,是構建軟體公司藝術的一部分。

然而,從候選人的角度來看,大多數關於面試的恐怖故事並不是來自那些第一關就失敗的人。大多數對編程測試感到惱火的人之所以感到鬱悶,是因為他們覺得自己被要求解決一些複雜而卻不具有代表性的奇怪問題。

為什麽總是出算法題?

面試中,最常見的就是要求編寫自行實現的排序函數,反轉二叉樹,或者做一個圖表搜索。

求職面試就像被直接送回大學學習一樣。這麽多年所有編寫實際程序的經驗突然被扔出窗外,你就像又回到課堂上,你被要求證明自己對理論課題的精通,而實際上那些喜歡啃 Donald Knuth《計算機程序藝術》的程序員總是能先你一步作答。

對於這種情況,當我閱讀網上的討論時,遇到的最常見的解釋是雇主是白癡。第二種最常見的解釋是,雇主都想成為谷歌,而谷歌顯然需要計算機科學專家,而其他公司並不需要。但不管怎樣,這些雇主還是非常推崇谷歌的招聘流程,希望讓自己成為億萬富翁。

而真正的解釋其實相當平淡乏味。當你坐下來為開發人員編寫一個面試問題時,必須滿足許多限制條件才能設計出一個好的問題。而滿足所有這些約束條件的問題,往往看起來就是“算法類”問題。

這樣的問題是恰當的。面試的目的是盡可能快地提取候選人的信息,並沒有要求一個好的面試問題必須代表真實的日常工作。為了說清楚這一點,可以想想怎麽面試飛行員。在建立了基本的誠意之後,可以在面試中詢問候選人在各種緊急情況下應該做什麽,這樣的問題是合理的。緊急情況雖然不能代表日常飛行工作,但安全特別重要,所以沒有人會指責面試官問了一些不相乾的問題。然而,這種指責在軟體世界中卻總是隨處可見。

既然我們的目標是盡可能快地提取求職者的技能信息,那麽我們的限制條件是什麽呢?

首先,要完成的程序需要非常短小。除非你想把整個面試時間只花在一個問題上,否則,一個有能力的開發人員在理想狀態下,應該在 30 分鐘左右完成這個程序題。而 30 分鐘裡寫不了太多代碼,這個約束已經淘汰了大多數可能提供實用價值的“真實”程序。

其次,它需要面試者獨立完成,不需要複雜設置或特定環境的知識。在面試中每多花一秒在解釋問題,就少花一秒去觀察候選人展示自己的技能。有時我在網上看到這樣的評論:“Foo 公司做 bog 標準的商業 web APP,所以他們面試時為什麽不讓我做一個 REST API,而是讓我自行實現一個排序函數呢?” 但是,請嘗試著寫下一個“編寫 REST API”的問題來甄選候選人,然後你會發現這個問題其實很大。這個 API 實際上實現了什麽?數據從哪裡來?希望面試者連接到數據庫,還是從文件中提供數據,還是在記憶體中維護數據?諸如此類的問題。

理想情況下,一個面試問題應該可以在 30 秒或更短的時間內解釋清楚。但有些公司確實會問這樣的問題,如果他們隻願意雇傭有專門技能的人,即在他們所選擇的特定框架下工作,並且該框架能夠自動化生成所有的樣板文件,那麽他們用這樣的問題來面試是可以的。在 R3,我們更願意雇傭來自不同背景和專業的開發人員,所以我們必須堅持使用那些無需任何特定框架或技術,就能得出可靠答案的問題。

第三,實際上這些問題應該能讓你相信候選人懂編程。編寫一些返回一些虛假 HTML 的函數並不能解決這個問題。至少,你希望候選人能夠運用循環、集合、類、IO,並且熟悉他們的標準庫,當然我的意思是大致了解其中的內容,而不是牢牢記住每個 API。

第四,它應該給優秀的候選人一個脫穎而出的機會。我所提到的這些技能似乎都是非常基本的。這並不意味著這家公司的招聘標準很低。一個好的編程測試在問題上會設置足夠的深度,從而讓一個優秀的候選人可以迅速且令人印象深刻地創建一個比初學者更好的解決方案。有了足夠的實踐,面試官就能學會區分有經驗的開發人員和初學者,即使他們向每個人提出相同的面試問題。

最後,你需要一些證據,證明候選人能夠接受一個不會馬上得出明顯解決方案的問題,並通過自己的思考找到答案,而不是停滯不前。這個問題的確切性並不重要,重要的是它不能通過候選人盲目地匹配以前見過的東西來解決。這也是整個過程中最模糊的部分,對應聘者的思維能力進行測試到底意味著什麽?它排除了“直接套用別人編的代碼來做這件事”這種形式的大多數解決方案,儘管在實際工作中,這通常是正確的方法。

簡短,容易解釋清楚,隻使用基本的語言特性,可能有糟糕的 / 優秀的解決方案,也不會流於套用樣板。我認為,所有這些約束條件都是打造一個稱職團隊的基礎,但試圖滿足這些要求,就不可避免地會導致面試者們遇到一些顯然不具有代表性的算法難題。這些問題的目的,並不是要考察你是否真的記得那些你可能從未上過的計算機科學課程中晦澀難懂的算法。這只是找個理由讓你編寫包含大部分基礎知識的代碼罷了。

所以不要強調你的答案是否具有理想的計算複雜度,至少別在第一次嘗試的時候做這樣的事情,面試官可能並不在意複雜度。相反,應該把重點放在用快速和有效的方式編寫乾淨的、沒有 bug 的代碼上。然後,如果你還有剩餘的時間,可以再倒回去做進一步優化。

結 論

由於缺乏全球認可的認證機構,以及對具體技術技能的需求,招聘開發人員的流程比某些行業要更加嚴格。從雇主的角度來看,這個流程在過去幾年裡有了很大的進步。對於那些樂於做這類面試的求職者來說,得到的獎勵是能進入能力更均衡的團隊,這樣的團隊中沒有 無用的偽程序員,而關於這點的抱怨,在過去相當常見,當然,在沒有採用這種面試流程的組織中可能仍然如此。

儘管如此,我必須指出的是,無論我們在這個行業付出了多大的努力,招聘在很大程度上仍有隨機性。精心設計的面試流程總是比隨機面試稍微好一點,這就是為什麽我們要這樣去設計面試流程。但考慮到解雇不合格員工的高昂成本,而且人們總是對誤判中的否定比肯定抱有更大偏見,因此,很可能會一直存在這樣的恐怖故事:在一家公司,本來明顯可以取得成功的候選人,卻遭到了機械程序的拒絕。正如 Spolsky 提出的用實習代替面試的建議所顯示的那樣,儘管存在種種缺陷,但這種制度仍然難以克服。

查看英文原文:

https://blog.plan99.net/in-defence-of-the-technical-interview-966f54a58927

點個在看少個 bug

獲得更多的PTT最新消息
按讚加入粉絲團