作为软件工程师,工作有一些年头了,在不同的公司,也面试过不少人。以前没觉得这事儿多有意思,但是这几年想法改变了,我发现在一家公司,去面试不同的候选人,是一个非常有价值的增长阅历、经验,让自己成长的机会,还有机会见识到各种各样的人的,获知他们不同的思考问题的方式。特别是作为 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 以考察候选人思考问题的全面性;
- 可以使用同一个问题问不同级别和经验的候选人,这样以便于把候选人放到一定纵深的实例集合中去比较考察。
快乐,不要沮丧
无论是成功还是失败,都不要让候选人觉得沮丧。最理想的面试,是能够通过一步一步引导,总让候选人觉得不断在进展,并且问题,或者是子问题的难度总是处于 “垫脚尖能够到” 的程度,难了容易灰心丧气,容易了又不能考察出候选人的能力边界。无论候选人能够通过面试,还是不能通过,希望这个过程对他来说,是快乐的,是一次正面的体验。
有人会质疑这一点,如果候选人觉得体验很好,但是最后却没能通过面试,这样的对比是不是更糟?有道理,但是,和留下糟糕的经历这样的印象比较起来,还是留下好的体验更值得。体验如何,毕竟和实际招不招人的决定,是两个相对独立的事情。我们希望,即便候选人没有通过面试,但是他依然可以去和他的朋友说,这家公司很好,很尊重候选人,整个流程我的感觉都不错,虽然我没有通过,还是推荐你去。当然,不要在面试的进程中放出任何通过、或是不通过面试的信号,因为通不通过的决定,是在面试之后的讨论会中才会做出的。
在面试讨论问题的进程中,需要尽量给候选人一定的自由度。有时候我们希望得到更多的候选人的数据,就会接连发问,可是,这样却可能适得其反,候选人会疲于应付接二连三抛出的问题,而失去靠自己独立去思考和发现问题的机会。
面试是双向的
你在面试候选人的时候,候选人也在面试你。基本上,对于那些优秀的候选人,根本就不愁 offer,因此,向候选人 “兜售” 加入团队的机会是很重要的。因为我也有 Amazon 的经验,因此我经常被问到 AWS 和 OCI 的区别,这一点可以说到好几个方面,比如:显然 AWS 更加成熟,工具、设施都比较丰富,而 OCI 的话,很多都需要自己干 ,但是相应地,我们能产生的影响力自然也大得多;再一个,我们每天遇到的问题和挑战,要丰富和模糊得多,这方面还是比较锻炼人的。
最后,我要说的是,在一个面试的 loop 中,除了 Hiring Manager(招聘经理),其它面试官一般都来自招聘经理自己的团队,唯有 bartender 是个例外,他必须来自其他团队,这是为了避免利益相关性上过度的集中,必须引入的一种分散机制(其实我认为这种机制的分散程度还是不足够的,我知道有一些其它的互联网公司有更好的办法)。因此,bartender 必须要有足够的 backbone,其肩上的担子也会尤其重,这个角色的重要性不言而喻。
过程比结果更重要
[Updated on 1/30/2020] “过程比结果更重要”,这可不是一个冠冕堂皇的说法,我想很多来 OCI 面试的人,对这一点都有不同的认识。我想更新一下这篇文章,主要就是来谈一谈我对于这一点的认识。对于面试中最主要的那个问题,我比较喜欢问模糊的,来自于实际的问题(我认为,优秀的问题最好是一个模糊的实际问题,而不是翻转一个字符串或者找一个最大值这样具体的 “纯算法题”,因为这可以考察更多方面,也和工程师日常遇到的问题更为接近),这个问题可以扩展讨论的空间的非常大,里面最主要子问题的解法可能有很多,而其中比较好的解法也有好几种。
这样的问题我会拿来问不同级别、不同工作经验,和具备不同解决问题能力的工程师候选人。有的可能还没有毕业,而有的可能有十五年的工作经验。但是,这是一个可以不断伸展的,不断递进的问题,能够在面试的时间内深入到、并使用到最佳解法来解决的,基本就没有。但是,不能得到最优解,绝不代表这样的面试就是失败的,我希望候选人能够在这样一个多层次的问题中,找到自己能达到的,并且如前文提到的,是 “踮踮脚” 能够找到的位置,这样,问题既能够具备区分度,又能够让候选人完成一个完整的问题讨论和解答的过程,从而让面试具备一定完整角度的考察性(这样的问题设计其实很难,但是如果你感兴趣,你可以看看我在 “极客时间” 专栏中介绍的一个例子,这个例子我虽然现在很少用了,但是也足够清楚地说明问题)。对于同样的问题,通过不断积累面试的数据,可以让自己的对候选人的评估更加客观、理性和稳定。
在这个过程中,我希望考察候选人的沟通能力、对于需求的理解能力、对于问题的分析能力、挖掘问题的能力、思考的条理性和清晰程度、考虑情形的周密程度、将问题和数学能力结合的能力、解决方案工程化的能力、面对困难的态度(面对困难的时候,我们更容易看清自己,比如会轻易地丢掉自己原来思考的方向,比如会听不进建议和问题,比如会在一个局限的圈子里面兜兜转转,而忘掉了实际该解决的问题),等等等等,这太多太多了,这些都是在开始正式编码前后,和面试官一起来攻克问题的最有趣的一部分。
大多数时候,这些问题的考察都在编码前,但也有很多时候,这些发生在编码之后,比如分析怎样去测试代码,怎样取改进,既包括时间、空间复杂度上的改进,又包括代码设计和组织上的改进,分析代码在实际的工程化过程中,会有哪些隐患,等等。
因此,真正编码的部分,其实在其中占的比重,未必很大。我比较倾向于让候选人写一段核心代码,而不是完整的解答,这样可以节约时间。有些时候,候选人这些做得都不错,但是由于时间关系,或者编码生疏的关系,不能够抵达或基本完成编码的环节,在综合评估以后,我依然会给出一个 “incline” 的投票。一个典型的情况是,我的这一轮中,其它过程时间占比过大,但是做得比较不错,因而没有时间留给编码,那么我们在 debrief 的时候,如果其它几轮面试官普遍反映编码能力不错,那么编码这个方面,我们依然会认为已经考察到,并且通过了。
但是候选人可能会意识到自己没有完成编码,或者是完成编码了,但是意识到实现不是最优的,就会沮丧。事实就是,候选人把这个 “结果” 看得过于重要了,而忽略了面试的整个过程中所反映出来的种种能力。从面试官的角度来说,我们希望让候选人感觉这个面试过程是 “完整” 的,能够愉快地结束,因此有时候,在可能的情况下,即便候选人在前面的环节做得不好,我还是希望能给他/她完成一段代码的机会,即便是很短的一小段代码。这段代码,即是对候选人考察的一个方面 ,也是保持面试完整性的一个方面。有时实在没有时间编码,但是如果候选人其它方面做得不错,我可能会安慰他/她说,“虽然没有写代码,但是你我们在很多方面讨论得很深入,已经走得很远了”,这也希望候选人可以保持良好的心态,也保留一个好印象,毕竟,面试是双向的(如前文所述)。当然,也是由于类似这样的差异,有时候候选人觉得自己不是很顺利,却拿到了 offer;有的候选人则觉得自己表现得很好,“搞定了一切”,却挂掉了面试。
文章未经特殊标明皆为本人原创,未经许可不得用于任何商业用途,转载请保持完整性并注明来源链接 《四火的唠叨》
你对候选人的推荐程度是什么,为什么?我们知道有些候选人的推荐 “只是认识而已”,有些对于候选人的推荐则 “愿意赌上我的名义”。
名义 -> 名誉?
确实,修改了
现在很多面试的问题都很开放,面试官挖掘候选人思考的能力,一步步推进的方法,确实是很重要的一方面。
读完以后很有收获,奇怪的是为什么点击量不高捏?怪哉怪哉
一个严肃的问题摆在你的面前:请问这样是否道德?