高效的面试方式:结对编程
有一定职业编程经验的人一定都知道,业界标准的面试模式大致如此:进入面试房间后,给你一个白色写字板(国内用纸卷做题应该也很常见),让你在上面写出每个问题所对应的代码。
这样的面试大家都会觉得不爽。在平时的工作环境中,你可以访问API,或者通过搜索引擎来寻求你的答案。但面对一张白板/白纸,这些都不可能。白板上的问题一般不会涉及到太多整体设计方法,往往局限于简单的算法问题,所以仅凭这一套面试题很难测试求职者的所有技能。说实话,一般程序员写字都很糟,让他们在一个大的白板上直接写代码感觉好不了。
我们喜欢编码。我们喜欢坐在电脑旁,喜欢和同事一起探讨自己的想法,并通过编译器来验证。白板面试仅能帮助面试官了解求职者的很少信息,但求职者不会从面试中学到任何东西。简言之,这种标准的面试方式还有许多需要改进的地方。
我所在的公司(译注:指Rally软件公司,5月底作者刚刚离开,加入了时代华纳有线)正在尝试另一种更高效的技术面试方式:结对编程。
新方式主要是在传统面试基础上增加了一些环节。求职者通过电话筛选后,会与团队中的两个开发者进行一个小时的直接面试(采用白板模式),随后会安排应聘者和其中一个开发者坐在一起,让他们去共同完成一个任务。
我已经尝试用这样的方式面试了一些应聘者,新增加的这些面试环节取得了很好的效果,所以我希望在此稍详细的介绍一下这个面试过程,并分享一下它带来的好处。
具体怎么做?
我们有一个名为“pairing”的git远程仓库,它包含一个基于IntelliJ的项目框架。其中包含Java、Ruby和JavaScript模块,面试者可以从我们常用的语言中选择自己最熟悉的。
每个模块都有一个基本的项目结构。比如,Java模块包含一个maven pom.xml文件,和“main”和“test”目录。这个pom文件也包含常见的库以方便应聘者编程。还有很多commons-lang工具包,以及Google Guava、JUnit、TestNG、Mockito和很多常用的库。
每个模块还有一个“README.txt”文件,它列出了一些练习。在Java模块里有5个练习。求职者可以从中挑选一个自己最感兴趣的项目。这些练习项目在结对编程的情况下大概需要花费两个小时,难度级别一样。同时,它们广泛覆盖了开发者所要解决的各种不同的问题。有一些涉及到大量的字符串和文本操作,另一些本质上则是纯粹的数学问题。
比如,其中的一个问题是写一个程序来分析一组扑克牌,并选出它最好的组合牌型(顺子、满堂红即三带两、对子等)。起初,我们计划采用两组扑克牌,并从中选出一组获胜者,但考虑到这样会使难点加大,为了与其余4个项目难度相当,我们最后又做了一些简化。
我向应聘者解释说,他们并不是必须要完成练习(这点很重要)。“我们的目标不是完成这个任务,而是让彼此感受一下对方喜欢如何工作。”但很多面试者仍试图能尽快完成该任务,每当我察觉到他们这么做时,我就开始问一些关于代码的值得思考的问题,以便他们能慢下来。一旦应聘者意识到他(她)已没有机会完成这个任务时,他们就会慢下来,停止冲刺。
当面试者写了一些代码后,我会寻问他们计划如何测试代码的准确性。一些人喜欢经常运行所写代码,一些人会写一个“public static void main”方法来验证所写代码是否实现了正确的功能,还有一些人会通过单元测试来验证。无论他们如何回答,我都会建议他们继续做下去,并确保到目前为止,所写的代码是正确的。这是一个很好的建议。因为在练习过程中最糟糕的事情就是,直到面试临近结束时,他们才运行自己所写的代码,结果发现了一堆的Bug,在剩下的时间里很难调试完。如果某个应聘者喜欢写测试代码,那我将和他(她)一起做乒乓结对编程(译注:结对编程的一种,在结对编程引入测试驱动开发,两个人轮流编写测试,由对方编写能通过测试的代码,能有效提高代码质量)。
很多时候,面试者都会问一些诸如“如果输入无效,我们应该怎么做?”之类的问题。我通常会反过来问他们,他们打算怎么做。在练习中,并没有所谓的完全错误的答案。有时,他们会提出想用Google搜索一些东西或查阅一些文档,可能有人会觉得有作弊之嫌。但我会说,对他们使用何用工具、资源没有任何限制。并反复强调说,他们应该像在平常工作中解决问题那样来完成这个任务。
在练习的最后20分钟左右时,我喜欢让面试者停止编码,并和他们一起讨论他们编写的代码。应聘者为什么采用了某种设计,而没选用另一种;他(她)是否还有其他想做的事等相关问题。我也会问他们,“如果我们计划和其他工程师一起对这些代码进行代码审查,在审查之前,你计划对这些代码做些什么?”通常在短短的两个小时内,面试者很难按他们所设想的去重构代码,所以我也希望了解,如果还有时间,他们将会从何入手。
当然,他们离开后,这就是我要做的事。其他的一些开发者和我一起审查这些代码,问我一些相关的问题,并就诸如代码风格等问题展开讨论。
有哪些好处?
上述面试过程所带来的反馈效果是相当不错的。首要的是,应聘者也很喜欢这种面试方式。相比在一个安静的屋里拿着白板笔苦思冥想,他们感觉在实际的电脑旁写代码更舒服。他们觉得这种面试方式比传统面试方式更轻松(刚开始面试者的反应让我都有些惊讶)。每个经历过这种面试过程的应聘者都表示很喜欢,我们今后的面试都将按这种方法来进行。而且,这种面试不再是单方面的了:应聘者感觉面试就好像在工作一样,双方可以很好地对彼此进行评估。
另外,相比普通面试,面试官通过上述面试过程,能更好地了解应聘者的“软技能”。他的交际能力如何?他和同事一起思考、解决问题的过程是怎样的?他喜欢协作,还是喜欢独立工作?他是否喜欢开玩笑?通过这些编码实践中,我对这些问题都能找到了很好的答案。
最重要的是,你实际上正在他们每天实际工作的环境中面试他们。因为开发者一般不会在白板上编码,所以白板面试只能测试应聘者在做白板面试时的好坏程度。他们可以用编译器或解释器,他们可以用测试工具,他们可以Google搜索,在结对编程练习中他们可以用所有这些辅助工具,但在白板面试过程中,这些都是不允许的。在熟悉的工作环境中测试开发者可以算是评审他们的一种极其高效的方法。
因为这种面试长达2个小时,并且只关注一个任务,所以更有机会了解面试者是如何进行编码设计的,比起“请写出一只鸡的对象模型”这种类型的设计问题来得更加实在些。不必要求应聘者画出UML,你就可以了解他的设计能力如何,因为他们在现实工作中可能并不总画UML图。
在主要的开发领域,采用上述面试过程是很重要的,不是呆在一旁的房间里,而是开始结对编程实践。面试者有机会看到他们将工作的环境,并有助于他们对文化环境做出评价。如果你工作在一个嘈杂、非正式的办公环境中,开发者可随时播放音乐和彼此开玩笑,当应聘者真正参与到此环境中时,面试官可以看到他们是如何融入到环境中的。
还有一点很重要,它感觉并不像是在面试。它并不是由面试官来拷问,然后面试者写下所有代码来回答。这并不是现实生活中结对编程的工作方式,所以在结对编程练习中,它也不应该是这样的。面试官也应该写一些代码,以显平等,面试者也会感觉更舒服些(应聘者当然要更多地负责解决问题的任务)。
基于应聘者和面试官都喜欢这种面试过程,目前我很难有理由去进行白板面试。就我个人而言,在和应聘者进行结对编程练习之前,我甚至都不看应聘者的简历。在结对编程之前,我觉得没有必要了解应聘者的任何事情,我喜欢在和他们完成任务的2个小时里去了解面试者的一切。
如果你在招聘优秀程序员的过程中有困难的话,可以尝试一下这个面试过程。把结对编程作为面试过程的一部分,看看效果如何。
原文链接:Different Kind of Technical Interview
【讨论】
此文引起了热议。有人提醒,在结对编程面试中不要让面试者在生产代码中开发,会涉及法律问题。
还有人认为这种面试会耗费更多资源,很多公司未必能效仿。这种说法当然引起了很多人的炮轰,很显然,这是典型的磨刀不误砍柴工,招到一个优秀的新同事会事半功倍。而作者回答说,其实资源与原来的方式相同,因为他们公司之前是三轮面试,第一轮电话筛选,第二轮是两个考官进行的白板面试(1小时),第三轮本来是另一组1小时的两考官白板面试,现在换成了一考官2小时结对编程。
还有人质疑,为什么非要结对编程呢?给面试者一台电脑,一个任务,让他编代码去,然后再问问问题,不也行吗?作者回答,通过结对编程,很逼近实际的合作场景,可以全面了解面试者,这是另一种方式无法做到的。
更多讨论可以访问:Reddit