如何做一个好的面试
date
Aug 8, 2024
slug
interview
status
Published
tags
总结
技术
summary
今天正好面试了一个面试者,作为一个经验不是很足的面试官,也做了一些准备,这篇文章是作为自己在准备的过程中学到的一些准则的总结,我用一句话来总结下就是:把面试的人当做你未来的同事,看他怎么和你合作,用这个方式来面试
type
Post
今天正好面试了一个面试者,作为一个经验不是很足的面试官,也做了一些准备,这篇文章是作为自己在准备的过程中学到的一些准则的总结,我用一句话来总结下就是:把面试的人当做你未来的同事,看他怎么和你合作,用这个方式来面试
对于准则我觉得不可能写的比皓哥的更好,所以这里借用皓哥的一些观点:
- 只有应聘者真实和自然的表现,才能了解到最真实的东西
- 重要的不是知识,重要的是其查找知识的能力
- 重要的不是那个解题的答案,而是解题的思路和方法
现在大厂很多都把算法当做面试的硬门槛,所以就出现了不少公司和自媒体来教如何刷题通过面试,一些课程的价格会到几千甚至上万,但是在工作中是否真的有用,这个是要打一个问号的程
程序员到底是做技术的还是做工程的?
举两个例子,就可以感受一下其中的明显差异
- 一个例子是在 LeetCode 上刷题。不停地刷题可以让你对数据结构算法更熟悉,也能更熟练地用语言去解决一些小的技术问题。
- 另一个例子是在项目组里写 CRUD。如果从难度的角度判断,我想你肯定会觉得刷题对于技术的要求更高,而在项目中写 CRUD 的技术含量并不高。
在 LeetCode 上刷题时,通常会希望自己能在限定时间内尽可能快地、一次性地把代码写完。也就是说,代码写完就完成了,很少需要在此基础上进行二次开发或反复修改。以写为主,而改为辅,但是面对真实的业务需求,会涉及到不断的业务需求变更,没有明确的输入和输出,由于有了更多的外部因素和团队协作的影响,单纯的技术能力就不足以完全推进一个项目的进展,所以工程能力总结为:在团队协作环境下,长期稳定输出,并持续提高水平的能力。
工程能力第一个要求是我们怎样才能变成一个更好的 Team Player。工程能力的第二个要求是长期稳定。这与我们在 LeetCode 上刷题不同。在实际工作中,用多快的速度写完代码其实没那么重要,毕竟未来还需要修改。所以更重要的是,我们要写出更好改、更好读、更容易懂的代码。
面试的题目选择
上面解释了下真实的业务项目需要的工程能力,接下来就聊一下什么是好的面试题目,这段是引用了皓哥的文章:
- 操作。我们的面试官分不清楚什么是操作技能,什么是知识,他们甚至认为操作技能就是知识甚至经验。比如他们会 问如下的问题,请问Java中的 final是什么意思?怎么查看进程的CPU利用率?怎么编写一个管道程序?怎么查看进程的程序路径?VI中的拷贝粘贴命令是什么?包括面向对象的XX模 式是什么。等等。我以为,这些能够通过查况相关操作手册或是能够google到的东西只能说明这个人的操作技术,并不能说明他有知识或有经验。
- 知识。知识是一个人认知和学习的体现,可能会是一些基础概念和知识。比如这些问题:TCP和UDP的优缺点比 较,链表和哈希表的优缺点的比较。什么是堆什么是栈?进程间是怎么通信的?进程和线程的优缺点?同步和异步的优缺点?面向对象的XX设计模式的主要原则是 什么,等等。我以为,“知其然”只是操作技术,“知其所以然”才是真正的知识。知识不够并不代表他不能工作,会操作技能就可以应付工作,但是知识的欠缺一定会限制你的经验和能力,同样会影响你的开发质量。
- 经验。经验通常跟一个人的经历有关系。一个人的知识范围,一个人经历过的事,通常会成为一个人经验的体现。面 试中,我们会问这些问题:你解决过最难的问题是什么?你是怎么设计这个系统的?你是怎么调试和测试你的程序的?你是怎么做性能调优的?什么样的代码是好的 代码?等等。对于工作年限不长的人来说,经历和做过的事的确会成为其经验的主要因素,尤其是业务上的有行业背景的东西。但是,我更以为,经验可能更多的是你对知识的运用和驾驭,是你对做过事情的反思和总结,是你对他人的学习,观察和交流。
- 能力。一个人的能力并不会因为知道东西少而不行,也不会因为没有经验而没有能力。一个人的能力是他做事情的一种态度,性格,想法,思路,行为,方法和风格。只要有热情,有想法,有好的行为方法,以及好的行事风格,那么知识和经验对他来说只是一个时间问题。 比如:学习能力,专研精神,分析能力,沟通能力,组织能力,问题调查能力,合作能力等等。所以,对于一个新手来说,也许他的知识和经验有限,但并不代表他 能力上有问题,但是对于一个老手来说,如果其存在知识和经验欠缺的问题,那么通常都是其能力的问题。你可能暂时怀才不遇,但我不相信你会长期怀才不遇。如 果是的话,那么你必然些问题其让你的能力发挥不出来。而此时,“没有经历过”只会是你“没有能力”的一个借口。
在面试中,我们需要清楚的认识到,应聘者的操作技能,知识和经验只是其能力的必要条件,并不是充要条件,而我们更应该关注于应聘者的能力。
我的面试思路
因为我是一面,所以我将面试过程分成了三段,每一段考察的侧重点会有一些差异:
- 第一段是考察重构的能力:因为在开发过程中持续重构的能力是最重要的,所以这个题目不会很复杂,而是一个简单的函数,然后让面试者开始按自己的思路开始重构,第一版本写完之后开始讲解一下自己的思路,然后再引导面试者Review下代码看有没有什么问题,然后进一步的优化一下代码,这个过程主要是一个对齐和交流的过程,不用关注是否有语法错误,而是通过看重构代码的过程和面试者和你的交流过程来综合衡量下
- 第二段是考察代码基础:也就是写if..else的能力,这些题的Edge Case, Corner Case有很多。这些题需要你想清楚了再干,只要你稍有疏忽,就会有几个case让你痛不欲生,而且一不小心就会让你的代码会写得又臭又长,无法阅读。通过做这些题,可以非常好的训练你对各种情况的考虑,以及你对程序代码组织的掌控(其实就是其中的状态变量)。在写完这段代码之后,我会让面试者补充一下测试用例,看下对于这种Edge Case比较多的代码是怎么设计测试用例的
- 第三段是考察下OOP:这部分注重考察面试者的设计过程,因为设计题目属于开放型的题目,所以过程中是怎么做知识的提取、分析、以及接口的设计和扩展点的设计,哪些应该设计一个扩展点等等,这个过程会有大量的交流和沟通,我会一直问面试者一个问题,你是怎么考虑的?
不知道有没有看出来,我在这个过程中的题目都不会很难,不是特别注重结果是否是100%正确,而是更注重过程中面试者拆解问题的思路,因为工程归根到底来说是按照自己的思路把一个大的问题拆解为小问题,并且经过沟通将不确定的事情变得确定,通过一个一个小问题解决掉的过程,在解难题 的过程中考查应聘者的能力才是最终目的,而不是为难应聘者
我们知道,对于软件开发来说,开发软件不难,难是的下面是这些挑战:
- 软件的维护成本远远大于软件的开发成本。
- 软件的质量变得越来越重要,所以,测试工作也变得越来越重要。
- 软件的需求总是在变的,软件的需求总是一点一点往上加的。
- 程序中大量的代码都是在处理一些错误的或是不正常的流程。
所 以,当我们在考查应聘者的代码能力时候,我们为什么不能模拟这样的过程呢?比如,让应聘者实现一个atoi()的函数,实现起来应该很简单,然后 不断地往上加新的需求或新的案例,比如:处理符号,处理非数字的字母的情况,处理有空格的情况,处理十六进制,处理二进制,处理“逗号”,等等,我们要看 应聘者是怎么修改他的代码的,怎么写测试案例的,怎么重构的,随着要处理的东西越来越多,他的代码是否还是那么易读和清晰。如果只是考查编码能力,一个小时,就问这一个问题,足矣。真正的程序员每天都在和这样的事打交道的。
写在最后
刘未鹏在2011年发表了一篇文章:《怎样花两年时间去面试一个人》,里面提到了Github计划:
- 清晰、明确,完全可度量。
- 防伪:同样不担心“泄题”。你伪造不了GitHub历史,伪造不了check-in历史,review comments,文档,交流记录…
- 它不但是招聘,也是不花精力的培养。善哉善哉。
- 评估的责任很大程度上交给了应聘者自己。
从你的GitHub旅程开始,你就已经一脚踏进了真正的企业,而企业的面试也已经开始。
书单+GitHub,就相当于一个两年左右的面试。没有什么面试比持续两年的面试更具有信息量。
书单,加上项目,已经基本上覆盖了所需的全部技能。最妙的是,有太多的人在焦急的等待着他们未来的雇主给出明确的信号,他们想投入精力,去学习和实践,去成为企业需要的人,但是他们就是不知道往什么方向走,所谓有动力没方向。所以,雇主给出了清晰明确的要求,相信对于很多人来说反倒是一个解脱:“终于知道该干什么了”。《编程之美》为什么常居畅销榜?因为它透露了雇主眼中的需求,明确、清晰的需求,可以实现,并且知道怎么去实现的需求。
你提前两年就开始面试和培养未来的候选者,而且还不需要你花出一分精力,而且人家还很乐意,没有比这更完美的面试了。
后记
这篇文章大部分内容来自于「酷壳」,主要是结合自己的实践做一个记录,以后不管自己面试还是面试别人,作为一个行为准则