程序员面试的标准答案并不标准

Peter Verhas 在技术面试时问了一个看似无关的问题,并得到了一个虽然没错但并不恰当的答案。随后,他宣称,“有时候,我会碰到那些不但不知道答案,还自作聪明地给出错误答案的候选人。知道错误答案比不知道更糟糕。一些极少数的甚至坚持和试图向我解释我应该如何理解他们的答案。这已经成为了一种个性问题,而且毫无疑问是面试中要 pass 掉的人。”我要声明的是,Peter 不仅是错了,而且这样的面试条件完全损害了他所就职的公司的利益,我个人绝对不会工作于有这样一种态度的公司。

你可以先去阅读他的原始文章。事实上,用不了多长时间。

好了,既然你已经了解了材料,那么下面让我们彻底地探讨一下吧。

问错误的问题

对于初学者来说,在我看来,整个过程从开始就错了:

有很多关于 Java 技术面试的问题,即使是最入门级的新手也能给出正确的答案。当我面对不那么初级的候选人时,我不会问这些问题来浪费时间。我假定候选人知道正确答案。但是,有时也有一些一开始我就认为是新手的候选人,我会削减面试以避免浪费他/她和我的时间,因此,我会问一些简单的问题。这些问题的答案通常能揭示知识的真正水平,于是我们就可以在较短的时间内评估其水平。

但是,伙计们,有一点要清楚的是:如果你是技术面试的面试官,那么你必须要求他们写代码,而不是回答问题。除非他们申请的职位就是用来解答编程问题的(在这种情况下,你面试的是老师,而不是实际的程序员),否则你就得要求他们展示他们的技术能力,而不是他们的口头知识。

这样做的原因应该是理所当然的,但如果你还不明白的话,我会从逻辑,例子,和类比这三个方面加以论证。

逻辑:你面试的程序员不是每一个都受过传统训练。他们可能不知道全部的偏好术语。是“getters and setters”还是“automatically-defined properties”亦或是“accessors and mutators”呢?这在某种程度上取决于你是在什么语言下成长的(例如,如果是 C ++ 的话,在相当长的一段时间内更喜欢用后者)。这取决于你阅读的是什么书。这取决于你有没有和其他人讨论过这些——也许是从一本书上学来的,并且是在网络上阅读相关内容。(StackOverflow 最近的民意调查显示,求职者中约三分之一或更多的开发人员自认为“自学成才”。)因为他们没有用对词,你就要踢掉完全合格的候选人吗?而这还不包括那些因为在面试时过度紧张而导致甚至简单的问题也回答得乱七八糟的人。

例子:有一个为我工作了两年的开发人员是一个相当有能力的 C# 开发人员。这是一个能领导小组,能指导一些比较初级开发人员,并想出一些相当得力的设计的家伙。然后,当潜在客户在会议中要求他讲解静态方法是什么的时候,他完全搞砸了,他牛头不对马嘴地开始谈论起构造函数和其他一些文不对题的东西。直到他终于意识到自己在说什么的时候,我已经坐在那里用一脸“见鬼了?!?”的表情看了他几分钟。如果按照 Peter 的标准,那么毫无疑问他会面试失败。然而,在那次会议之后,他依然为那个客户担任了 9 个月的团队领导,对于他的技术,他的能力,以及那些静态问题的答案(讽刺的是,从来没有人谈到这一点!)没有人提出异议。换句话说,在没有面试压力时,他做的很好,他的工作也说明了这一点。

类比:比方说,如果你要雇佣乐队来为你的婚礼演奏,那么你真的介意他们讲解音乐理论和作曲的能力吗?或者说你更关心的是他们能不能演奏你最喜欢的舞蹈音乐,能不能演奏你的配偶选择的歌曲,能不能让你的祖父祖母也跑到舞池中跳起来?很多乐队(甚至我敢说是所有乐队!!)是因为他们的工作表现和/或样带才得到的演出机会,而不是他们回答问题的能力。

期待错误的答案

接着,Peter 说,

知道错误答案比不知道更糟糕。一些极少数的甚至坚持和试图向我解释我应该如何理解他们的答案。这已经成为了一种个性问题,而且毫无疑问是面试中要 pass 掉的人。

呵呵,真是狂妄自大,索性你就叫“编程面试上帝”得了。我的意思是:

有这样一个简单的问题:一个类的静态方法能不能调用同一个类的非静态方法?如果你稍微懂点 Java,你知道答案是:no,不能。静态方法属于类,而不属于实例。你甚至可以直接使用类的名称执行静态方法,而不需要任何类的实例。甚至在整个 JVM 中没有类的一个实例,它也可以运行。因此,哪里能够调用一个运行连接到实例的普通方法?

狂妄自大的家伙,没有理由认为静态方法不能调用实例方法,好不好。这里 Peter 的问题基于这样一个事实,静态方法没有特定对象的引用(通常是“this”引用),这是给出的答案的理由:“没有 this,没有方法调用”。

然而:

话又说回来,这时出来一个候选人他的回答是:yes。他甚至开始解释这样的情况可能发生在静态方法访问实例的时候。它可能会得到一个实例作为方法参数,并且通过那个引用,它可以调用实例方法。他说的是对的。

但是:

这样的回答并不能改变他对 Java 知之不深的事实,虽然在这个非常特定的问题上,他的回答是对的。

所以,请原谅我的直言不讳:这个答案可以说是对的,但你也可以说是错的,因为“这个候选人没有深刻地了解 Java”?但是反过来我也可以说,这个候选人就是因为充分地理解 Java,才能找到一个虽然出乎你的意料、但实际上却是正确的答案。

接下来会发生什么就显而易见了:对自己的技术自信满满的面试官,准备好了一系列已经规定了答案的问题来询问候选人,如果候选人没有按照他的答案回答,那就被认定为是“不合格”。

举一个我亲身经历过的例子。几年前我到一家公司去面试一个 C ++ 的职位,当被问到“私有字段能不能从类的外部访问时?”,正常的回答应该是“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”字段是不能从其他地方访问的,是不?

不过,我的回答是:“当然可以。你只需要将对象实例转换成 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”,并认为这是我在这门语言中的得意之作之一。)

好了,你的回应可能是:

  • 哇,想不到你能想到这一点。很有意思。我在想…
  • 好吧,这样的确可以,但它不算是一个好主意。
  • 你完全没有领会这个问题的精神。所以,你还是错了。

如果你的回应是前面两个中的一种,那么我和你在同一阵营。它是一种尝试,无论如何这是一种尝试,而尝试通常是你正在做错事情的标志,除非是在非常狭窄的情况下,没有其他办法,以及除非从今往后你是唯一一个接触那些代码的人。

但是,如果你是第三种回应,那么你可能没有抓住要领。问题的要领就是,候选人指出了一种绕过绊脚石的方式。如果你不能认识到这一点,那么我认为错在于你,而不在于候选人。

你雇用的人与你面试的判定标准相关

不管是对是错,你给出你的问题,候选人用他们的方式想问题,然后想出一个新奇的答案。但是只关注答案的话,你就会错过重要组成部分——他们找到的绕过它的办法。

面试可用于发现那些满足一定技术门槛的候选人,也可以用来找到那些有办法绕过障碍物的求职者。Bug,生产中断,设计缺陷,不管是什么,你需要找寻那些不会墨守陈规的迂腐之人。

但是当候选人真的这么做了的时候,你又把他刷了下来。

所以,其实你想要的是那种普通的,乏味的,没有主见的答案,而他们给出的却是一个“开箱即用的”,有创意的,令人耳目一新的答案。

你是否声称你只聘请“最好的”?但是要知道,如果你这样做的话,那么你聘请的只是那些中间的普通的程序员,在最理想的情况下。那些鹤立鸡群的程序员往往是一些开箱即用的思考者,因为他们知道有时候以及在一些特定情况下,规则是用来打破的。

在这一点上,你认为他们会满意你这样中规中矩的面试官吗?我想也不会。

总结

所以这里的挑战是:如果你是面试官,你要面试什么呢?

顺便说一句,还记得我提到过的多年前面试过的那家公司吗?面试官的回应非常典型:“不好意思,正确的答案应该是’不’,但是我知道你的意思。你是第一个给我这样一个回答的人。”此后不久,他们就雇用了我。并且在我离开公司之前,我使用了不少语言技巧来帮助显著精简了他们的代码库体积。

本文文字及图片出自 www.codeceo.com

余下全文(1/3)
分享这篇文章:

请关注我们:

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注