什么是“代码面试”?前端
“代码面试”指全部直接测试候选人的技能,或审查他们编写的代码或伪代码的方法。这些方法包括:程序员
审查代码片断,或GitHub的我的页面;面试
编程测试(Codility等);算法
编程挑战,或在我的时间里自由完成的题目;数据库
现场编程,或结对编程;编程
在白板上实现算法。后端
代码面试的目的数组
这些方法的出现绝非偶然,而是为了取代那些更差的面试手段,好比:安全
脑筋急转弯:一架波音747中能装多少个网球?网络
咬文嚼字:Java中接口和子类的区别是什么?
白板编程:至少在这些中不是最差的......
发现式测试:“怎样检测链表中是否存在环?”
咱们认为,这一切都是很是愚蠢的面试手段,由于它们没法反映软件开发者在平常工做中所需的技能。所以,咱们在面试过程当中,试图经过代码面试重现平常的工做。
然而问题在于:这种方法也根本无论用。由于真相是:代码面试根本不能重现真实的工做。固然,代码面试能让候选人展现工做所需的部分技能——但代码面试的环境和真正的工做环境彻底不一样。
代码面试的问题
代码面试能减小候选人的数量,但也能拒绝真正优秀的候选人,还能对差的候选人作出虚假的判断。
代码测试会占用面试者和候选人双方大量的时间。若是能产生效果,也许前者还能够接受,但后者会致使很难在买方市场上寻找到好的工程师。
因为随时更新代码测试题很困难,结果就致使面试体验不好。若是候选人对现有的工做满意,那么他们根本不会作你的代码测试题。这些题目也会增长面试的时间,从而延长整个雇佣过程。但这一切都不能增长候选人的数量。
更重要的是,代码面试并不能很好地模拟真实工做。
Google的研究发现,优秀的团队都拥有一项特质,叫作“心理安全”(https://rework.withgoogle.com/blog/five-keys-to-a-successful-google-team/)。只有当团队的全部人都愿意承担风险、愿意身处弱势时,团队才能达到最佳状态。
这跟代码面试彻底不同。候选人一般会感到焦躁、感到压力,担忧一个小错误就会丢失这份工做。所以你没办法得到候选人的最佳状态。
更糟糕的是,这些题目会刷掉那些没有太多自由时间的候选人。经过这些题目只会让你筛选出那些有空闲时间的人。所以你的候选人会更年轻、更没有经验。你还会错过一些其余人,如未婚父母或须要照顾家中病人的人。
有更好的办法吗?
虽然说忠言逆耳,可是你必须去和你的候选人谈话。你须要去了解他们,须要和他们对话。也许这很难,但从总体来看这种方法更容易。
做为面试官你必须提升技术力。
面试技巧:前提条件
代码面试是空中楼阁,看起来很美好,惟一的缺点是没法筛选出好的候选人。你须要思考什么样的技术力和品质对你的团队最有价值,而代码面试只不过是你偷懒的借口而已。
招聘很难,想作好招聘可能须要掌握一系列的技巧。站长站,可是,有些技巧能够当即提高你的面试水平:
事先规定你须要的候选人的特征,该规定须要作到具体、详细;
询问候选人一系列固定的问题;
在面试以后、征求他人意见以前,记下全部面试的反馈;
练习,练习,再练习。
不须要代码的方法
不须要写代码就能衡量候选人的方法可能有一万种。我经常使用的三个主要方法能够覆盖许多不一样的技能。在面试过程当中,咱们会谈论候选人的经验,要求他们作一些代码审查,并与别人合做设计一个系统。
下面我会详细解释这个过程。
我试图经过这些方法找到真正可以胜任技术工做的候选人,而且他们必须能在单纯的编程技能以外给团队带来价值。一般在一次面试中我能在大约一个小时内覆盖全部三个部分。我有信心这些信息能让我找到好的候选人。
深刻挖掘他们的经验
许多团队已经这样作了。他们会在面试一开始花几分钟,询问候选人以前的工做,他们对工做的态度,等等。大多时候这就像随意谈话同样。
但这是不对的。
记住这是面试。你须要尽量地理解他们构建系统时使用的技术。
为了作好这一点,你须要在面试开始以前仔细阅读他们的简历。这不是开玩笑,在面试开始以前至少花上10分钟仔细阅读(不是略读)简历,若是花30分钟时间则最好。要从简历中尽量多了解些他们以前的项目,Google一下看看可否找到他们项目的公开信息。面试时挖掘背景信息所花的时间越少,就越能得到好的效果。
在面试中,要求候选人谈谈他最近最感兴趣的项目。要练习主动的倾听,要学会参与。伪装你是他团队中的一员,或者伪装大家是在作架构审查。你要努力了解他们构建的东西以及构建的方法。这样作的好处和坏处是什么?要让候选人知道,不知道答案无所谓,但重要的是能勾起你的好奇心。
下面是我认为能得到好的答案的问题:
你在项目中的职责是什么?这个问题自己并非决定性的。即便在项目中承担的职责很小,他们也可能很适合大家的团队。你的候选人也许正是由于没能得到重要的职责而在寻找新的机会。所以,知道他们过去的职责会颇有帮助。
你从他人那里得到了什么帮助?没法感觉他人的帮助是个极其危险的信号。即便是我的项目,也必定须要别人的帮忙。你确定不想要一个以自我为中心的同事。
给我介绍下那个功能的工做原理。解释下数据的来源和去向、存储方式以及这一切能带给最终用户的好处。这个问题的答案足以吸引你的好奇心。
这个项目中最糟糕的技术债务是什么?好的工程师必须理解他们作出决定时须要付出的代价。问完这个问题,能够继续询问他们怎样改正这些问题,或者还没有改正的理由。
有没有出过生产环境下的bug或服务中断?测试下他们是否理解bug的缘由,电视剧大全,以及团队解决bug的方法。他们是否提早预期到了bug?下次怎样才能避免一样的问题发生?
这一部分面试能让你直接了解候选人的经验。作好这一部分还能让你了解他们如何感谢别人或责备别人。你将会了解到他们如何在两难的工程问题上作出抉择,他们会与你分享最近的教训,他们与别人沟通技术的能力应该也很明显。
若是他们选择了不太适合的项目,能够考虑谈论其余项目。所谓不太适合的意思是项目不够复杂或他们记不清的状况。
注意,这一步要避免询问相似于“告诉我你解决过的最难的bug”之类的问题。要求别人回忆系统的某一部分的具体原理会带来大量的虚假负面判断。人们不可能拥有他们修复的bug相关的一切知识,这种问题会给面试过程带来很大压力。
让他们审查大家的代码
这项活动一半是代码审查一半是角色扮演。你能够借此筛选出那些可以提高团队总体代码质量并促进办公室氛围的人。
下面是代码审查过程当中须要关注的一些方面:
他们怎样与代码的“做者”交流?交流是否有用?是否高效?是否友善?
他们会着重哪些问题?是否能明确表达出他们的疑问?他们是否会当即指出哪些可有可无的问题?
他们是否善于阅读本身不熟悉的代码?
这个方法须要提早准备不少东西。你须要找到或编写一段代码供候选人审查。你还须要为你但愿候选人找出的问题建立一个优先级列表。不要让面试管当场出题,必定要事先准备好。
在选择须要审查的代码时,不要选择产品代码。你的候选人没有你所拥有的背景知识,这样作其实是将候选人与你的同事比较,而不是与其余候选人比较。
努力下降代码示例中的复杂度。面试的时候,候选人没有太多时间阅读代码,并且极可能他们并无想到会作代码审查。热身就要花很长时间。
在代码中加入一两个真实的bug,但不要强调找bug。通常来讲,代码审查并非个好的找bug方法,特别是审查者历来没有见过代码的状况下。能自证的bug(如给须要数组的函数传递字符串)最好。在你的优先级列表中,bug的优先级应该是最低的,bug应该是给极其优秀的人的加分项。
最后,代码应该作一些实际的事情。若是你的公司很出名,那能够选择你的产品简化版本。但若是你须要花大量时间为候选人提供背景信息的话仍是算了。
最好的选择要么是虚构的代码(也许能够选择本文竭力避免的代码面试中用到的代码),要么是开源代码中的一个拉取请求。
一旦决定了要审查的代码,你应该期待候选人找出下面这些东西:
过于糟糕的拉取请求的描述或提交信息;
能用但没法自洽的代码;
过于复杂的代码(须要重构的代码);
混乱的变量或方法名;
过分设计的代码(即实际上永远不会用到的功能)。
若是代码中没有足够的问题,就多加一些。
这里有个潜在的问题,我尚未肯定的答案。这个问题是:你是否应该提早将代码发给候选人?
若是你这样作,就又给那些有空闲时间的人以巨大的优点。若是不这样作,就要面临增长面试压力的风险。
我倾向于后者。好的面试官能够减轻压力,方法之一就是让面试者提早知道他们将作代码审查,你也能够在审查开始以前介绍你的指望。
共同设计系统
做为面试官,你最重要的任务之一就是判断候选人是否能完成要求他们完成的技术工做。好的评价方法应当尽量避免虚假的正面和负面判断,同时在更普遍的技术水平范围内区分候选人。
即便是新手也应当能针对问题取得一些进展。最高级的候选人应当能快速找出他们没法当即解决的问题。
这种方法我从大学时代就开始使用,后来在业界用了二十多年。这种方法很是有效。
这种方法是什么?
协同设计系统的意思是与你的候选人共同设计一个工具、平台或项目。不须要写代码或伪代码,只须要讨论系统的设计思路和作出的取舍,还要提出这些取舍可能带来的问题,以及解决问题的方案。
这种方法之因此有效,是由于新手工程师和高级工程师之间的主要区别就是他们能预见到的问题的数量。凭借经验能够造就更强壮的系统设计,也能随时解决新问题。
怎样使用这种方法?
首先你的团队须要选择一个但愿候选人“构建”的项目(全部候选人应当使用同一个项目。长时间这样作,面试官就能作出更好的评价),本身作一次练习并计时。面试时要让候选人知道系统设计大概要花多少时间,并告诉他们不可能完成全部设计。他们应当提早了解预期的产出。
花上几分钟解释基本的需求。若是需求没法用几句话解释清楚,那可能不是个好项目。例如,你的项目能够是构建一个与某个著名的社交媒体平台类似的东西,好比你无需解释Instragram的工做原理。
事先提供一切你认为价值不大的东西。而后询问候选人他们但愿首先构建的部分。而后继续讨论新功能,直到时间用完。
若是候选人很容易就完成了这一切,那么能够提升复杂度。若是他们表现得很困难,就下降复杂度。
项目的难度可变,这样就能深刻了解候选人的技能水平。就像是对候选人水平作二分查找同样!
选一个项目
这项活动的关键就是需求必须易于理解。若是你公司的产品很出名,能够利用它作为起点。不然,选一个知名的网站(如Facebook)。项目应当与候选人入职后要作的工做相关。拿咱们来讲,咱们有两个项目,一个用于后端招聘,一个用于前端招聘。
后端项目的主要关注点是流行社交网络的底层系统。前端项目会提供一些简化了的产品功能截图,并询问候选人如何构建(组件怎么定义、组件间交互用什么方法等)。
示例:构建Facebook
首先,咱们会介绍任务。告诉候选人咱们要构建一个相似于Facebook的网站。咱们假设如今这个网站包含了用户、认证和一些其余功能。
此时,我会询问候选人怎样才能构建最小功能的Facebook。咱们喜欢这个问题,由于这个问题能看出候选人怎样考虑产品上的需求,也能够给以后的决策和取舍的讨论提供基础。
此时,我会使用白板记录下他们的想法。这样能使我参与其中,保证我以后能理解他们的设计。若是我理解错了,他们会当即注意到并纠正。
候选人可能会告诉我,最小功能集合包含好友、状态更新、新闻源,以及点赞的功能。问问他们挑选这个功能列表时的原则。是否漏掉了什么明显的功能?是否包含了没必要要的功能?他们的思考过程比功能列表自己更重要。而后,问问他们打算先作哪一个。假设候选人决定先作“好友”功能。
候选人会有不一样的想法。一些候选人可能会提出不可行工做的方案,但不该该剥夺他们的机会。最优秀的候选人应该能很快就完成这个阶段。
咱们假设候选人告诉我,他要建一个表来保存好友关系。这个表应该包含好友关系的发起人和接收者。
而后继续挖掘。在Facebook中的好友关系是双向的。怎样才能在数据库中表示?这种表示方法对系统设计有什么影响?
选择之一就是不须要作任何特别处理。查找给定用户的好友时用两列同时查找。另外一个选择是在好友数据库中保存两份数据,每一个数据表示一个方向。若是这样作,那么删除好友时要同时删掉两条数据。讨论二者的取舍。
下个话题多是如何处理好友请求。他们可能会选择在“好友”一栏添加一个“接受”按钮。他们可能会创建新的表保存好友请求。接下来能够讨论黑名单和垃圾请求等话题。
此时好友的话题基本上说完了,能够继续讨论下一个功能。随着新的功能不断加入系统,讨论各个功能之间的交互是件颇有意思的事情。
假如候选人无话可说也不要紧!你能够提出一种解决方案,问问他们的想法。这种方案的优缺点是什么?要是他们仍是不理解,能够试着讨论其余的功能。
这项活动中我最喜欢的地方就是它颇有意思。若是面试官表现很好,候选人也积极参与,那么最终整个面试过程可能不怎么像面试,而更像是一次与同事间就新项目进行的谈话。
而这正是候选人即将担任的角色。完美。
何时应该用代码面试?
尽管我很不喜欢代码面试,但有时候也有用:
肯定入门级程序员是否可以编程;
若是你的公司强制进行结对编程,那么在面试中进行结对编程能够当作是之后工做的预演;
一个角色须要许多特定的编程技能,而你没有太多时间去教他们,当你在两个高级职位名称之间举棋不定时尤其如此;
从代码面试到无代码面试的转变过程当中不要忽然转变,给本身一段转变的时间,能够帮你创建无代码面试的技能。
最后,若是团队的面试技能欠缺,就须要利用代码面试。代码面试的效果不太好,并且也有许多缺点。可是,它很是容易实施。即便是没有经验的面试官也能够很好地处理代码面试。
若是你正是这样的人,那么培养本身的面试能力应该是最优先的——雇佣错误的人是最昂贵的错误。
结论
只要一点点练习,你的团队就能在这种无代码面试中作得很好。他们能在较短的时间内作出更好的雇佣决策,并且面试也能招来更多的候选人。
我但愿这篇文章对你有帮助。若是有问题,请在评论区留言。但愿你能在下一次面试中干掉代码面试!