程序員面試一直是社區樂(lè )于討論的熱門(mén)話(huà)題。我自己從06年實(shí)習以來(lái),先后經(jīng)歷了4家軟件公司,全部是外企,其中有世界500強的通信企業(yè),有從事期權期貨交易的歐洲中等規模的金融公司,也有為大型汽車(chē)制造商開(kāi)發(fā)Android智能汽車(chē)的新興公司??缛隝T行業(yè)以來(lái),我在求職過(guò)程中經(jīng)歷過(guò)多次面試,最近兩年也有過(guò)多次面試別人的經(jīng)驗。我感覺(jué)現在到了對這個(gè)問(wèn)題發(fā)表自己看法的時(shí)候,這篇文章是我站在面試官角度對于程序員面試問(wèn)題的一個(gè)階段性反思和經(jīng)驗總結。
【目標】
相信和不少朋友一樣,有了幾年工作經(jīng)驗成為Senior后就開(kāi)始了面試別人的經(jīng)歷。我在最初這個(gè)階段只是按照自己的想象把”找到基礎好的程序員“,”找到算法能力優(yōu)秀的程序員“,”找到有Android開(kāi)發(fā)經(jīng)驗的程序員“等作為面試的目標。但是,實(shí)際的經(jīng)歷告訴我,尤其是按“基礎好”,“算法好”這些目標招到的人最終效果并不好。比如,有的面試者基礎知識和算法掌握情況不錯,進(jìn)程、線(xiàn)程、內存等概念清晰,基本的Hash,二叉樹(shù),快速排序等數據結構和算法也比較熟悉,但是進(jìn)公司后在實(shí)際工作中表現得很糟糕。后來(lái),我才發(fā)現原來(lái)是我的面試目標出了問(wèn)題,我原先的面試方法更像是大學(xué)的算法或操作系統期末考試,按照這種方法讓許多并不合適的人通過(guò)了面試,同時(shí)也可能錯過(guò)了許多合適的人。
后來(lái),我的反思是,從公司的角度講,面試的根本目的是找到"能夠干好工作"的人,而“高學(xué)歷”,“算法好”,“基礎好”,“有經(jīng)驗”這些都是表象而不是根本,它們并不能直接和“工作好”劃等號。
【方法】
目標明確了,但接下來(lái)的問(wèn)題是假設面試者是一個(gè)黑盒系統,“工作好”不是直接可觀(guān)測變量,你所能直接觀(guān)測的變量是基礎、算法、經(jīng)驗、學(xué)歷、性格、談吐、年齡等等。所以,實(shí)際上,你只能從“基礎好”,“算法好”等可以直接觀(guān)測的量去推測“工作好”的概率,這就是一個(gè)在“X好“條件下"工作好“的條件概率問(wèn)題:P(工作好 | X好)。
根據這個(gè)模型,面試所應該考察哪些方面就很明顯了,那就是選擇那種最具有區分性的方面來(lái)考察。比如,考察面試者的體型特征沒(méi)有太大意義,因為P(工作好|高),P(工作好|矮),P(工作好|胖),P(工作好|瘦)的概率都差不多;所以,體型特征不具有區分性,這不是面試所應該關(guān)注的內容。
面試官應當結合職位的要求明確哪些因素具有比較好的區分性。比如,如果要招一名技術(shù)門(mén)檻比較高的3D游戲引擎開(kāi)發(fā)工程師,面試者A具有3D游戲引擎開(kāi)發(fā)的經(jīng)驗,但是在基礎知識和算法面試方面表現一般;面試者B相反,基礎知識和算法面試表現很好,但沒(méi)有游戲開(kāi)發(fā)經(jīng)驗,而你只能選擇其一。你選誰(shuí)呢?其實(shí),這就是兩個(gè)條件概率問(wèn)題P(工作好|經(jīng)驗好,基礎一般,算法一般)和P(工作好|沒(méi)經(jīng)驗,基礎好,算法好)。這個(gè)問(wèn)題就留給面試官來(lái)判斷了,就我個(gè)人而言,對于技術(shù)門(mén)檻較高需要技術(shù)積累的職位,經(jīng)驗更加說(shuō)明問(wèn)題,因此,我更傾向于面試者A。
下面,我再結合自己的經(jīng)驗談?wù)剬γ嬖囍谐R?jiàn)方面的看法。
【算法】
算法是Google和MS等大公司面試所重點(diǎn)考察的內容。我個(gè)人很喜歡算法,曾經(jīng)參加ACM/ICPC拿過(guò)北京賽區的13名。但是,就個(gè)人經(jīng)驗來(lái)看,我所接觸過(guò)的絕大多數開(kāi)發(fā)職位而言,算法都不適合作為考察面試者優(yōu)劣的主要因素。對于普通的非算法性開(kāi)發(fā)職位,考察面試者的算法就相當于考察他打乒乓球好不好一樣,與目標“工作好”的相關(guān)性太低。就我個(gè)人的經(jīng)驗來(lái)看,差不多P(工作好|算法好)=50%,也就是算法面試沒(méi)有太大的區分性。
甚至,還有一種很不好的情況特別多地出現在算法好的面試者身上,我稱(chēng)之為“只磨刀,不砍柴”。什么意思呢?有類(lèi)人只對什么A*算法,異步編程,JVM類(lèi)加載機制這種純技術(shù)問(wèn)題感興趣,對實(shí)現用戶(hù)需求毫無(wú)興趣。這類(lèi)人看起來(lái)有一定的技術(shù)能力,但是對公司來(lái)講貢獻十分有限,甚至不如技術(shù)一般但認真負責的人。所以,一旦遇到面試者算法好,我就特別留意考察會(huì )不會(huì )是這種“只磨刀,不砍柴”的人。
另外,雖然我個(gè)人不了解Google和MS,但我對于其特別重視考察算法能力的面試策略是持懷疑態(tài)度的。即使在這樣的世界級大公司,算法雖然重要,但可以想象在項目實(shí)施過(guò)程所遇到的各種各樣問(wèn)題中,算法問(wèn)題絕大多數時(shí)候不會(huì )是主要瓶頸,沒(méi)有到那種需要每個(gè)人都是算法高手的情況。實(shí)際上,絕大多數項目真正難點(diǎn)并不是一兩個(gè)算法瓶頸,甚至也不是單點(diǎn)的技術(shù)瓶頸,而是系統性的組織、協(xié)調、設計、開(kāi)發(fā)問(wèn)題,有大量的看起來(lái)不是那么有技術(shù)含量的臟活累活,也有許多問(wèn)題是由于信息不足,并不是技術(shù)能力強就能克服這些困難。一個(gè)團隊最好優(yōu)勢互補,有人算法強,有人業(yè)務(wù)分析能力強,有人擅長(cháng)后端服務(wù),有人擅長(cháng)前端界面,有人聰明,有人踏實(shí),這是最好的。如果按照“算法好”的單一標準選材,必定會(huì )把許多優(yōu)秀的人才拒之門(mén)外。
補充:在更多地了解了Google和Facebook等一流公司的面試細節之后,我對這個(gè)問(wèn)題的認識有了一定的改變,實(shí)際上這些公司在面試過(guò)程中并不完全強調技巧性很強的算法,而是更加注重編碼(Coding)能力,只是在進(jìn)行編碼測試的過(guò)程中往往是通過(guò)一些簡(jiǎn)單算法題來(lái)進(jìn)行的。我對于這種面試方法越來(lái)越欣賞,并且也作為了我們公司面試過(guò)程中的重點(diǎn)環(huán)節,因為編碼能力的測試是十分必要的,它有著(zhù)知識性問(wèn)題無(wú)法取代的作用,如果一個(gè)面試者連“判斷一個(gè)字符串是否是另一個(gè)字符串的子串”這樣的題目都無(wú)法正確并快速地實(shí)現,那么基本上可以直接排除了。我這里所強調的是不必考察高難度的算法問(wèn)題,并非不重視編碼能力測試,請讀者不要誤解。
【基礎】
基礎面試是指考察諸如指針使用、進(jìn)程線(xiàn)程概念等基礎知識的面試,十分類(lèi)似于大學(xué)期末考試題。我曾經(jīng)以為基礎面試十分重要,但是現在不這么看了。在工作中基礎的確是重要的,但是在面試過(guò)程中,它必須具有區分性才有意義,也就是說(shuō)P(工作好|基礎好)的概率要高,那么考察指針使用,進(jìn)程線(xiàn)程區別這樣的基礎題目才有它的意義。我的實(shí)際經(jīng)驗是,基礎面試并不具有很好的區分性,和算法一樣, 差不多P(工作好|基礎好) = 50%。同時(shí),基礎面試是最容易準備的,中國人有長(cháng)期的應試教育經(jīng)驗,要準備幾個(gè)把玩指針題目太容易了。
我曾經(jīng)遇到過(guò)這樣的面試者,他的C語(yǔ)言基礎和編譯、鏈接等原理掌握得非常好,給我留下了深刻的印象,我給的面試結論是:知識面不寬,只會(huì )C語(yǔ)言,但基礎很扎實(shí),建議錄用。后來(lái)的事情證明了那個(gè)結論的前半部分是對的,但是”建議錄用“錯了。他在實(shí)際工作中表現得一塌糊涂,不理解需求,不理解整體架構;同時(shí),上班時(shí)間不是花在項目上,而是花在閱讀諸如《程序員的自我修養》之類(lèi)的書(shū)籍上。最后,這位同事由于長(cháng)期“不出活”離開(kāi)了公司。
基礎不是不重要,而是“基礎好”不足以說(shuō)明面試者能干好工作,因為基礎是屬于局部性知識,而實(shí)際工作需要綜合性能力,二者有天壤之別。C語(yǔ)言、操作系統能考高分,但是不會(huì )寫(xiě)程序的人在大學(xué)我們還見(jiàn)得少嗎? 軟件開(kāi)發(fā)就像蓋房子,綜合能力是設計和搭骨架,基礎知識是碼磚。張小龍原先Foxmail是Delphi開(kāi)發(fā)的,他它不懂C#,你如果要招聘一個(gè)開(kāi)發(fā).NET Email客戶(hù)端的人,你考察他對CLR掌握得好不好有意義嗎? 讓張小龍來(lái)開(kāi)發(fā)一個(gè)C#版的Foxmail真的會(huì )有困難嗎? 你招一個(gè)精通C#但沒(méi)有Email客戶(hù)端開(kāi)發(fā)經(jīng)驗的人來(lái)真的比張小龍靠譜嗎?
我說(shuō)基礎知識不重要,和古人說(shuō)的“不積洼步無(wú)以至千里”是不是矛盾呢?不矛盾!“洼步”與“千里”是一種可累加關(guān)系,但再多的“基礎知識”都累加不成“綜合能力”。學(xué)習軟件開(kāi)發(fā)要像持續集成一樣,一開(kāi)始就是一個(gè)完整的系統,雖然規模不大,問(wèn)題很多,但它麻雀雖小五臟俱全,從小系統到大系統,從簡(jiǎn)單系統到復雜系統逐步演化。
所以,基礎好本身不足以說(shuō)明太多的問(wèn)題,必須進(jìn)一步考察綜合能力。對于基礎面試表現不好的面試者,如果時(shí)間允許也要進(jìn)一步考察,有的面試者其實(shí)是有能力的,只是沒(méi)有進(jìn)行充分的準備。最理想的狀態(tài)當然是基礎和綜合能力俱佳,若不能兼顧,應當綜合能力優(yōu)先。
【經(jīng)驗】
這里所說(shuō)的經(jīng)驗不是通過(guò)工作了多少年來(lái)衡量的,而主要是指面試者的經(jīng)歷,比如,是否完整地實(shí)現過(guò)一個(gè)軟件,或作為主要開(kāi)發(fā)者完成過(guò)一個(gè)項目。經(jīng)驗的重要性在于它能說(shuō)明一個(gè)人的綜合能力。從項目的性質(zhì)、規模和難度,面試官就可以大致判斷出面試者的綜合能力。如果一個(gè)面試者一直在大公司負責一個(gè)小模塊的開(kāi)發(fā)維護,那么基本可以判斷他不具備獨立或作為主要開(kāi)發(fā)者承擔一個(gè)項目的能力,只適合在另一家大公司做類(lèi)似的事情。對于門(mén)檻較高需要長(cháng)期技術(shù)積累的職位,相關(guān)經(jīng)驗更顯得尤為重要,比如,Linux內核開(kāi)發(fā),JVM開(kāi)發(fā),游戲引擎開(kāi)發(fā),數據庫實(shí)現,高級UX等。對于這類(lèi)職位,沒(méi)有經(jīng)驗的面試者即使綜合素質(zhì)不錯也是需要長(cháng)時(shí)間的學(xué)習和積累才能勝任。所以,基本上如果確定了你的職位屬于此類(lèi),那么相關(guān)經(jīng)驗毫無(wú)疑問(wèn)應該成為首選因素,換句話(huà)說(shuō),P(工作好 | 相關(guān)經(jīng)驗好)的概率是非常高的。
通過(guò)項目經(jīng)驗判斷面試者的優(yōu)劣比通過(guò)基礎和算法測試更加靠譜,所以,面試過(guò)程中面試官應該花比較多的時(shí)間聽(tīng)面試者介紹項目經(jīng)驗,并進(jìn)行深入地探討交流,了解面試者的知識面、思維能力、表達能力等。同時(shí),可以結合項目提一些基礎知識和算法的問(wèn)題,比如,如果面試者做過(guò)C++相關(guān)的項目,那就可以問(wèn)他如何進(jìn)行內存管理?是否熟悉智能指針?如果面試者的回答不能令人滿(mǎn)意,那么就基本上可以判斷他的項目做得不是很好。
要注意的是,經(jīng)驗也是一個(gè)多維度的事物。比如,C++股票交易中間件系統,這就涉及(C++,中間件,股票) 3個(gè)維度。假如面試者A做過(guò)C++股票交易客戶(hù)端,面試者B做過(guò)C的股票交易中間件。從語(yǔ)言角度看,A最匹配,從項目性質(zhì)看,B最匹配,你如何選擇?這就是在多個(gè)維度中,哪個(gè)維度更重要的問(wèn)題,就這個(gè)例子而言,我個(gè)人更傾向于B,因為我認為中間件開(kāi)發(fā)經(jīng)驗是主要矛盾,而從C切換到C++并不是問(wèn)題。所以,面試官需要判斷哪一種經(jīng)驗是主要的,而哪一種經(jīng)驗是次要的。比如,我們招聘Android應用開(kāi)發(fā),這個(gè)職位的Android技術(shù)門(mén)檻并不高,它的真正難點(diǎn)在于做出好的用戶(hù)體驗(UX)。所以,如果一個(gè)面試者沒(méi)有Android的經(jīng)驗我們是可以接受的,但是我希望他在UX方面有經(jīng)驗,至少做過(guò)其他平臺的移動(dòng)應用開(kāi)發(fā)。
【性格】
現在,我來(lái)談我認為最重要的因素:性格。這可能是許多初為面試官的朋友所難以想象的,怎么會(huì )是性格最重要呢?說(shuō)實(shí)話(huà),當我意識到這一點(diǎn)時(shí),我自己也很驚訝!說(shuō)白了,還是 P(工作好|性格好)的概率最高啊。我的實(shí)際經(jīng)驗是,如果一個(gè)人的性格好,他能把工作做好的可能性是最高的,性格好遠比基礎好、算法好要靠譜。
一個(gè)人如果技術(shù)上有缺陷,經(jīng)驗上有不足,但性格好,在團隊中是很容易由其他人來(lái)補位的,他自己也很容易逐漸補起來(lái);相反,如果一個(gè)人的性格不好,所有的技術(shù)優(yōu)勢經(jīng)驗優(yōu)勢都發(fā)揮不出來(lái),甚至還會(huì )起到負作用,而且性格缺點(diǎn)很難改變。我一直談到實(shí)際工作所需要的是綜合性的能力,這種綜合能力的發(fā)揮中性格是至關(guān)重要的。項目中不止會(huì )遇到技術(shù)問(wèn)題,要涉及溝通、協(xié)調,不同的人不同的部門(mén)既有合作又有磨擦,如何處理這些事情都需要一個(gè)良好的性格??梢哉f(shuō),在開(kāi)發(fā)團隊里讓你與眾不同的不是你從哪個(gè)學(xué)校畢業(yè),也不是你過(guò)去的經(jīng)驗,而是你的性格。
當然,性格是一個(gè)復雜的東西,它包含了很多的方面,并非所有方面都是程序員面試所需要關(guān)注的。我的經(jīng)驗是可以重點(diǎn)考察這些方面:
1) 態(tài)度積極還是消極。有的面試者在談吐中就會(huì )自然給你一種積極上進(jìn)的感覺(jué),或者你可以在他的經(jīng)歷中發(fā)現他積極的因素,這些都不是太難看出來(lái)的。相反,有的面試者你能明顯感覺(jué)到他的消極情緒。積極性在工作中是十分重要的,積極的人能給團隊帶來(lái)朝氣,也更易于合作?;旧?,如果確定面試者屬于態(tài)度積極的,他通過(guò)我這一關(guān)的可能性就會(huì )大大增加;相反,如果確定屬于態(tài)度消極的,即使技術(shù)能力不錯我也會(huì )十分謹慎。
2) IQ。我的經(jīng)驗是,總體來(lái)看,聰明的人在工作中的表現更為優(yōu)秀。在面試中要考察一個(gè)人是否聰明并不一定要像Google和MS那樣找些專(zhuān)門(mén)測試IQ的智力題,其實(shí),你只需要看他討論問(wèn)題是不是很有邏輯性,思考和說(shuō)話(huà)是不是反應敏捷就可以做出大致的判斷。另外,眼睛是人心靈的窗戶(hù),一個(gè)人聰明與否,眼睛是會(huì )說(shuō)話(huà)的。不過(guò),聰明也不完全是優(yōu)點(diǎn),比如,當公司或項目遇到困難時(shí),往往是聰明人先跑掉了,堅守的往往是IQ一般的人。
3) 語(yǔ)言表達能力。語(yǔ)言表達能力也是程序員十分重要的一項素質(zhì),它關(guān)系到項目中的溝通是否順暢。面試官可以看看面試者能否用簡(jiǎn)明的語(yǔ)言介紹清楚曾經(jīng)做過(guò)的項目,能否抓住要點(diǎn),能否考慮到聽(tīng)者的相關(guān)背景。一般來(lái)講,語(yǔ)言表達能力強的人綜合能力都不會(huì )太差。
4) 是否具有用戶(hù)意識。有人說(shuō)程序員是做研發(fā)的,哪來(lái)什么用戶(hù)?只有銷(xiāo)售、市場(chǎng)人員才會(huì )和用戶(hù)打交道。其實(shí),這是完完全全的錯誤認識。你寫(xiě)一個(gè)模塊,甚至一個(gè)API,只要有別人用,他就是你的用戶(hù)。有的程序員設計一個(gè)模塊或是一個(gè)軟件總是習慣于從使用者的角度來(lái)考慮,盡量地方便使用者,這就是一種良好的用戶(hù)意識。具有良好的用戶(hù)意識的人更能考慮別人的感受和整體的需要,而不是單純地從自己和局部來(lái)思考問(wèn)題。當面試者談及過(guò)去的項目經(jīng)驗時(shí),面試官可以常常站在用戶(hù)的角度對其進(jìn)行提問(wèn),從這個(gè)過(guò)程中觀(guān)察其是否具有良好的用戶(hù)意識。
5) 如何應對質(zhì)疑和壓力。面試官應該對面試者的回答以及以往項目進(jìn)行合理的質(zhì)疑,看看他如何應對。曾經(jīng)有一位面試者談到做游戲登錄服務(wù)器的經(jīng)歷,我就問(wèn):“如果登錄服務(wù)器掛了,怎么辦呢”?他說(shuō)原先雖然沒(méi)有考慮這個(gè)問(wèn)題,但是可以怎么怎么改進(jìn)。其實(shí),大家都理解項目中有各種不完美,這里面原因很多,只要面對質(zhì)疑和壓力能從容應對努力往好的方向思考解決就可以了,不需要掩飾缺陷,更不應該有情緒。我遇到過(guò)有的面試者,一旦你對其項目提出質(zhì)疑,他馬上產(chǎn)生反抗情緒,或不高興,或不承認有問(wèn)題,這很容易一下子看出來(lái)他在工作中容不得質(zhì)疑和批評,這種人要想合作就很困難。
6) 個(gè)性特點(diǎn)。許多面試者喜歡在簡(jiǎn)歷上寫(xiě)“精通C++/Linux“,這些字眼看得人麻木,如果有人寫(xiě)”喜歡C++/Linux“,我就會(huì )有一種眼前一亮的感覺(jué)?!熬ā笔菦](méi)有感情色彩的敘述,而“喜歡”包含了面試者的個(gè)性,我更愿意看到面試者的個(gè)性。我相信對某樣東西真正的熱情遠比你當前對它的掌握程度更為重要。其實(shí),N年的經(jīng)歷告訴我們,同一個(gè)班的同學(xué),同一個(gè)項目組的同事,雖然每天所學(xué)的知識,所接觸的工作都是相同的,但其實(shí)每個(gè)人的成績(jì)和表現差異是十分明顯的。那么,到底本質(zhì)的差異是什么呢?其實(shí),就是每個(gè)人的個(gè)性。是個(gè)性使得有的人業(yè)余時(shí)間去打球,有的人業(yè)余時(shí)間去看書(shū),有的人喜歡Linux,有的人喜歡Mac。一個(gè)人在團隊中扮演的角色也和他的個(gè)性有很大的關(guān)系。面試官應該引導面試者展現自己的個(gè)性,并判斷其是否有益于團隊。
【總結】
最后總結起來(lái),我的經(jīng)驗是: 1) 面試官的目標是找到”工作好“的人,一定要圍繞這個(gè)目標來(lái)進(jìn)行面試,如果把面試當成了算法或操作系統期末考試這就走入了誤區;2) 面試過(guò)程是通過(guò)學(xué)歷、性格、基礎、經(jīng)驗、算法等可以測試的因素去綜合判斷面試者“工作好”的概率;3) 在各種因素中,性格 > 經(jīng)驗 > 基礎 > 算法。性格是最重要的,如果性格不好,所有技術(shù)能力都會(huì )大打折扣,而且技術(shù)缺陷容易彌補,性格缺陷很難改變;經(jīng)驗體現了一個(gè)人的綜合能力,你可以從面試者過(guò)去的經(jīng)歷中判斷他能從事哪種工作,不能從事哪種工作;基礎和算法則主要起到輔助參考的作用,基礎好的程序員一般適應性比較強,學(xué)新技術(shù)更快,但是切忌單純從基礎來(lái)判斷一個(gè)人的能力。