近期面试观摩的一些思考

作为软件工程师,工作有一些年头了,在不同的公司,也面试过不少人。以前没觉得这事儿多有意思,但是这几年想法改变了,我发现在一家公司,去面试不同的候选人,是一个非常有价值的增长阅历、经验,让自己成长的机会,还有机会见识到各种各样的人的,获知他们不同的思考问题的方式。特别是作为 bartender(在 Oracle,bartender 基本上就是面试的技术负责人,所有团队招人,都必须有一个来自别的团队的 bartender 来保证候选人的水准,具体的面试流程你可以参考一下我写过的 这个专栏 ),这样的机会有很多,虽然会占用一些自己团队和项目的时间,但是和收获比起来,显然是很有价值的。

最近跟一些公司内一些经验特别丰富的 bartender 交流,并实际地 shadow(包括 reverse shadow)了一些他们的面试,学习了一些面试方法,包括其间的各种思路和套路,感觉有不少收获。有几个 bartender 是 IC-6 的级别,这个基本上就是 Oracle 的工程师技术上升通道上理论上能够达到的最高级别了,整个公司也没几个人;还有几个则是在 Oracle 有了几百次面试的经验,也可以说是阅人无数了。因此无论从哪个角度说,这样的学习机会都是很难得的。这里说的 shadow,就是 “观摩”,指的是这些经验丰富的工程师面试,我旁观,结束之后大家再切磋一下;而 reverse shadow,则是反过来,我面试,他们中的某一个旁观,结束之后再切磋一下。

这里面有几个思路、观点,我在这里记录和分享一下,有一些是来自别的同事,有一些则是自己的。当然,需要明确的是,面试没有什么 “最佳实践”,在这么短的时间内要对一个候选人定性,本来就是一件非常困难的事情。

采纳推荐人的意见

有时候候选人有公司内的员工推荐,大家都认为推荐人的意见往往非常有价值,因为面试官可能就花了一个小时和候选人接触,而推荐人则可能和候选人一起工作过很长时间,显然这样的评估更为全面。

在 debrief(相当于面试之后所有面试者聚到一起,评估应聘者的的讨论会)的时候,我看到了一些不同的做法。而我的方法是, 请推荐人进入这个会议,接受 “拷问”,但是询问清楚几个问题以后,就请他离开 ,以避免他知道任何 debrief 的进程和结果——因为这些既是对于候选人隐私的泄露,又可能造成他被候选人询问时而可能出现的为难。因此我们让他离开可以让这个状况变得简单,同时我们要让推荐人知道,这些内容是严格保密的。这几个问题是:

  • 你对候选人的推荐程度是什么,为什么?我们知道有些候选人的推荐 “只是认识而已”,有些对于候选人的推荐则 “愿意赌上我的名义”。
  • 你觉得候选人有哪些优缺点?这些优缺点我们可以重点结合面试的反馈做出进一步的评估。
  • 你和候选人是否熟悉,你们是否一起工作过,什么时候工作过,有多长时间?
  • 你在公司、团队工作多长时间了,你的职位和角色是什么?这也是一个必要的问题,显然一个更熟悉本公司、本团队的员工,更熟悉文化,理解产品,这样的推荐往往更有价值。

对,就这些问题,其实 这些问题基本上就是为了明确两个事情:(1)推荐人对候选人的评价本身,以及(2)到底这个评价到底在对候选人的整个评估体系中赋予多大的权重。 当然,也可以询问其他问题,但是上面这几个问题是必须要覆盖到的。

分析问题的角度

对于一些有经验的程序员候选人,在得到一个粗略的、缺乏整理的问题的时候,他会一层一层地抽丝剥茧,把问题梳理清楚。在设计的时候也是如此,而不是很快地跳进问题解决的泥潭中。当然也有很多候选人,也许是大多数候选人,他们上来就开始动手,行动的意愿极其强烈,仿佛只有这样才算有了进展,心里才感到安心。

以往,当我遇到上述后者这样的候选人的时候,我可能会尝试中断候选人这样的做法,并问到,“你想清楚了吗?”,或者是,“你实现的思路是否已经明确?”,以希望候选人 “想清楚了再动手”。

但我现在觉得更好的做法,特别是对于一些经验相对较为缺乏的程序员来说,是顺其自然。尽管这意味着可能会出现设计上大量的反复,可能会出现实现上大量的涂改,候选人可能也将不得不磕磕绊绊,面对并解决一个一个的问题,并低效和曲折地逐步接近他的目标。这没有错,但是 如果你强行改变候选人的思维方式,他可能将因此迷失 。因为每个人的思维方式是不一样的,一般说来,比较理想的方式可能是自上而下的,更有统筹和规划性,可是自下而上却更为容易思考、更容易开始。

这让我想起了 TDD(测试驱动开发),它就鼓励(即便这种鼓励并非出于 TDD 的本意)问题没想清楚之前,就动手,然后逐步往上迭代进新的分支用例。不可否认这种方式有它的好处,但是我依然认为,还是 “想清楚了再动手” 更为理想,至少要把大致思路和重要的分支用例想清楚,在面试中其实也是如此,可是我们当然应当容许不同的思维方式。

另一方面,如果通过这种自下而上的相对低效的方式,候选人能够不断地发现问题,思考解决方案,并不需要面试官较多的指引,就可以独立不断地解决这一个一个的小困难,这就是一个很明确的闪光点了。但这大多是对于经验较少、级别较初级的程序员来说的,他们如果通过了面试,在团队中还需要得到进一步的引导,慢慢改进自己的问题分析和解决方法。相应地,对于一些已经是 “老司机” 的候选人,如果还使用这种自底向上方式来分析解决问题,而没有一个俯瞰的、纵览的视图,这显然就不是一件好事了。

问项目、挖简历的占比

我们的面试中,有一项内容就是挖掘简历和项目,就是说根据候选人的项目经验,找到一个点往深了挖,以了解他是怎样工作的,完成了怎样的成就,从中可以看出很多问题,特别是能够把那些实际做事的人和那些口若悬河的人给区分开。

这个方法其实很好,但是需要注意的是,针对不同的候选人,这种方式在整个面试过程中的占比应该有所不同。具体说,对于经验较少的候选人来说,这个过程可以短一些,因为经验较少,能问出的内容和价值也相对较低;而对于那些几十年经验的程序员,则要多问,不但容易发现闪光点,也容易发现问题。而且,有趣的一点是, 对于特别有经验的程序员,你去仔细挖掘他的简历,还往往是一种 “尊重” 的体现 ,我听说有的面试官,面试一位工作了二十几年的程序员,上来就让写快排,这立马就把对方惹恼了。我们且不说这种面试方法对不对、好不好,也不说候选人的气量如何,但显然把对方惹恼这件事情是很容易理解的。面试过程毕竟是双向的,面试官有义务尽量保持候选人一个愉快的体验,这一点,下文我还会讲到。

主要问题的选择

对于面试过程中,时间占比比较大的那个 “主要问题”,我们都知道要选择一个模糊的、最好是实际的问题,面试官会和候选人花费几十分钟时间,一起来解决这个问题,期间会考察多个方面。但是除此之外,还有一些要点:

  • 不要一味避开那些常见问题,更重要的是要选择自己有着透彻思考的问题,可以是实际项目的问题;
  • 从算法和设计的角度来说,都要允许存在多个解,并且它们可以进行 trade-off;
  • 最好能够存在一些特殊的 case 以考察候选人思考问题的全面性;
  • 可以使用同一个问题问不同级别和经验的候选人,这样以便于把候选人放到一定纵深的实例集合中去比较考察。

快乐,不要沮丧

无论是成功还是失败,都不要让候选人觉得沮丧。最理想的面试,是能够通过一步一步引导,总让候选人觉得不断在进展,并且 问题,或者是子问题的难度总是处于 “垫脚尖能够到” 的程度 ,难了容易灰心丧气,容易了又不能考察出候选人的能力边界。无论候选人能够通过面试,还是不能通过,希望这个过程对他来说,是快乐的,是一次正面的体验。

有人会质疑这一点,如果候选人觉得体验很好,但是最后却没能通过面试,这样的对比是不是更糟?有道理,但是,和留下糟糕的经历这样的印象比较起来,还是留下好的体验更值得。即便候选人没有通过面试,但是他依然可以去和他的朋友说,虽然我没有通过,还是推荐你去。另外,不要在面试的进程中放出任何通过、或是不通过面试的信号。

在面试讨论问题的进程中,需要尽量给候选人一定的自由度。有时候我们希望得到更多的候选人的数据,就会接连发问,可是,这样却可能适得其反,候选人会疲于应付接二连三抛出的问题,而失去靠自己独立去思考和发现问题的机会。

最后,我要说的是,在一个面试的 loop 中,除了 Hiring Manager(招聘经理),其它面试官一般都来自招聘经理自己的团队,唯有 bartender 是个例外,他必须来自其他团队,这是为了避免利益相关性上过度的集中,必须引入的一种分散机制(其实我认为这种机制的分散程度还是不足够的,我知道有一些其它的互联网公司有更好的办法)。因此,bartender 必须要有足够的 backbone,其肩上的担子也会尤其重,这个角色的重要性不言而喻。