程序員面試的標(biāo)準(zhǔn)答案并不標(biāo)準(zhǔn)
Peter Verhas在技術(shù)面試時問了一個看似無關(guān)的問題,并得到了一個雖然沒錯但并不恰當(dāng)?shù)拇鸢浮kS后,他宣稱,“有時候,我會碰到那些不但不知道答案,還自作 聰明地給出錯誤答案的候選人。知道錯誤答案比不知道更糟糕。一些極少數(shù)的甚至堅持和試圖向我解釋我應(yīng)該如何理解他們的答案。這已經(jīng)成為了一種個性問題,而 且毫無疑問是面試中要pass掉的人。”我要聲明的是,Peter不僅是錯了,而且這樣的面試條件完全損害了他所就職的公司的利益,我個人絕對不會工作于 有這樣一種態(tài)度的公司。
你可以先去閱讀他的原始文章。事實(shí)上,用不了多長時間。
好了,既然你已經(jīng)了解了材料,那么下面讓我們徹底地探討一下吧。
問錯誤的問題
對于初學(xué)者來說,在我看來,整個過程從開始就錯了:
有很多關(guān)于Java技術(shù)面試的問題,即使是最入門級的新手也能給出正確的答案。當(dāng)我面對不那么初級的候選人時,我不會問這 些問題來浪費(fèi)時間。我假定候選人知道正確答案。但是,有時也有一些一開始我就認(rèn)為是新手的候選人,我會削減面試以避免浪費(fèi)他/她和我的時間,因此,我會問 一些簡單的問題。這些問題的答案通常能揭示知識的真正水平,于是我們就可以在較短的時間內(nèi)評估其水平。
但是,伙計們,有一點(diǎn)要清楚的是:如果你是技術(shù)面試的面試官,那么你必須要求他們寫代碼,而不是回答問題。除非他們申請的職位就是用來解答編程問題的(在這種情況下,你面試的是老師,而不是實(shí)際的程序員),否則你就得要求他們展示他們的技術(shù)能力,而不是他們的口頭知識。
這樣做的原因應(yīng)該是理所當(dāng)然的,但如果你還不明白的話,我會從邏輯,例子,和類比這三個方面加以論證。
邏輯:你面試的程序員不是每一個都受過傳統(tǒng)訓(xùn)練。他們可能不知道全部的偏好術(shù)語。是“getters and setters”還是“automatically-defined properties”亦或是“accessors and mutators”呢?這在某種程度上取決于你是在什么語言下成長的(例如,如果是C ++的話,在相當(dāng)長的一段時間內(nèi)更喜歡用后者)。這取決于你閱讀的是什么書。這取決于你有沒有和其他人討論過這些——也許是從一本書上學(xué)來的,并且是在網(wǎng) 絡(luò)上閱讀相關(guān)內(nèi)容。(StackOverflow最近的民意調(diào)查顯示,求職者中約三分之一或更多的開發(fā)人員自認(rèn)為“自學(xué)成才”。)因?yàn)樗麄儧]有用對詞,你 就要踢掉完全合格的候選人嗎?而這還不包括那些因?yàn)樵诿嬖嚂r過度緊張而導(dǎo)致甚至簡單的問題也回答得亂七八糟的人。
例子:有一個為我工作了兩年的開發(fā)人員是一個相當(dāng)有能力的C#開發(fā)人員。這是一個能領(lǐng)導(dǎo)小組,能指導(dǎo)一些比較初 級開發(fā)人員,并想出一些相當(dāng)?shù)昧Φ脑O(shè)計的家伙。然后,當(dāng)潛在客戶在會議中要求他講解靜態(tài)方法是什么的時候,他完全搞砸了,他牛頭不對馬嘴地開始談?wù)撈饦?gòu)造 函數(shù)和其他一些文不對題的東西。直到他終于意識到自己在說什么的時候,我已經(jīng)坐在那里用一臉“見鬼了????”的表情看了他幾分鐘。如果按照Peter的標(biāo) 準(zhǔn),那么毫無疑問他會面試失敗。然而,在那次會議之后,他依然為那個客戶擔(dān)任了9個月的團(tuán)隊(duì)領(lǐng)導(dǎo),對于他的技術(shù),他的能力,以及那些靜態(tài)問題的答案(諷刺 的是,從來沒有人談到這一點(diǎn)!)沒有人提出異議。換句話說,在沒有面試壓力時,他做的很好,他的工作也說明了這一點(diǎn)。
類比:比方說,如果你要雇傭樂隊(duì)來為你的婚禮演奏,那么你真的介意他們講解音樂理論和作曲的能力嗎?或者說你更 關(guān)心的是他們能不能演奏你最喜歡的舞蹈音樂,能不能演奏你的配偶選擇的歌曲,能不能讓你的祖父祖母也跑到舞池中跳起來?很多樂隊(duì)(甚至我敢說是所有樂 隊(duì)?。。┦且?yàn)樗麄兊墓ぷ鞅憩F(xiàn)和/或樣帶才得到的演出機(jī)會,而不是他們回答問題的能力。
期待錯誤的答案
接著,Peter說,
知道錯誤答案比不知道更糟糕。一些極少數(shù)的甚至堅持和試圖向我解釋我應(yīng)該如何理解他們的答案。這已經(jīng)成為了一種個性問題,而且毫無疑問是面試中要pass掉的人。
呵呵,真是狂妄自大,索性你就叫“編程面試上帝”得了。我的意思是:
有這樣一個簡單的問題:一個類的靜態(tài)方法能不能調(diào)用同一個類的非靜態(tài)方法?如果你稍微懂點(diǎn)Java,你知道答案是:no, 不能。靜態(tài)方法屬于類,而不屬于實(shí)例。你甚至可以直接使用類的名稱執(zhí)行靜態(tài)方法,而不需要任何類的實(shí)例。甚至在整個JVM中沒有類的一個實(shí)例,它也可以運(yùn) 行。因此,哪里能夠調(diào)用一個運(yùn)行連接到實(shí)例的普通方法?
狂妄自大的家伙,沒有理由認(rèn)為靜態(tài)方法不能調(diào)用實(shí)例方法,好不好。這里Peter的問題基于這樣一個事實(shí),靜態(tài)方法沒有特定對象的引用(通常是“this”引用),這是給出的答案的理由:“沒有this,沒有方法調(diào)用”。
然而:
話又說回來,這時出來一個候選人他的回答是:yes。他甚至開始解釋這樣的情況可能發(fā)生在靜態(tài)方法訪問實(shí)例的時候。它可能會得到一個實(shí)例作為方法參數(shù),并且通過那個引用,它可以調(diào)用實(shí)例方法。他說的是對的。
但是:
這樣的回答并不能改變他對Java知之不深的事實(shí),雖然在這個非常特定的問題上,他的回答是對的。
所以,請原諒我的直言不諱:這個答案可以說是對的,但你也可以說是錯的,因?yàn)?ldquo;這個候選人沒有深刻地了解Java”?但是反過來我也可以說,這個候選人就是因?yàn)槌浞值乩斫釰ava,才能找到一個雖然出乎你的意料、但實(shí)際上卻是正確的答案。
接下來會發(fā)生什么就顯而易見了:對自己的技術(shù)自信滿滿的面試官,準(zhǔn)備好了一系列已經(jīng)規(guī)定了答案的問題來詢問候選人,如果候選人沒有按照他的答案回答,那就被認(rèn)定為是“不合格”。
舉一個我親身經(jīng)歷過的例子。幾年前我到一家公司去面試一個C ++的職位,當(dāng)被問到“私有字段能不能從類的外部訪問時?”,正常的回答應(yīng)該是“No,private會把這個字段封裝起來,就好像與世隔離了一樣。”
- #include <iostream>
- #include <string>
- using namespace std;
- class Person
- {
- public:
- Person(const char* fn, const char* ln, int a)
- : first_name(fn), last_name(ln), age(a)
- { }
- string description() {
- return first_name + " " + last_name + " is " + to_string(age) + " years old";
- }
- private:
- string first_name;
- string last_name;
- int age;
- };
- int main() {
- Person ted("Ted", "Neward", 45);
- cout << ted.description() << endl;
- }
按照原意的話,“age”字段是不能從其他地方訪問的,是不?
不過,我的回答是:“當(dāng)然可以。你只需要將對象實(shí)例轉(zhuǎn)換成void指針(void*),然后從對象的開始位置計算偏移量,這樣就可以訪問到它了。”
- int main() {
- Person ted("Ted", "Neward", 45);
- cout << ted.description() << endl;
- void* pTed = (void*)&ted;
- int offset = sizeof(string) + sizeof(string);
- char* pTedAge = (static_cast<char *>(pTed) + offset);
- cout << static_cast<int>(*pTedAge) << endl; // prints 45
- }
我甚至向他們展示了如何將此歸納成為一個模板(我把它叫做“THackOMatic”,并認(rèn)為這是我在這門語言中的得意之作之一。)
好了,你的回應(yīng)可能是:
-
哇,想不到你能想到這一點(diǎn)。很有意思。我在想…
-
好吧,這樣的確可以,但它不算是一個好主意。
-
你完全沒有領(lǐng)會這個問題的精神。所以,你還是錯了。
如果你的回應(yīng)是前面兩個中的一種,那么我和你在同一陣營。它是一種嘗試,無論如何這是一種嘗試,而嘗試通常是你正在做錯事情的標(biāo)志,除非是在非常狹窄的情況下,沒有其他辦法,以及除非從今往后你是唯一一個接觸那些代碼的人。
但是,如果你是第三種回應(yīng),那么你可能沒有抓住要領(lǐng)。問題的要領(lǐng)就是,候選人指出了一種繞過絆腳石的方式。如果你不能認(rèn)識到這一點(diǎn),那么我認(rèn)為錯在于你,而不在于候選人。
你雇用的人與你面試的判定標(biāo)準(zhǔn)相關(guān)
不管是對是錯,你給出你的問題,候選人用他們的方式想問題,然后想出一個新奇的答案。但是只關(guān)注答案的話,你就會錯過重要組成部分——他們找到的繞過它的辦法。
面試可用于發(fā)現(xiàn)那些滿足一定技術(shù)門檻的候選人,也可以用來找到那些有辦法繞過障礙物的求職者。Bug,生產(chǎn)中斷,設(shè)計缺陷,不管是什么,你需要找尋那些不會墨守陳規(guī)的迂腐之人。
但是當(dāng)候選人真的這么做了的時候,你又把他刷了下來。
所以,其實(shí)你想要的是那種普通的,乏味的,沒有主見的答案,而他們給出的卻是一個“開箱即用的”,有創(chuàng)意的,令人耳目一新的答案。
你是否聲稱你只聘請“***的”?但是要知道,如果你這樣做的話,那么你聘請的只是那些中間的普通的程序員,在最理想的情況下。那些鶴立雞群的程序員往往是一些開箱即用的思考者,因?yàn)樗麄冎烙袝r候以及在一些特定情況下,規(guī)則是用來打破的。
在這一點(diǎn)上,你認(rèn)為他們會滿意你這樣中規(guī)中矩的面試官嗎?我想也不會。
總結(jié)
所以這里的挑戰(zhàn)是:如果你是面試官,你要面試什么呢?
順便說一句,還記得我提到過的多年前面試過的那家公司嗎?面試官的回應(yīng)非常典型:“不好意思,正確的答案應(yīng)該是’不’,但是我知道你的意思。你是***個給我這樣一個回答的人。”此后不久,他們就雇用了我。并且在我離開公司之前,我使用了不少語言技巧來幫助顯著精簡了他們的代碼庫體積。
譯文鏈接:http://www.codeceo.com/article/when-interviews-fail.html
英文原文:When Interviews Fail