mirror of
https://github.com/cheetahlou/CategoryResourceRepost.git
synced 2025-11-19 15:43:44 +08:00
del
This commit is contained in:
158
极客时间专栏/geek/技术面试官识人手册/面试进行|实践篇/05 | 流程把控:控好流程,让面试进程高效有温度.md
Normal file
158
极客时间专栏/geek/技术面试官识人手册/面试进行|实践篇/05 | 流程把控:控好流程,让面试进程高效有温度.md
Normal file
@@ -0,0 +1,158 @@
|
||||
<audio id="audio" title="05 | 流程把控:控好流程,让面试进程高效有温度" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/eb/b1/eb316f35ee0da24964dcd819bee48cb1.mp3"></audio>
|
||||
|
||||
你好,我是四火。
|
||||
|
||||
“工欲善其事,必先利其器”,在专栏前面的部分,我们已经讲了怎样理解团队的需要,怎样做面试计划,以及怎样设计合适的技术问题,这些,可以说都是在正式面试之前需要搞定的事情。
|
||||
|
||||
今天这节课,我将会和你分享面试流程把控的基本思路,以及一些常用技巧。只有把控好流程,我们前面辛苦设计的面试计划、技术问题才能真正派上用场。
|
||||
|
||||
## 流程把控的反面例子
|
||||
|
||||
先来问一个开门见山的问题,究竟谁来把控面试流程,候选人还是面试官?
|
||||
|
||||
有人说是候选人,当候选人带着自由度表现的时候,才能发挥自己的实力;有人说是面试官,因为面试官需要按照预想,领着候选人来推进面试进展。
|
||||
|
||||
好像都有道理对不对?我卖个关子,先不回答这个问题,带着这个问题,我们来看看几个流程把控的反面例子。看看这些例子中,有没有你熟悉的。
|
||||
|
||||
### 收尾时间狂飙代码
|
||||
|
||||
这可能是一个一下就映入脑海的反面例子了,也是我见到的最多的一种流程把控的反面例子。
|
||||
|
||||
无论是由于问题过于复杂、沟通出现误会、候选人解决问题能力不强,或是候选人或面试官迟到等等原因,**到了白板编码环节,候选人有了思路,也开始写了,可时间快没了。**
|
||||
|
||||
这时候直接放弃吧,有点可惜,于是候选人就擦擦额头上的汗珠,颤抖地拿起记号笔,开始马力十足地在白板上狂奔,字也是越写越龙飞凤舞;而面试官呢,也颇为体谅,让下一位面试官在门外稍加等待,要求延期“就五分钟”,并不断提醒候选人时间越来越少。
|
||||
|
||||
最后,无论代码是否写完,面试匆匆结束,就仿佛一场大战结束,候选人累得瘫坐下来,这一轮的面试官一只脚刚迈出会议室,下一轮的面试官另一只脚就迈进来。若是代码基本写完了,候选人心里想,我去,真够紧张刺激,幸亏老子搞定了;若是没写完,可得失落和恍惚好一阵子。结束的时候,双方礼貌性地握手,手心满是汗。
|
||||
|
||||
### 寒暄时间占比不当
|
||||
|
||||
这里的“寒暄时间”,指的是技术面试中,正儿八经讨论技术问题以外的时间,一般发生在面试开始时和结束前。
|
||||
|
||||
一种极端情况是这个时间过短,甚至没有。候选人和面试官见了面,握个手,就开始做题,连个过渡都没有,让人觉得颇为唐突——“是不是这个团队都是老古板啊?”。
|
||||
|
||||
另一种极端情况是,打个招呼,互相介绍一下,聊两句感兴趣的话题,或是最近的热点新闻。扯扯淡,聊聊天,帮助候选人放松一下。本来这些都是挺好的“操作”,但问题是这个时间如果拖得太长,原本的技术考察重点就打了折扣。
|
||||
|
||||
我分享一个我shadow(观摩)的经历,有一位面试官在面试中和候选人“闲聊”,面试的一半时间过去了,候选人终于忍不住了,她主动问面试官,“咱们不谈点什么技术问题吗?还是继续这样随便聊吗?”,他们这才开始讨论技术。
|
||||
|
||||
考虑到在面试计划的时候,这位面试官是确定要考察算法和数据结构的,因此事后我问面试官,我理解这也是一种面试风格,可既然面试计划已经确定了,你为什么没有主导这个面试过程,让技术方面的讨论早一点开始?面试官回答说,他想看看候选人有没有足够的主动性主导这个面试过程。
|
||||
|
||||
对于这个案例,我的想法是,面试官这样做,虽然考察了他所关心的“候选人的主动性”这个数据点,但也使得这个面试偏离了原本的计划,也就是说,在我看来,确有所得,但得不偿失。
|
||||
|
||||
### 踌躇不定的思路选择
|
||||
|
||||
这个例子是来自于我自己。
|
||||
|
||||
一个问题往往有很多解决的思路,有一次,候选人和我讨论某个问题的算法,这个过程一开始还挺顺利,候选人选择使用Map+数组排序的思路做,方案虽然略有一些硬伤,但是也行得通;期间他忽然想到,使用一个二叉搜索树数据结构的思路更好,于是我们又放弃了前面的思路,沿着这条路推进;结果忙活到一半,他忽然再一次“恍然大悟”,觉得可以用一个Map+链表的方式来做更简单。
|
||||
|
||||
这整个过程其实没有太大的问题,整个思路的转变,反映了候选人很好的思考能力,能够跳出具体实现,重新审视问题。
|
||||
|
||||
但是由于这一系列的思路调整耽误了太长时间,导致到面试结束的时候,我们只讨论了思路,连完整的方案都没有讨论清楚,自然原本计划的编码根本没有时间开展。从考察角度来说的话,我们就丢失了相当一部分考察项的覆盖。
|
||||
|
||||
## 流程把控的技巧
|
||||
|
||||
不知道刚才那几个例子是否给你带来了似曾相识的感觉?其实这些反例说到底还是因为流程把控没做好。
|
||||
|
||||
那既然如此,下面我就来正面谈一谈我的理解,带你一起看看有哪些流程把控的技巧。这些技巧能够帮助我们在面试中,**保证最核心的考察项能够覆盖到,同时,还能够给候选人留下一个好印象。**毕竟,如同我们在专栏前文中所说,面试是“双向”的。
|
||||
|
||||
### 有头有尾,有礼有节
|
||||
|
||||
首先我要谈的,不是什么复杂的技巧,而是礼节。
|
||||
|
||||
什么,礼节?对,你没有看错。我认为,面试官有义务确保考察过程的完整性,这能让候选人心情愉悦,在友好的氛围里完成面试的过程。
|
||||
|
||||
不知你是否听说过,有一些面试的风格颇为激进,甚至不尊重人,观察候选人在极端压力下的表现。也许这确实可以让面试官得到他想要的考察数据,但我认为这是非常不妥的。
|
||||
|
||||
**面试,说到底是社交活动的一种,我们必须建立在平等和尊重的基础上,我们要达到目的,但不能不择手段,因此在我看来,这就是一个根本性的错误。**
|
||||
|
||||
我觉得面试就有点像是江湖上相逢,缘分一场,我们客客气气地切磋武艺,点到为止,你我互相尊重,为的也是来日好再相见。
|
||||
|
||||
面试应该做到有头有尾,在面试开始时,我们可以:
|
||||
|
||||
- 礼貌地打招呼、握手,邀请候选人坐下,问问今天感觉怎么样,如果迟到了要表示歉意;
|
||||
- 询问候选人是不是需要休息两分钟,是不是需要喝水,是不是需要使用洗手间,在不少互联网大厂的面试培训里,这一条都被反复提到;
|
||||
- 做自我介绍,这个自我介绍可以很简单,一两句话概括,但是让彼此认识的环节不能少;
|
||||
- 可以简单提一提,在今天的面试中可以预期的内容,这样候选人会有个心理准备。
|
||||
|
||||
而在面试结束前,我们可以:
|
||||
|
||||
- 表示问题的讨论告一段落,留给对方问问题的机会,表示在自己力所能及的范围内将努力回答对方的问题;
|
||||
- 对于候选人的到访表示感谢,可以赞许一下今天的讨论,也可以对他后续的求职过程表示祝愿;
|
||||
- 礼貌地握手、告别。
|
||||
|
||||
对于电话面试,或者是特殊时期的线上面试,不能握手了,可上面大部分礼节还是一样的。上述这样的过程也许用不了5分钟、10分钟,但是面试的整个过程显得自然、得体,并且也能够帮助候选人放松。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/c3/59/c3d082c6aca9927c420387ab7d3eda59.jpg" alt="">
|
||||
|
||||
你看,这些有什么特别的技巧吗?完全没有,**上面这些哪是在说面试啊,其实只是礼仪之邦的待客之道对不对?**
|
||||
|
||||
没错!其实,要做到上面这些,只需要细心,并不需要多么高深的技巧,但是却能够令候选人大大提升印象分。还是那句话,面试是双向的。面对多家竞争对手的时候,你肯定希望优秀的候选人能够选择你的公司和团队。
|
||||
|
||||
我说一个我自己的故事,那是在好几年前了,我在找工作期间,在国内几个城市都面试了几家公司,只有当时在北京的亚马逊,面试的过程中,面试官主动给我倒水,面试完毕后送我离开(当时需要上出租车,赶去机场)。且不说面试的内容,这些细节给了我非常正面的印象,我相信无论业务和技术怎样,面试我的团队至少是非常懂得尊重人的。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/bd/3d/bdbf2db9d7304e3b592c63e82430d13d.jpg" alt="">
|
||||
|
||||
### 做一个完整的项目
|
||||
|
||||
对于技术面试而言,**面试官要抱着和候选人一起做一个有头有尾的迷你项目的心态。**
|
||||
|
||||
这里,“迷你项目”这四个字可以说是重中之重,即所谓“麻雀虽小而五脏俱全”。这个问题的解决过程要完整,从需求澄清,到分解、设计、抽象、落地、验证、改进,有头有尾。
|
||||
|
||||
举例来说,前文所谈到的这个网约车的问题,我们考察的是数据结构和算法,在代码层面“落地”的思路沟通清楚以后,就可以写白板代码了。
|
||||
|
||||
在代码完成后,候选人可以使用一个简单用例走读代码,验证正确性。再之后,面试官还可以提出“follow-up”问题,比如聊一聊有什么瓶颈,怎么改进。
|
||||
|
||||
好,我想从中你可以看到这样一个完整的过程,而**理想的面试,确实也不应该在中间的某一个过程戛然而止。**
|
||||
|
||||
比方说,如果代码实现的思路讨论清楚了,但是因为没有时间完成代码实现,想必候选人也会觉得沮丧;而只有一个完整的过程,才会让候选人如释重负,有一种“项目完成了”的成就感。
|
||||
|
||||
举例来说,一个模糊的问题,一个代码层面考察(例如算法和数据结构)的路径,一轮面试总时间为1小时,而去除寒暄和收尾的环节,核心时间为50分钟,那么可以参考这样一个时间分配的思路:
|
||||
|
||||
- 10分钟澄清问题,厘清面试中需要实现的需求,细化到可讨论实现的层面;
|
||||
- 15分钟分析、讨论该需求抽象后的问题,这些问题必须是软件可解的,比如该使用怎样的数据结构和算法来解决,时间、空间复杂度各是多少;
|
||||
- 15分钟现场编码;
|
||||
- 5分钟使用实际用例走读代码,验证正确性;
|
||||
- 5分钟讨论算法的优化,以及进一步的改进空间。
|
||||
|
||||
你可能会问,现场编码只有15分钟,这么短的时间,够吗?
|
||||
|
||||
够。这里我必须说明的是,**在编码前,我们期待候选人和面试官已经将思路大体上沟通清楚了**,那么这个编码过程,其实只不过是一个将思路“翻译”成代码的过程而已。
|
||||
|
||||
我们在编码前对于思路和逻辑的讨论,目的就是要保证编码能够顺利进行,所有的关于“problem solving”的部分基本已经解决,于是就只剩编码过程。
|
||||
|
||||
值得注意的是,编码前的思路和讨论,以及编码本身,我们考察的侧重点是不一样的。比方说,有的候选人就是具备很强的逻辑能力,来解决问题,但是就是无法将思路落实到代码上。因此,别看过程很短暂,却是不可缺少的。
|
||||
|
||||
你可能也注意到,在需求确认以后,很多候选人都喜欢上来就立马落笔写代码,但作为面试官来说,是不是可以落笔,需要着重关注候选人是不是已经有了清晰的思路,否则很可能浪费时间。这样急于落笔也很难一蹴而就,来回涂改,会做很多无用功。
|
||||
|
||||
如果你留意到,候选人即便有了清晰的思路,在基础编码能力具备的情况下,代码的实现依然要花费超过15分钟,那么你就应该考虑调整这个问题的设计了,是不是要求代码实现的部分过于复杂,从而最终导致在限定时间内,整个问题的解决流程无法完成。
|
||||
|
||||
如果是这种情况,**我们可以要求只实现代码片段,例如算法的核心部分,或者是涉及到的几个重要的类,而不是整段代码。**通过这种方式,我们可以将预期的编码时长降下来。
|
||||
|
||||
举例来说,如果实现一个完整的LRU缓存颇为耗时,那么算法实现可以要求写出数据结构,以及其中缓存更新的部分。
|
||||
|
||||
另外,你可能还听说过,在有些面试中,面试官会在一轮面试中,要求实现两个较为简单的算法。这种情况确实有,但是我一般是不推荐的,原因就是,这整个问题的讨论和解决过程已经颇为耗时了,很难在一轮面试中覆盖一个以上的算法实现。
|
||||
|
||||
如果硬要塞进两个算法题的实现,那就要问非常简单的问题,那么,即便勉强做到了,用意又何在呢?
|
||||
|
||||
### 选择合适的介入时机
|
||||
|
||||
还记得这一讲一开始,我开门见山地问的那个问题吗?“究竟谁来把控面试流程,候选人还是面试官?”
|
||||
|
||||
我打个比方,一个国家的经济活动有强有弱,走势有高有低,通常情况下,从大体上看,市场经济可以自然地发展,但是在某些特殊环节,或者极端情况下,国家需要介入,需要调控。
|
||||
|
||||
面试也是如此。我认为,在核心时间中,面试官应该关注于大的层面上,是不是能够顺利完成今天的考察内容,是不是能够得到自己关心的考察数据。
|
||||
|
||||
**如果候选人能力很强,对于问题的推进合理有效,那么面试官就要学会做“绿叶”,给对方更多的发挥空间,让对方去主导问题的解决**,这当然是最理想的情况,候选人能跟着自己的计划走,自然也最舒服。
|
||||
|
||||
反之,如果遇到了困难(还记得我们[上一讲](https://time.geekbang.org/column/article/362407)在“设定‘踮踮脚能够到’的最高难度”部分,谈到的降低难度的方法吗?),或者看着路线要“跑偏”,或者时间进度已经大大落后,那么面试官就要毫不犹豫地及时介入,主动调控,从而保证整个方向和时间的可控。
|
||||
|
||||
## 总结与思考
|
||||
|
||||
好,今天我们开始讲怎样主导技术面试,把控流程了,既谈到了一些常见的反面例子,又介绍了我们应该掌握怎样的技巧,完成一个成功的技术面试。
|
||||
|
||||
在这一讲的最后,我想再次强调“互相尊重”的重要性,虽然我不会在专栏中再反复强调它,但请记得它是我们面试等一切职业行为的最基本要求。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/c6/5a/c645fc40bd37578b2aac0eef5fc7f85a.jpg" alt="">
|
||||
|
||||
最后,我有一个问题,正在阅读的你,能否在评论区和大家一起聊一聊,你作为候选人参与过的面试,都有哪一些有意思的细节呢?期待你的分享。
|
||||
|
||||
好,我是四火,我们下一讲见!
|
||||
204
极客时间专栏/geek/技术面试官识人手册/面试进行|实践篇/06 | 算法和数据结构考察:怎样有层次地驾驭算法考察?.md
Normal file
204
极客时间专栏/geek/技术面试官识人手册/面试进行|实践篇/06 | 算法和数据结构考察:怎样有层次地驾驭算法考察?.md
Normal file
@@ -0,0 +1,204 @@
|
||||
<audio id="audio" title="06 | 算法和数据结构考察:怎样有层次地驾驭算法考察?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/c8/18/c84b65f1d39423f21146bb8689b99b18.mp3"></audio>
|
||||
|
||||
你好,我是四火。
|
||||
|
||||
在上一讲中,我们学习了从整体上怎样做流程把控,那么从这一讲我将针对技术面试中最常见的考察重点,做进一步的展开。
|
||||
|
||||
为了让你系统地学习,我会根据常见的技术考察重点分类,从数据结构和算法,系统设计,面向对象、测试和其它工程技能,以及行为面试这样几个部分分别介绍。
|
||||
|
||||
每一部分,我都会从反面列举一些典型的不当实践,再从正面分享一些考察技巧。今天要讲的是数据结构和算法的部分,除去上述内容,我在最后还给出了一个模拟案例,帮助你完全理解进行算法和数据结构考察的过程。
|
||||
|
||||
首先我要说明的是,今天这一讲开始的这些阐述,都不是针对一个完整的面试过程展开的,而是从整个过程中,提炼出最能够体现考察重点的其中几个步骤。如果你不清楚一个完整面试过程应该怎样去把握,可以回看前几讲。
|
||||
|
||||
## 糟糕的例子
|
||||
|
||||
我先说几个典型的、糟糕的例子,可以说,数据结构和算法恐怕是技术层面最常见的考察点了,所以,所谓的不当操作,也出现得最多。
|
||||
|
||||
### 闷头编码
|
||||
|
||||
在我见到的编码面试中,这一点可以说是出现得最为频繁的问题。请你联想实际工作,如果你的团队中有这样一个工程师,拿到需求以后,不确认问题、不沟通设计、不讨论方案,直接就开始埋头苦干,就算能写出可以工作的代码,这是不是依然是一件无比恐怖的事情?
|
||||
|
||||
显然,**我们的面试一大目的就是排雷,就是要尽可能避免这样的事情在实际工作中发生。**毕竟我们要找的是软件工程师,不是只会刷题的编码者。
|
||||
|
||||
在专栏前面的几讲,我已经反复讲到了,我们怎样去设计问题,怎样层层推进,而不要上来就编码。
|
||||
|
||||
但事实上,据我观察,我相信**大部分具备技术背景的面试官都非常清楚,闷头编码“不好”,**但往往还是由于缺乏主动、坚决介入的决心,在这种情况下听之任之。作为面试官,我们不要去想当然地认为,这只是候选人自己应该意识到的问题。
|
||||
|
||||
### 只写伪代码
|
||||
|
||||
你也许会对这一点不以为然,为什么只写伪代码不行?伪代码和实际代码能差多远?
|
||||
|
||||
从工程的角度说,它们差得很远。**伪代码,其实说到底,只是问题解决逻辑的其中一个表达形式而已,**或者说,不写伪代码,也可以用作图、文字描述等等方式将逻辑表达出来。
|
||||
|
||||
我们不反对候选人写伪代码,如果这能帮助他理清思路,那为什么不呢?但作为数据结构和算法面试的一个核心,候选人不能只写伪代码。
|
||||
|
||||
那么我们就再说说代码。从代码可以看出编码能力,这是软件工程师最最基本的工程技能。就好像造房子,图纸上可以设计得清清楚楚,而编码就是根据图纸把房子造出来、把方案真正落地。编码能力,从本质上说,就是将思路、逻辑工程化的能力。
|
||||
|
||||
从编码可以看出工程思维是不是严谨,是不是各种corner case都考虑到了?是不是具备编程语言功底,能够比较流畅地将思路转化到具体实现上?是不是能够比较好地组织代码,方法设计合理,层次结构清晰,变量命名一致?是不是具备良好的面向对象思维和模块化思维?
|
||||
|
||||
有了具体代码以后,我们还可以进一步给面试中这个迷你项目收尾,比如讨论一下对于实现的代码,怎样使用测试去覆盖,哪些地方容易出现瓶颈,哪些地方可以进一步优化等等。从这里可以看出,实际代码的作用非常之大,别的形式都无法代替。
|
||||
|
||||
事实上,我本周刚刚面试了一个职业经历很丰富的软件工程师候选人,他做过产品经理,做过解决方案工程师,最近的一份工作是咨询师。
|
||||
|
||||
他的面试其它表现基本可以说还不错,但就是几乎没有编码能力。最后我们给了他一个进行其它职位评估的可能,但毫无疑问的是,软件工程师的岗位,恐怕他是很难胜任的。
|
||||
|
||||
### 纠结编码细节
|
||||
|
||||
不同的编程语言,有不同的库函数、API可以调用,但是有的时候候选人记不太清楚。比如说,对于Java的Queue接口来说,往队列里面添加一个元素可以用offer(),或者用add(),我注意到很多候选人都不清楚这两个的区别,甚至有用push()的。有时候候选人就很沮丧,觉得这是一个大错。
|
||||
|
||||
但在我看来,这完全不是什么问题,属于“知道最好,不记得也没什么大不了”的小记忆点而已,它并不能左右我们对于候选人整体的评估。我遇到这种情况时,为了避免候选人担心,往往会主动向其说明。
|
||||
|
||||
类似地,有时候我们能见到候选人纠结于某一个变量的命名,把A改成B,觉得不好,又改成C,过一会又回来把它改回A。
|
||||
|
||||
这样的“纠结症”真的非常常见,我们当然要关心变量的命名,是不是一致、是不是具体化、是不是符合实际的意义,但是归根结底,**我们需要帮助候选人把最多的编码时间精力花费在最核心的代码逻辑上,不要让他们捡了芝麻,丢了西瓜。**
|
||||
|
||||
## 考察技巧
|
||||
|
||||
好,前面我们从反面列了一些典型情况,它们都发生在数据结构和编码的考察过程中,它们也都说明,面试官本可以帮助候选人在这样的面试中给出更充分、更客观的,关于编码能力的数据点,不知道你是否也有相似的经历呢?
|
||||
|
||||
下面我从正面介绍几个考察技巧。这些内容来自我的经验,这里选了面试比较常见和常用的,但如果你有希望补充的场景,或是遇到了具体问题,也欢迎在评论区提出来。
|
||||
|
||||
### 白板编码
|
||||
|
||||
一直有争议的白板编码必须得放在第一条。
|
||||
|
||||
现场的白板编码好不好?老实说,不好。面对什么都没有的白板,候选人压力大,也没有工作中IDE能够带来的方法提示,还需要考验候选人的握笔和书写能力。
|
||||
|
||||
但是,我依然觉得,**白板编码是如今这些现场编码考察的操作方式中,最公平、最直接,且最有效的一种方式了,**这有点像高考。
|
||||
|
||||
和使用IDE编码比,它更为公平、统一,所有候选人都是一样的,而且候选人往往更放得开、参与性强,在白板上讨论问题可以说是非常高效;和使用白纸相比,除去前述优点以外,还便于涂改。
|
||||
|
||||
当然,现在疫情期间,或是电话面试的原因,如果白板不方便,那么一些在线的编码工具也是一个折中的方案。
|
||||
|
||||
白板编码的过程中,作为面试官,我们要扮演一个怎样的角色呢?我们不光要做候选人的同事,一起讨论问题,我们还需要在必要的时候介入,推进问题的解决,或是帮助候选人进行时间管理。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/11/30/1105ebd314ec37893465f73583d1a630.jpg" alt="">
|
||||
|
||||
### 追随候选人的思路
|
||||
|
||||
在思考数据结构和算法这一类问题的时候,我观察到,有很多不同的思维方式。比如说,有自上而下的,也有自下而上的,有按照递归思考的,有按照循环思考的。
|
||||
|
||||
作为面试官,只要思考是向着大体正确的方向,我们的**优先选项一定是顺着候选人的思路走,一起讨论,即便这样的思路不是最佳的。**
|
||||
|
||||
在有了思路基本清晰了以后,如果时间充裕,且候选人显示出具备挑战更好的解决方法的能力,那么我们可以再进一步挖掘,看看能否在给出一定提示的前提下,促使候选人更进一步,找到一个更好的解。
|
||||
|
||||
但是如果觉得继续前进比较困难,或者看起来要花费较多的时间,我们可以立即收手,告诉候选人“我们一会有时间的话再来讨论这个思路”,先回归到他原来的思路上去。
|
||||
|
||||
我们经常能够听到一些面试“箴言”说:如果你无法给出最优解,那么至少也给出一个解,哪怕是一个暴力解,也比没有解要强。这道理朴素且正确,但我们要清楚的是,这件事情不能完全依赖于候选人,期望他自己就能意识到,还需要面试官引导。
|
||||
|
||||
## 模拟案例
|
||||
|
||||
好,在正反两个角度都谈过之后,我们讲一个模拟案例。比如有这样一个问题:
|
||||
|
||||
>
|
||||
某社交网站有两千万的注册用户,每个用户都有积分属性,且根据在线用户在社交网站上的行为,积分会有小幅度的变更(比如登录一次就+1分,评论一次就+2分等等,每次不超过3分),在线用户还需要频繁地获取自己在所有用户中基于积分的排名,那么,要设计一种什么样的算法,才能**高效、准确、实时**地获取指定用户的排名呢?
|
||||
|
||||
|
||||
这个问题描述有两个关键字:“准确”和“实时”,如果没有这两个词的限制,那么很多“模糊准确”的方法都可以采用,说白了就是牺牲一致性的方法,比如异步、定时的排序,就些是最容易想到的方案。
|
||||
|
||||
如果候选人具备更进一步的能力,我们就可以尝试,能否在满足这两个修饰词限制的情况下,找到好的实现方案。
|
||||
|
||||
接下来,我会列举一个详细的对话片段,我们来看看面试官怎样和候选人一起讨论,逐步推进模拟案例中这个积分排序问题的求解。
|
||||
|
||||
**第一阶段:简单排序**
|
||||
|
||||
候选人:我觉得问题的解法就是,在每次需要获取排名的时候,根据用户的积分,对这两千万个用户进行排序。
|
||||
|
||||
面试官:好,这样的方式下,对于每次排名的获取,时间、空间复杂度是多少?(要求澄清)
|
||||
|
||||
候选人:用户量是n的话,时间复杂度是n*log(n)……(说着说着自己意识到时间复杂度较大)
|
||||
|
||||
面试官:对了,如果说这个时间复杂度我们无法接受,你能否优化这个效率?(给出挑战)
|
||||
|
||||
候选人:……(提出了一些排序的优化思路,但是他自己对它们的效率也不满意)
|
||||
|
||||
**第二阶段:维护用户的有序数组**
|
||||
|
||||
面试官:好,为什么这些思路的效率都不令人满意呢,就是因为这个排序对不对?如果在需要获取排名的时候,才给那么大的数组排序,看起来就很难高效了。(给出挑战)
|
||||
|
||||
候选人:对了,可以让数据一直是排好序的!这样就不用在获取排名的时候现排了。
|
||||
|
||||
面试官:嗯,是一个挺有意思的方向,那你怎么设计这个机制呢?(要求澄清)
|
||||
|
||||
候选人:我可以使用一个map来保存用户ID到排序记录的映射,再把所有用户的记录,根据积分从大到小按序放在数组中,这样二分查找就可以找到对应积分所处的排名。
|
||||
|
||||
面试官:能举例说说吗?(要求澄清)
|
||||
|
||||
候选人:你看下面这个图,左边是一个map,右边是一个数组。用户(ID=6)通过数组下标index找到对应的在右边数组中的记录,积分是12345,和用户(ID=7)的积分相同,排名也是相同的3337;而用户(ID=8)的积分是545,排名是65654。
|
||||
|
||||
面试官:了解了,很不错的想法。那么这时候获取排名的时间复杂度是多少?(要求澄清)
|
||||
|
||||
候选人:Map映射的复杂度是O(1),找到右侧数组中的记录,也就找到了排名,所以整体的时间复杂度是O(1)。
|
||||
|
||||
面试官:嗯,那每当用户的积分小幅变化的时候,你怎么保持这个数组依然有序?(要求澄清)
|
||||
|
||||
候选人:更新一下这个积分,然后再调整一下这个记录在右侧数组中的位置。
|
||||
|
||||
面试官:这个变更影响的数据量有多少呢?(要求澄清)
|
||||
|
||||
候选人:影响的数据量取决于积分变化幅度,对于积分是12345的这条记录,如果积分+3,那么就可能影响所有积分从12345到12348的用户。
|
||||
|
||||
面试官:不错,那么这些受影响用户,对应右侧表中的index都可能会发生改变,你怎么去更新左侧map中的记录呢?(要求澄清)
|
||||
|
||||
候选人:哦,那就需要在右侧数组的每一条记录中,增加一个用户ID,这样对于任意一条发生更新的记录,就可以以O(1)的时间复杂度找到左侧map中的记录来更新。
|
||||
|
||||
**第三阶段:维护积分的有序数组**
|
||||
|
||||
面试官:好,现在,假设说新注册用户很多,可能会有大量的用户拥有相同的积分,比如只有1分,或者2分这样非常小的数。那样的话,如果这些用户的积分有一点微小的变化,就会引起排名的剧烈变化,于是右侧数组中大量数据的移位——这个问题,你能否解决?(给出挑战)
|
||||
|
||||
候选人:……有了!使用积分关联,而不是单个用户数据来关联——左侧map只存放用户ID和对应右侧数组中积分记录的下标,右侧数组只存放积分对应的排名,这样每次小的积分变更,只需要根据下标往上、往下找几条记录就可以了,因此影响的行数就非常少了,并且右侧数组的更新也不需要改变左侧map。
|
||||
|
||||
面试官:能举例说说吗?(要求澄清)
|
||||
|
||||
候选人:你看下面这个图,左边map的用户(ID=6)和用户(ID=7)都有12345分,都指向了下标是1220的数组记录,因此在右侧数组的第1220条记录中就找到了排名。下标是1221的排名比相邻的1220的排名高了2,说明有两个用户的积分都是12345。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/f5/9c/f514a1f9895aee861651a2da6784d09c.png" alt="">
|
||||
|
||||
**第四阶段:维护积分的有序链表**
|
||||
|
||||
面试官:很好,可右侧的数组里面,积分的出现并不一定是连续的,因此这个方法会带来一个问题,你能想到吗?(给出挑战)
|
||||
|
||||
候选人:……(思考)
|
||||
|
||||
面试官:比如说,上面的例子,右侧数组里面,用户(ID=6)增加了1分,12345变成了12346,而12346又不存在,会出现什么问题?(给出挑战)
|
||||
|
||||
候选人:哦,如果积分变化以后,新的积分是没有出现过的,那么添加到数组里,就是一个新元素,于是所有比它小的积分,其所在的数组元素全部都要向后平移(shift)一个单位,这样的错位导致左边的map和右边的数组中的元素都要大量更新。
|
||||
|
||||
面试官:非常好,那么你怎么优化?(要求澄清)
|
||||
|
||||
候选人:如果使用链表代替数组,就可以解决这个问题了。把通过数组下标的关联,改成通过链表元素引用的关联。因此,我需要一个双向列表,这样积分新增或减去一个小的变化量的时候,就可以快速完成更新了。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/20/b8/205479e893207743540bffc5429523b8.png" alt="">
|
||||
|
||||
**第五阶段:Follow-up问题**
|
||||
|
||||
对于上面这个问题,在讨论清楚思路以后就可以写代码了,如果编码顺利,还可以继续follow-up问题的挑战,比如:
|
||||
|
||||
面试官:由于某个原因,我们一次赠送给一批量用户十万积分,也就是说,我们讨论的这个积分变化的增量,如果非常大,那么在右侧链表中可能影响的数据量也非常大,这种情况有没有办法优化?(给出挑战)
|
||||
|
||||
候选人:……(这一步也有很多可行的思路,比如有用跳表的,有用线段树等解法的)
|
||||
|
||||
以上,问题其实有很多解法,而**这个具体的问题与解法不是最重要的,最重要的是,****我希望通过刚才的例子把这个互动的模式交代清楚。**
|
||||
|
||||
你可能已经发现了,面试官最重要的话基本可以分成下面这两类:
|
||||
|
||||
- 给出挑战:接着既有的内容,提出新的问题,增加新的限制,给候选人创造新的挑战;
|
||||
- 要求澄清:基于候选人的陈述,要求进一步解释问题,细化解决方法,或者给出实例。
|
||||
|
||||
候选人往往就是这样在面试官给出挑战,或者是要求澄清的反复引导下,一起分析思考,逐步推进问题的解决。
|
||||
|
||||
实际这个过程并不一定那么顺利,或许也只能抵达到其中的某一步位置,但是我们的难度控制,是希望最终候选人能抵达一个“踮踮脚能够到”的位置(我们在[第4讲](https://time.geekbang.org/column/article/362407)已经谈到过),并至少有时间完成核心代码。
|
||||
|
||||
如果你觉得意犹未尽,我在《全栈工程师修炼指南》的[第36讲](https://time.geekbang.org/column/article/173359)中,介绍了一个流量控制问题如何从算法角度层层推进,你可以继续做拓展阅读。
|
||||
|
||||
## 总结与思考
|
||||
|
||||
好,今天的内容主要就是这些,我列出了算法和数据结构考察的一些反面实践,并结合自身经验推荐给你一些考察技巧,最后还通过一个模拟案例,帮助你理解这个过程。
|
||||
|
||||
在这个过程中,我们需要用**“给出挑战”和“要求澄清”**两种方式,不断地推进问题的解决。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/a0/85/a086235e65408da7b25f3759ea138585.jpg" alt="">
|
||||
|
||||
在最后,我想问一个问题,对于算法和数据结构的考察,都有哪些你觉得很有价值的技巧,或者有哪些需要避开的坑,你能否在留言区谈一谈呢?我会就你的想法和问题和大家一起讨论。
|
||||
|
||||
好,我是四火,我们下一讲见!
|
||||
241
极客时间专栏/geek/技术面试官识人手册/面试进行|实践篇/07 | 系统设计能力考察:系统设计内功到底怎么考?.md
Normal file
241
极客时间专栏/geek/技术面试官识人手册/面试进行|实践篇/07 | 系统设计能力考察:系统设计内功到底怎么考?.md
Normal file
@@ -0,0 +1,241 @@
|
||||
<audio id="audio" title="07 | 系统设计能力考察:系统设计内功到底怎么考?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/f4/4f/f46db6fd5322b1a4b44f39fdf63a1c4f.mp3"></audio>
|
||||
|
||||
你好,我是四火。
|
||||
|
||||
在上一讲,我们谈到对于数据结构和算法部分考察的把控,这一讲,我们来聊聊系统设计。
|
||||
|
||||
我们经常说软件工程师要注意积累工作经验,那么,年复一年的工作中,我们到底积累了哪些技术方面的经验?
|
||||
|
||||
我想,其中很重要的一个就是对于系统的理解。对于刚毕业和工作不久的工程师来说,我们不应苛求他们对系统具备相当深度的理解;另一方面,即便工作年数相同,不同候选人对于系统的认识深度也有着非常大的差距。
|
||||
|
||||
和能够明确判断出正误的算法类问题不同,系统设计我们往往没法给出丁是丁卯是卯的正误判断,因而面试中讨论的更多是可行性,以及对于不同实现方案的利弊权衡。这也是符合现实逻辑的,有一些相似的系统,它们的实现技术截然不同,有着不同的优势和短板,但是最终都解决了最核心的问题。
|
||||
|
||||
## 糟糕的例子
|
||||
|
||||
好,我们先来说几个典型的反面例子,和算法、数据结构的面试不同,系统设计的面试往往能遵循的简单套路更少,因而也能见到更多的“踩坑”实践。
|
||||
|
||||
### 排斥不一样的思路
|
||||
|
||||
最典型的例子就是面试官缺乏包容心。就像“看自己的代码越看越开心,看别人的代码越看越糟心”一样,在讨论一些经典系统设计思路的时候,如果对方的思路和常规思路明显不同,**某些面试官可能会立即觉得对方的想法很“奇葩”。**
|
||||
|
||||
**这种想法其实是非常危险的,因为面试官在心里默默建立了一个护城墙,凡是不符合“标准”的解决思路,都会产生排斥心理。**
|
||||
|
||||
下面我举一个具体例子说明吧。有一次,某位面试官和候选人讨论,怎样设计一个篮球比赛的文字直播系统。
|
||||
|
||||
这个系统需要实时显示当前的比分等信息,那么一种思路是使用普通的查询,客户端主动发起,即定时地不断询问服务端最新的比分;还有一种思路是使用长连接,或者long poll这样的机制,使得服务端可以更实时地推送最新的比分更新。
|
||||
|
||||
很多系统都采用后者的思路来实现,这主要是基于实时性等方面的考虑,但是当时候选人考虑使用前一种方案。于是,面试官就直接中断了他的陈述,并直接解释为什么应该选择后者。
|
||||
|
||||
暂且不说所谓的正误,或者好与不好。这个技术实现选择的不一致,本来可以引出一个很好的面试实践,也就是对两种实现机制的利弊做讨论,但很遗憾,这种打断的做法直接终止了这样的讨论。
|
||||
|
||||
也就是说,我们完全可以跟着候选人的思路,用上一讲提到的“要求澄清”的办法让他自己来分析出实现的利弊来。
|
||||
|
||||
之后,如果候选人自己意识到,或者面试官使用“给出挑战”这样的办法,通过讨论这个方案的不足,来引出后一个方案,并放到一起进行优劣比较。
|
||||
|
||||
这样一来就可以有比较多的讨论与互动,我们也能得到更多的关于候选人对于系统理解的数据点。我想强调的是,最后采用哪一个方案其实并不重要,重要的是这个过程和我们得到的考察数据。
|
||||
|
||||
还有种类似情况是,**有时候选人对于系统的设计思路是自底向上的,而面试官则是自上而下的。**
|
||||
|
||||
一般说来,自底向上去思考和设计系统的时候,确实存在“捡了芝麻丢了西瓜”的情况,但是如果面试中候选人这么做,我们不要去打断他,或者破坏他的这种思维模式,而要顺着他最熟悉的方法来讨论这个问题。
|
||||
|
||||
我们做系统设计面试的目的,是要考察候选人对于系统的理解,抓住一些有意义的数据点,而不是要尝试去把系统设计做到最好。
|
||||
|
||||
换言之,**我们在面试中,一定要摒弃掉所谓的“最佳设计”或者“推荐方案”这样的想法,而是尽量追着候选人的思路跑!**
|
||||
|
||||
最后设计出的系统也许有这样那样的问题,但请记住面试官可以主导面试,却最好不要主导设计——完成的系统一定是一个候选人主导设计的系统,而不是面试官。
|
||||
|
||||
### 无意义的深挖
|
||||
|
||||
我们当然可以针对系统的某一个点进行深挖,但是如果候选人已经暴露出,他还不具备深挖该问题的基础知识,那么这个继续深挖很可能就是徒劳的,因为它除了给候选人带来沮丧以外,并不能得到太多更有价值的考察数据点。
|
||||
|
||||
举个例子,有一位面试官和候选人一起讨论“短URL系统”的设计问题。其中一个点是,在做短URL重定向的时候,返回码应该选择301还是302?
|
||||
|
||||
302是临时重定向,301是永久重定向,虽然301可能会减轻一定的访问压力,但通常来说,我们一般都选择302。这里的原因是,这些系统有一个很大的价值就是可以获取用户的访问数据,使用301可能会使得用户后续的访问直接跳过了这个系统,而去访问重定向后的系统,这样,这些有价值的URL访问数据就丢失了。
|
||||
|
||||
但是,当时候选人只对HTTP返回码略有了解,并不知道301和302的意义是什么,回答也明显有些搪塞,这种情况下,面试官还想继续往下挖,问到底应该选择301还是302。我觉得,这种深挖的意义就不大了。
|
||||
|
||||
## 考察技巧
|
||||
|
||||
好了,说完反面,下面来从正面讲讲系统设计考察的技巧。通常来说,系统设计的考察有两种主要形式:
|
||||
|
||||
- 第一种,是让候选人讲他自己熟悉的、做过的系统,或者是引以为豪的项目;
|
||||
- 第二种,是像前几讲中介绍的那样,给出一个实际问题,细化、分析,延伸成一个对于核心功能的系统设计问题,并加以讨论和解决。
|
||||
|
||||
### 做过的系统
|
||||
|
||||
第一种面试方式非常常见。**让候选人谈论做过的系统,把握一条原则,是候选人必须非常熟悉,最好是“最”熟悉的系统**,这样我们才能了解到,候选人在过去的工作中,表现如何,有多深入的理解,又有多少思考。
|
||||
|
||||
我们不妨回想一下其它的技术方面的考察路径,如果是算法和数据结构,问“做过的算法”,好像很难这么问,而且这么问很可能也挖不到什么有价值的信息;如果是面向对象,问“做过的项目中,类和方法的设计”,听起来就觉得非常别扭,对不对?
|
||||
|
||||
确实如此,对于技术方面的考察点,唯有系统设计,问“做过的系统”,是一个非常好的途径。
|
||||
|
||||
话说回来,这样的面试方式,**也存在着一定的局限性。**
|
||||
|
||||
**最大的问题,就是它只考察了候选人对于“已有系统”的理解,多为“经验之谈”,这是可以事先充分准备的。**它并不能很好反映出,对于一个陌生的新问题,候选人能否灵活地运用掌握的套路和方法来解决它。
|
||||
|
||||
事实上,在面试中,我也确实遇到个别候选人,虽然对于自己做过的项目说得头头是道,但给出一个新问题,却畏手畏脚,缺乏想法,表现不佳。
|
||||
|
||||
其次,必须指出的是,**这种方式,对于面试官的素质也有着相当高的要求。**
|
||||
|
||||
因为相对而言,这种方式下,谈论怎样的系统,包含着怎样的问题,涉及到怎样的技术,都是候选人所主导的,如果面试官并不具备丰富的经验,又恰好遇到一个不属于自己熟悉领域的软件系统,有时候就没办法提出一针见血的问题,也没法采集到充分且有说服力的考察数据。
|
||||
|
||||
在某些大厂的面试培训中,**培训老师甚至会明确建议,经验较少的面试官不要主导系统设计面试,而是主导相对容易操作的算法和数据结构的面试。**<br>
|
||||
<img src="https://static001.geekbang.org/resource/image/4a/11/4a2872f07c2da3e22e5873ae4cfa4411.jpg" alt="">
|
||||
|
||||
对于发问,我们可以这样做:
|
||||
|
||||
>
|
||||
你能否介绍一下,过去有哪一个你最熟悉,或是最引以为傲的软件系统?
|
||||
|
||||
|
||||
我们也可以找到简历上最加以渲染的项目,而发问:
|
||||
|
||||
>
|
||||
你在简历上说,你主导了一个半年期的项目X,我对于这个系统很感兴趣,你能否介绍一下?
|
||||
|
||||
|
||||
其实这两个方式的目的是一致的。
|
||||
|
||||
对于考察的过程,我觉得要从宏观和微观层面去分别把握。
|
||||
|
||||
**在宏观上,观察候选人能否对他介绍的系统有着清晰的把握,有着整体的认识**,而不是一下子就跳到某一个具体细节实现上去。比如说:
|
||||
|
||||
- 系统解决了什么问题?
|
||||
- 系统的架构是怎样的?
|
||||
- 模块、组件之间的交互是怎样的?
|
||||
- 系统存在哪些问题,有哪些瓶颈?
|
||||
- 如果再给一次重新设计系统的机会,哪些地方可以改善?
|
||||
|
||||
**在微观上,对于候选人自己熟悉的、做过的部分,我们要选择几个点向下挖,并且挖掘得足够深,到“具体是怎样实现的”这样的程度**,毕竟在现实中,夸夸其谈的人不在少数。
|
||||
|
||||
“深入”的核心,就是要抓住两个词——“具体”和“细节”,下面我通过一个小例子来说明。
|
||||
|
||||
比方说,候选人说,他最近主导了一个三个月期的性能优化项目,那我们就可以抓住这一点进一步细化。请看下面这个对话片段:
|
||||
|
||||
候选人:我最近在项目中把门户网站的性能优化了一倍。
|
||||
|
||||
面试官:我很感兴趣,能具体说说是什么方面的性能优化了一倍吗?
|
||||
|
||||
候选人:是网页的加载时间优化了一倍,以前平均一个页面要将近3秒,现在1.5秒就可以打开了。
|
||||
|
||||
面试官:是什么网页,门户网站的所有网页吗?
|
||||
|
||||
候选人:不是,是媒体详情页,不是媒体列表页。
|
||||
|
||||
面试官:哦,那你做了哪些改进才做到的呢?
|
||||
|
||||
候选人:我把详情页上的评论部分改成Ajax调用了,这样页面加载出来,用户浏览评论区时再去异步请求获取评论。
|
||||
|
||||
面试官:了解了,那你通过什么方法得知这个页面加载时间从3秒优化成1.5秒的呢?
|
||||
|
||||
候选人:我们做了性能测试,压测我们beta环境的系统,1.5秒是TP99的值。
|
||||
|
||||
面试官:那在压测的过程中,系统的吞吐量是多少呢?
|
||||
|
||||
候选人:只有一个主请求,没有模拟静态资源访问的情况下,QPS上限大概是2000。
|
||||
|
||||
面试官:那在测试中你是怎样确认这个QPS已经达到上限了?
|
||||
|
||||
候选人:根据我们的单机压测模型,开始并发数逐渐增加,吞吐量线性增大,后来增长减缓,但到大概第10分钟的时候出现拐点,延迟突然增大,吞吐量也过了峰值走低。
|
||||
|
||||
这里抓住一个点深挖的目的,并不是考察候选人能否记得性能优化的每一处细节,而是要确认候选人是否真正参与了这个过程,是否对这个优化过程的几个核心问题有清晰准确的认识。
|
||||
|
||||
换言之,如果候选人重新做一个类似的性能优化项目,要看看他是否确实因为这个项目而具备了相当的功底。从中我们也可以看出候选人对于某项技术,到底把握到何种程度,对于做过的项目和系统,是否具备一定深度的理解。
|
||||
|
||||
需要说明的是,一个技术点的深挖要以拿到预期的考察数据为目标,可以问1分钟,可以问10分钟,这都是没有限制的。一旦拿到了预期考察的数据,不必过多纠缠,继续下一个环节。
|
||||
|
||||
当然,这个话题点一定要是候选人(至少是自称)熟悉的,并且,**深挖和关注细节不是纠缠于细节,我们不要把追问变成钻牛角尖,也不要把追问变成“考记忆力”。**
|
||||
|
||||
### 全新的问题
|
||||
|
||||
前面讲了我们怎样去考察候选人对于他做过的、熟悉的系统,到底有多少理解,下面我们再来讲讲,如果是一个新问题呢,候选人能否顺利地设计一个全新的系统来解决它?这两个方面其实是互相独立的。
|
||||
|
||||
那我们就用一个模拟案例来介绍,如果我们像[第4讲](https://time.geekbang.org/column/article/362407)说的,像做一个迷你项目一样,给出一个实际问题,层层递进,逐步细化、分解和延伸成一个系统设计的问题(如果你忘记了,请一定回看第4讲),我们又该注意哪些方面。那个具体问题就是:
|
||||
|
||||
>
|
||||
“请你设计一个网约车系统。”
|
||||
|
||||
|
||||
并且我们也谈到了,经过细化以后,下面的系统设计考察,就是要求设计一个系统,来完成定位、叫车、搜索、接单等网约车系统的核心功能,如:
|
||||
|
||||
1. 乘客可以随时随地叫车;
|
||||
1. 系统寻找邻近的司机并转发请求,如果无法接单,继续扩大寻找范围;
|
||||
1. 司机可以抢单,即接受或者拒绝叫车请求;
|
||||
1. 双方可以刷新自己在地图上的位置,也可以查看彼此当前的位置。
|
||||
|
||||
对于非功能需求,特别是系统容量的估算,我们后续将在专题中谈到;而对于功能需求的系统实现方面,我们继续来看后面候选人和面试官之间的对话片段。
|
||||
|
||||
**第一阶段:客户端 - Service - 存储的基本层次建立**
|
||||
|
||||
面试官:根据我们的讨论所确定的需求,这个系统中会有哪些主要模块?(要求澄清)
|
||||
|
||||
候选人:我觉得这个系统中,乘客可以叫车,司机可以接单,因此我打算创建一个Ride Service来接受乘客的请求,ride的信息存放在数据库中。整个交互过程如下图:
|
||||
|
||||
1. 乘客请求乘坐,提交一个ride(相当于一个请求乘坐的订单);
|
||||
1. Ride Service将乘坐请求发给多个司机;
|
||||
1. 司机抢单;
|
||||
1. Ride Service再将接单的信息告知乘客。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/e8/50/e8a3c8d7a4001152ed4772f7e41f1650.png" alt="">
|
||||
|
||||
**第二阶段:Service 解耦**
|
||||
|
||||
面试官:嗯,那么其中的第2步和第4步,消息怎样从服务端传递给客户端呢?(要求澄清)
|
||||
|
||||
候选人:我觉得可以使用长连接,来保证消息能够第一时间送达,如果这一步失败,iOS或者安卓平台还有统一的消息推送机制。
|
||||
|
||||
面试官:好,那么Ride Service怎么来寻找合适的司机来转发乘客的乘坐请求呢?(给出挑战)
|
||||
|
||||
候选人:我觉得Ride Service知道所有乘客和司机的位置,那就可以寻找最近的一些匹配,位置可以通过司机和乘客各自手机上的app来汇报,比如每十秒钟就汇报一次GPS位置。
|
||||
|
||||
面试官:可是我没有看到你画的图中有这个啊?(要求澄清)
|
||||
|
||||
候选人:哦,他们都汇报给Ride Service。
|
||||
|
||||
面试官:所以,位置信息归Ride Service管,乘车请求的匹配归Ride Service管,匹配上了以后,结果的通知也归Ride Service管,它一个service要管那么多事情吗?(给出提示)
|
||||
|
||||
候选人:嗯……我觉得可以解耦,根据单一职责的原则,让一个service只做一件主要的事情:
|
||||
|
||||
- Ride Service只管ride的匹配和决策;
|
||||
- Notification Service负责通知消息;
|
||||
- Location Service负责维护司机和乘客的位置。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/d8/fc/d8137ed34cbeaeb73ac5f0d402b6dbfc.png" alt="">
|
||||
|
||||
**第三阶段:进一步解耦,补足缺失**
|
||||
|
||||
面试官:嗯,确实看起来好多了。但是我还有个问题,司机和乘客汇报GPS位置的时候,从图上看,只有在乘客请求和司机接受ride的时候才会汇报位置信息吗?。(要求澄清)
|
||||
|
||||
候选人:哦,系统是需要实时获取位置信息,才好做匹配,我觉得GPS的信息也应该从ride的逻辑解耦开,应该有单独的位置汇报请求发给Location Service。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/cf/f4/cf4ae62f446880320000614bdb170bf4.png" alt="">
|
||||
|
||||
**第四阶段:细化存储层设计**
|
||||
|
||||
面试官:嗯,不错。我注意到ride数据和位置数据也随着Ride Service和Location Service的解耦而分离开了,这很好。那么,对于这两类数据的存储,你打算分别选用怎样的技术来实现呢?
|
||||
|
||||
候选人:ride数据需要接受关系查询,位置信息需要根据司机、乘客的ID来查询,还需要能够快速找到邻近位置的司机和乘客……(对于这两类数据的存储,可以作为下一个话题来详细展开)
|
||||
|
||||
不知道你发现没有,这个小片段,就模拟了面试官使用“要求澄清”和“给出挑战”两大法宝,怎样领着候选人一步步攻克系统设计问题的过程,这个过程和上一讲的算法和数据结构面试,是类似的。
|
||||
|
||||
其中,对于位置数据的存储,如果感兴趣的话《全栈工程师修炼指南》的[第26讲](https://time.geekbang.org/column/article/162965)中,我做了详细的介绍,你可以做延伸阅读。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/2c/fa/2c610e117e0ebdb75a614375ee70b9fa.png" alt="">
|
||||
|
||||
## 总结与思考
|
||||
|
||||
好,今天的内容主要就是这些。
|
||||
|
||||
我先给你举了一些系统设计面试的踩坑案例,然后又给你分享了两类主要的面试方式,深挖候选人做过的系统,或者和他一起讨论一个全新迷你项目的实现,它们都能考察候选人对于系统的理解,但是又各有侧重。
|
||||
|
||||
你可以结合我为你还原的面试现场对话,仔细体会系统面试的操作方法。
|
||||
|
||||
这里我需要额外强调的是,系统设计就和算法一样,我们还是更应该关注基础,选择合适的问题,可以问,但不要一味追求高大上的“海量存储”、“大数据”这样的问题,这和算法和数据结构的面试不要过度追求“偏题”、“怪题”是一样的。
|
||||
|
||||
**毕竟,能将生活中那些实际的问题,选择合适的工程技术来解决,才是软件工程师最根本的使命。**
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/af/1d/af55fabf291cc6c979d439b7541cbd1d.jpg" alt="">
|
||||
|
||||
在最后,我想请你聊一聊你在阅读后的想法,特别是你是否有系统面试的经历,你觉得有哪些特别重要的方面,能否在留言区谈一谈呢?我会积极回复你的想法和问题。
|
||||
|
||||
好,我是四火,我们下一讲见!
|
||||
173
极客时间专栏/geek/技术面试官识人手册/面试进行|实践篇/08 | 其它技能考察:见微知著,不可忽略的其它考察点.md
Normal file
173
极客时间专栏/geek/技术面试官识人手册/面试进行|实践篇/08 | 其它技能考察:见微知著,不可忽略的其它考察点.md
Normal file
@@ -0,0 +1,173 @@
|
||||
<audio id="audio" title="08 | 其它技能考察:见微知著,不可忽略的其它考察点" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/71/d9/71a11cdae37d79f9d991e49c22e661d9.mp3"></audio>
|
||||
|
||||
你好,我是四火。
|
||||
|
||||
关于怎样主导技术面试的问题,在前面几讲里,我们分别对算法和数据结构,以及系统设计这两个最常见的考察路径,做了重点讲解。
|
||||
|
||||
而在技术考察方面,还有一些常见的其它路径,比如面向对象的考察,还有针对测试能力的考察等等。
|
||||
|
||||
据我观察,近几年来大家对于软件工程师的全面性要求越来越高,早就不再是会写代码逻辑、会设计系统就可以轻松当面霸了,在这一讲中,我就介绍一些比较常见的其它面试路径。
|
||||
|
||||
## 其它工程技能考察
|
||||
|
||||
### 面向对象考察
|
||||
|
||||
严格说起来,多数情况下,这一点应该叫做代码设计能力考察,只不过面向对象是最常见的其中一个方面而已。从技术角度上说,它包含了两个方面:
|
||||
|
||||
1.**考察候选人代码层面的面向对象设计能力;**<br>
|
||||
2.**考察候选人代码层面的综合代码组织的能力。**
|
||||
|
||||
先来说说上面的第1点。面向对象考察,尤其是对于入职没多久的程序员候选人来说,这是一个非常常见的形式。我们有时讲的代码层面的建模,其实就是通过面向对象的办法,把实际问题使用代码的类、方法等抽象来描述的过程。
|
||||
|
||||
既然重点是面向对象,这就意味着往往问题并不夹带复杂的算法逻辑,而面试官的重点也将放在代码设计的层面,能否将实际问题场景的核心抽象成一个又一个的类、方法和属性,安排它们之间的关系,并且应用合适的设计模式,作出合理的解耦,最终落地到代码上。
|
||||
|
||||
这种考察方式其实很考验候选人代码层面的设计能力,又和同为代码层面的算法能力有明显区别。我们也确实见到有一些候选人,他们虽然能够攻克复杂的算法,但是在代码设计和组织上却不尽人意。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/e7/83/e797df83c7a667c1ffe05654c09eb583.jpg" alt="">
|
||||
|
||||
再来说说上面的第2点,综合代码组织的能力。如果我们再站高一点看,其实好的代码都不一定非得是面向对象的,即便是过程式的代码,一样可以做好模块化、解耦,因此本质上我们考察的重点是候选人综合的代码组织能力。
|
||||
|
||||
另外,这样的面试也需要对编程语言的许多语言特性有准确的认知。比方说,如果面试题目明确指出了要求面向对象的方式来完成实现,那么除了代码设计层面,我们也能看出候选人对于封装、继承、多态等等一些现代编程语言基本特性的理解如何。
|
||||
|
||||
无论这一轮面试关注于上面说的哪一点,都要像我们前几讲介绍的那样,专注于具体问题的解决,即和候选人一起使用这些技能和工具解决实际问题,而不是单纯地做设计原则和设计模式理论和概念的问答。
|
||||
|
||||
事实上,**面向对象考察中,我观察到最常见的误区,恰恰就是纠结于设计模式。**说到底,代码层面的设计,最终目的是为了代码具备更好的可读性、可重用性和可扩展性。
|
||||
|
||||
因此,分层清晰,做到了良好的模块化、做到了合适的解耦,又留下了一定的扩展能力的代码,往往就已经是好代码了,不一定非得扯上某个著名的设计模式;反过来也一样,即便能够准确地说出某个设计模式的定义,它也不能作为对于代码设计能力的有力证明。
|
||||
|
||||
### API设计考察
|
||||
|
||||
现在对于很多大厂来说,业务都分得很细致,那么每一个团队往往都要维护若干个service,并且将业务能力通过API的形式暴露出来。在这种情况下,API的调用方就是团队的用户。
|
||||
|
||||
因为API的设计能力显得举足轻重,所以针对它的考察能够从相当程度上,看出候选人是否在代码接口和客户端与service的交互方面有一个平衡的理解。前者是对代码的理解,而后者是对系统的理解。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/19/2f/19f0e1d4ded01394b86cd79ffec3412f.jpg" alt="">
|
||||
|
||||
比方说,还记得[第7讲](https://time.geekbang.org/column/article/364712)中谈到的网约车系统吗?对于其中的Ride Service,我们就可以引导候选人完成类似如下的API接口设计表格:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/45/10/45583cb6594d716a3936abf5608da510.jpg" alt="">
|
||||
|
||||
假如说我们把这个提供API的模块当作一个黑盒,当它所有的API都已经清楚了,我们对于这个黑盒的功能,以及这个黑盒的用户怎样和它进行交互,这两件事情也就非常明确了。
|
||||
|
||||
上面这个API的设计,是从HTTP协议,或者说是从REST服务的角度来描述的,对于不符合这种情况的,或者候选人不熟悉网络协议,我们也可以简单从编程语言代码中方法签名的角度描述,说清楚方法的作用,入参、返回值和数据结构,以及常见的异常种类,其本质是一样的:
|
||||
|
||||
```
|
||||
Response createRide(Request req);
|
||||
|
||||
```
|
||||
|
||||
### 测试能力考察
|
||||
|
||||
测试能力的考察,在某些北美的互联网大厂中更为常见。比方说,Google的工程师面试loop中,经常会单独放一轮由测试工程师主导的测试能力考察面试。
|
||||
|
||||
你可能会好奇,为什么这些大厂格外重视这点呢?
|
||||
|
||||
这里面的初衷是这样的,测试能力是对于一个具备全栈能力的工程师,所必须包含的一项重要素质,而这些企业的大多数负责开发的工程师岗位,都不会再匹配大量的测试工程师来完成项目,因此需要开发独立完成测试。
|
||||
|
||||
说白了,就是自己写的代码要自己测试,自己上线,自己oncall和修复问题,完成闭环。
|
||||
|
||||
对于测试能力的考察,有两种常见形式。
|
||||
|
||||
**第一种形式是针对已经完成的代码,做白盒测试。**面试官会期望候选人,能够拿着简单的测试用例来走一遍代码。之后也可能会提问,怎样设计测试用例才能将刚写的代码覆盖到,甚至要求写一小段单元测试代码,这是属于白盒测试。
|
||||
|
||||
白盒测试一般时间需求比较少,适合结合在每一轮包含编码的面试中,在编码完成后进行拓展。这种形式除了对于测试本身的考察,对于候选人在代码层面的理解也有着很明确的要求。
|
||||
|
||||
**而第二种形式,则是黑盒测试。**对于某一个产品,或者某一个功能特性,从黑盒的角度讨论,怎样才能做好它的测试。黑盒测试主要出现在单独的测试能力考察轮次,这种形式除了对于测试本身的考察,也要求候选人在系统和产品的层面有一定的理解。
|
||||
|
||||
举例来说,一个经典的黑盒测试能力考察的面试题是:
|
||||
|
||||
>
|
||||
如果你负责Google Map地图的设计,系统给出了从A点到B的通行路径,你计划做怎样的测试,来保证从A到B的路径这一结果是合理的?
|
||||
|
||||
|
||||
两种形式,黑盒白盒虽然差异很大,但是很多独立完成测试的工程师所需要的重要素质,比如问题场景的分析能力和用例设计的能力,其实都覆盖到了。
|
||||
|
||||
### 项目与任务管理
|
||||
|
||||
我们再来说说项目管理与任务管理方面的考察。在很多大厂的面试中,有一轮经常是由PM来负责的,这个PM有时候是Project Manager,更多时候则是Program Manager,他们会比较关注项目、任务和软件工程的流程方面。
|
||||
|
||||
最常见的考察方法是问经历,即直接了当地询问候选人,当前团队中,项目是怎样管理的,产品是怎样上线的,任务是怎样管理的,优先级又是怎样排的。其中很大一部分都可以用询问行为型问题的方法来操作,而这部分我们将在后面重点介绍。
|
||||
|
||||
好,上面介绍了一些常见的工程技能的考察类型,但是还有一些其它类型我并没有逐一展开来细数,比如针对产品思维的考察,一些在招聘团队中的产品经理很喜欢这种形式,抛出一个问题,和候选人一起挖掘用户的痛点,从产品角度讨论设计等等。
|
||||
|
||||
## 行为型问题
|
||||
|
||||
最后我想介绍一下行为型问题(Behavior Question),这是一种非常流行的非具体技术考察方式。这种方式不光很多重视价值观、领导力的大厂愿意采用,其中很多招聘团队中的Hiring Manager更是特别热衷于它。
|
||||
|
||||
### 概念与逻辑
|
||||
|
||||
首先,我们必须要弄清楚一个概念,什么是行为型问题?
|
||||
|
||||
**行为型问题基本上是一类用来观察候选人过去在特定的工作情境下,是怎样解决困难并取得成功的问题。**
|
||||
|
||||
这里要求候选人所描述的情境,包含的内容非常广泛,可以是与内部同事之间的,可以是与外部客户之间的,可以是关乎项目和任务的,可以是业务决策方面的,也可以是具体技术实现上的。
|
||||
|
||||
无论哪一种,**这里面的逻辑是,候选人在过去遇到困难的时候,遵循的逻辑和采取的行为,这相当程度上反映了未来候选人将怎样应对类似的困难。**
|
||||
|
||||
如果你还觉得不太清楚的话,可以看看下面这个行为型问题的例子:
|
||||
|
||||
>
|
||||
你能否告诉我一个实例,让我了解你在工作中是怎样说服同事,采纳你的技术决策的?
|
||||
|
||||
|
||||
从这个问题的回答,我们能够看出很多内容,譬如说,对于不同的技术决策,候选人是根据怎样的标准来评估优劣的,候选人是怎样和同事沟通的,等等。通过这样的问答方式,面试官可以看出候选人的许多品质,比如这个例子中,候选人对问题的分析思考能力,和同事的交流沟通能力,以及是否具备backbone(不轻易动摇)等等。
|
||||
|
||||
再比如下面这样的例子:
|
||||
|
||||
>
|
||||
<p>你在工作中是否遇到过不同意你主管(经理)看法的时候?你又是怎样处理的?<br>
|
||||
对于预先订立的项目目标,你有没有遇到过未能按时实现的情况?<br>
|
||||
对于在你做过的项目中的软件设计,有没有事后你觉得自己做错了的?</p>
|
||||
|
||||
|
||||
### 原则与窍门
|
||||
|
||||
好,看完例子,我来总结一下,如果要向候选人提出行为型问题,有这样几个原则和窍门:
|
||||
|
||||
**第一,问题都是基于“过去”的**,或者说,我们希望知道的,都是活生生的,已经在候选人身上发生了什么事情,他抱了怎样的看法,又是怎样应对的。与之相对的是,“假如”型问题,比如:
|
||||
|
||||
>
|
||||
假如你觉得同事的code change给系统造成了一个很严重的隐患,但是他又拒绝修改,你该怎么办?
|
||||
|
||||
|
||||
这样的问题当然有它的价值,但它就不属于行为型问题,也不符合前面所说的“过去反映未来”的逻辑来得到考察数据,以帮助我们对候选人做出评估。
|
||||
|
||||
为什么这么说?因为所有人是可以“假想”的,但是假想并不能像过去的“事实”一样反映他真的会那样做。
|
||||
|
||||
**第二,情境要包含冲突,如果可能,最好是一个棘手的冲突。**不是所有的行为型问题都要求包含“冲突”的,比方说:
|
||||
|
||||
>
|
||||
介绍一个你自己认为最为成功的项目,并说明为什么你觉得它是成功的?
|
||||
|
||||
|
||||
这个问题本身就不包含明显的冲突,没有冲突就不利于我们知道,在“困难”的情境下,候选人是怎样应对的。当然,这样温和的问题可以进一步发散开去,引出更多尖锐的、包含冲突的问题,那当然是另一回事。
|
||||
|
||||
反过来,看看前面我前文中举的一些例子,比如“和主管看法不同”的例子,就隐含了一个和主管观点不一致的冲突。在面试双方能够顺利沟通的前提下,挖掘一些对于尖锐冲突场景应对的事例,可以很好地帮助我们了解候选人。
|
||||
|
||||
**第三,追问并达到一定深度。**这一点和前面几讲中提到的[第7讲](https://time.geekbang.org/column/article/364712)中怎样询问项目一样,我们当然不是希望事无巨细,但有深度的挖掘能在一定程度上帮助确认这些都是发生过的事实,而非随口应付而编造的答案。
|
||||
|
||||
**第四,尽量避免太过常见的问题。**这和技术问题的设计类似,面试都是可以提前准备的,一些太过常见的问题,可能会变成“背答案”,自然也无法得到真实的考察数据。
|
||||
|
||||
**第五,事先明确并聚焦考察的数据点,控制问题展开的进度。**一般采用行为型问题来进行面试的时候,我们可以逐步展开一个问题,并不断发问,但是需要注意的是,小心不要被候选人“拐跑了”,结果就感觉聊了很多,却没有什么有用的事实数据。
|
||||
|
||||
由于这种面试形式,并不像前面我们讨论一个“迷你项目”那样很容易看出其中的主线,因此我们需要很明确到底要着重考察什么,而不是和候选人“随便聊聊过去”。在得到自己想要的信息以后,可以先给讨论的问题收个尾,再开始下一个问题。
|
||||
|
||||
最后,我们来回想一下,对于一个行为型问题,**我们希望从候选人那里得到哪些内容?我觉得可以用“情境”、“思考”、“应对”和“结果”这样四个词来概括。**
|
||||
|
||||
也就是说,对于当时那种情况,候选人是怎样分析和思考的,于是采取了哪些做法,以及最后的结果如何。当然,在候选人的表达之后,根据内容我们可以从中提炼我们关心的考察数据,那完全是面试官的事了。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/e6/07/e63a51f2b647b14d6be40c2f79e57207.jpg" alt="">
|
||||
|
||||
总之,**对候选人的性格态度、沟通方法、处事风格等等与团队文化密切相关的要素,我们可以通过行为型问题做比较有针对性的考察,可以说这是对技术层面考察的一个非常必要的补充。**这样的形式并不需要花很多时间,非常精心地准备技术问题,而且讨论非常自由,对于没有工程师技术背景的面试官,更是可以比较顺利地采用,因此这种形式还是比较流行的。
|
||||
|
||||
## 总结与思考
|
||||
|
||||
在前面几讲介绍了针对软件工程师候选人的算法和数据结构考察,系统设计考察之后,在这一讲我讲解了一些其它工程技能的考察路径,并对于非常常见的一种非技术范畴的考察方式——怎样问行为型问题做了解读。
|
||||
|
||||
我要特别给你强调的是,行为型问题很有价值,但是我们还是要保证整个面试过程中,大部分的时间,还是要放在软件工程相关的技术考察方面,这一点我在[第2讲](https://time.geekbang.org/column/article/360268)的计划制定部分已经说过了。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/yy/f4/yye1f9165071ef95d6cb1d1e6ca797f4.jpg" alt="">
|
||||
|
||||
今天的主要内容就是这些。我想在最后留下一个问题,你能否在留言区和我一起讨论——在你的经历中,都有哪些我们没有介绍到的面试考察形式呢?
|
||||
|
||||
好,我是四火,我们下一讲见!
|
||||
101
极客时间专栏/geek/技术面试官识人手册/面试进行|实践篇/答疑课堂02:面试实践篇热点问题解答.md
Normal file
101
极客时间专栏/geek/技术面试官识人手册/面试进行|实践篇/答疑课堂02:面试实践篇热点问题解答.md
Normal file
@@ -0,0 +1,101 @@
|
||||
<audio id="audio" title="答疑课堂02:面试实践篇热点问题解答" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/57/d5/5731b3a6d17e50a2824ca6a15afa8bd5.mp3"></audio>
|
||||
|
||||
你好,我是四火。
|
||||
|
||||
又到答疑课了,这一讲主要是围绕第二大板块的“面试进行/实践篇”的主要内容叙述的。这一讲中,我将回答一些专栏正文内容之外的热点问题,因为从面试角度看这些问题也相当重要。
|
||||
|
||||
**问题 1:面试官对候选人谈及的业务或技术不甚了解时,如何把控局面?**
|
||||
|
||||
好,我们先谈一个频繁出现的问题。在面试官和候选人的沟通过程中,一旦把话题谈论深入一点,特别是在候选人介绍项目、介绍系统的时候,就很容易出现候选人大聊特聊,面试官却听不懂的情况,那么,我们该怎样把控这样的局面呢?
|
||||
|
||||
**首先,摆正交流的心态,正视彼此认知的交集与盲区。**每个人背景不甚相同,你有你的领域,我有我的专长,既不需要惭愧,也不需要惊慌,这非常常见。
|
||||
|
||||
其实反过来也一样,某一方面内容,也许你觉得它是“常识”,甚至觉得理解它是“理所当然”,那么假如对方不知道,你也请继续保持谦逊平和的心态,保持“职业修养”。也许这的确是一个很简单的道理,但要知道自卑与自负同样来自人性,因此有时候这一点并不容易做到,需要时不时提醒自己。
|
||||
|
||||
**其次,判断为什么觉得自己“不了解”或者“听不懂”,是因为自己对通用的业务或技术领域缺乏认知,还是候选人的思路与表达有问题?**
|
||||
|
||||
比方说,假如候选人介绍他做的项目,那么通常他需要说明,这个项目的背景是什么,系统的用户是什么,他在其中做了哪些事,最后有着怎样的结果等等。这些内容,对任何一个“外人”说,都是不了解的,面试官也不例外。
|
||||
|
||||
这就不是一般意义上的“缺乏认知”了,面试官可以通过几个问题介入,通过有来有回的“沟通”,而不是单纯地听候选人的叙述,理解他介绍的内容。
|
||||
|
||||
**再次,谈及具体的业务或技术的时候,把“请候选人介绍”,变为“向候选人请教”,即便自己对它相当了解。**近似的问题,问法不同,可能效果会大不相同。
|
||||
|
||||
举个例子,候选人说,他优化了某个缓存的开源库中,锁竞争的逻辑,使得它在高并发的场景下,实现了更好的性能。那么面试官无论对这个库是否了解,都可以这样问:
|
||||
|
||||
>
|
||||
我听说过这个库,能否趁此机会向你请教一下,它原来性能上的缺陷在哪里,而你又做了怎样的修改提升了它的性能?
|
||||
|
||||
|
||||
为什么这样的方式有时会有更好的效果呢?因为一方面是“示弱”,面试官主动暴露给候选人自己的“无知”一面,而非高高在上,候选人会下意识提升信心;另一方面也能向候选人明确,面试官的知识背景,候选人会根据这一情况,调整他的陈述方式,以尽可能直白、充分和清楚。
|
||||
|
||||
事实上,一个好的面试官,不应该说太多,反而更应该成为一个倾听者。在候选人介绍业务或技术的时候,无论有多了解,都是一个很好的倾听的机会。**这样的方式能有效帮助候选人抛开顾虑,更“敢说”,尽其所能把这些问题表述清楚。**
|
||||
|
||||
如果面试官对这个业务或技术本来不了解,藉由候选人清晰的表述,依然可以获得更好的沟通,进一步了解候选人的真实一面;而如果面试官实际对它是有一定了解的,那么可以更好地判断出候选人是不是真正理解它。
|
||||
|
||||
据我观察,一些面试官无法放下身段,听不懂就“嗯”、“啊”过去了,候选人也就认为听的人知识渊博,相应地简化陈述,想避免啰嗦,这反而不利于面试官获得真实的考察数据。
|
||||
|
||||
**问题 2:面试过程中,发现候选人作弊,该如何应对?**
|
||||
|
||||
作弊或撒谎的情况其实并不少见,我在面试中就遇到过多次。有一次,在我们谈论一个算法的时候,候选人忙着敲键盘在互联网上搜索,无论是敲键盘的声音,还是视频里眼镜的反光,都暴露了他的“行踪”。
|
||||
|
||||
印象最深的是某次校招,有一个笔试环节,候选人线上答题,最后笔试得分排名靠前的十位里面,居然有好几个都是从某处拷贝了题解,整个粘贴到答题页面,然后再修改一下变量名、方法名、注释和格式。候选人可能以为代码提交前面试官一无所知,殊不知整个过程都被答题工具记录下来了。
|
||||
|
||||
如果在面试中遇到类似的情况,我们该怎样应对呢?**我听过许多不同的看法,我的建议是,不要戳穿,不要质疑,一如既往地继续流程,但在这个过程中注意收集事实数据。**
|
||||
|
||||
在面试后的决策会环节,可以首先提出这一点并与其他面试官交换意见,看看是否有类似的观察。作弊是品德问题,在一些企业中,遇到这样的候选人,是要列入黑名单中的,后续他的再次应聘,直接会被系统拒绝掉。
|
||||
|
||||
例如在我工作的公司OCI(甲骨文的子公司)中,除了Hire / Weak Hire / Weak No Hire / No Hire 这几个选项以外,还有一个很少使用的 Never Hire,就是为这种情况准备的。这类严重的品德问题在决策会一开始就可以在Bartender的引导下进行确认,一旦事实清楚,后面的流程就可以跳过了(这也几乎是实际操作中,唯一可以快速结束决策会的情形)。
|
||||
|
||||
**问题 3:如何在面试中“推销”自己的公司和团队?**
|
||||
|
||||
我在 [[开篇词](https://time.geekbang.org/column/article/359007)] 中说过,面试这个过程是双向的,很多人忽略了这一点。所以市场有些时候是买方的,有些时候是卖方的,这一点随时都在改变。因此我们在考虑考察角度的时候,也别忘了审视自己具备什么。
|
||||
|
||||
从公司的角度来说,不同的公司有不同特质,大公司在待遇上丰厚一些,小公司则能提供有挑战性和独立性的工作机会,而创业公司,则能够给以未来的期许。从团队的角度来说,也有类似的分析,即你的团队,能给候选人提供什么?
|
||||
|
||||
如果对方是优秀的软件工程师,通常不缺有竞争力的机会,那么如何在竞争中赢得青睐,这是面试中面试官需要向对方“推销”的内容。
|
||||
|
||||
对,你没有听错,在面试的时候,面试官绝不是一个高高在上的考官,而是一个平起平坐的工作伙伴,面试的过程就是一个互相体验工作氛围的过程,并且**遇到了优秀的候选人,一定要找机会向对方介绍目标团队,这样的机会比宣传册上的文字更接地气。**
|
||||
|
||||
举例来说,某团队有做分布式基础设施的机会,这更合候选人的胃口,而且团队规模和产品规模都还不大,属于较早期,工程师的工作更容易产生影响力,这就是很好的可用于“兜售”的内容。这件事情,不只经理面试官可以做,工程师面试官也可以做,而他们的角度是不同的。
|
||||
|
||||
你不妨回想一下,我们的专栏很详细地讲了怎样设计问题,怎样主导面试。别忘了这也正是一个展示自己团队的好途径。对于候选人来说,**能有一个不住回味的面试体验,能够在面试中和面试官讨论得充实、开心,这不就是一个理想工作机会的金字招牌吗?**
|
||||
|
||||
但是,反过来,我们也要坦诚告知公司和团队的局限。在沟通过程中,我们可以询问对方的近期目标、远期目标,对于公司和团队的要求等等,得到对方的期望,如果和团队能够提供的差得比较远,那么双方就没法具备合作的机会。
|
||||
|
||||
**这一点,不能光靠直白地询问,还要靠多次的旁敲侧击,因为有时候选人口中的期望,和他心中的期望其实不一致。**一般来说,我们希望这方面在电话面试的时候就已经大致确认清楚了,但是如果遗漏了,到了现场面试的时候就要补上。
|
||||
|
||||
举个例子,候选人说,他很希望做大数据的项目,而自己的团队却明确没有这样的机会,那么就可以进一步打探,对方对这个要求有多看重。如果这个愿望很强烈,那么我们的团队即使发了offer,也很可能是一个陪跑的角色,候选人加入了也呆不久,这种情况下,可以考虑公司其他团队能否为候选人提供机会了。
|
||||
|
||||
再有一个典型的例子,是关于oncall的,有的团队ops压力比较大,这一点不需要隐瞒,可以指明,给出诚实的预期,如果对方非常介意,那自然也没有办法继续下一步了。
|
||||
|
||||
**问题 4:怎样主导自由提问的环节?**
|
||||
|
||||
在面试结束前,我们尽量要留出两三分钟的时间,给候选人一个问问题的机会。不是说每轮面试非得保留这个机会,但是,这是一个进一步沟通和展示的好机会。有些时候,候选人有问题,但是没有机会问;有些时候,候选人能和经理能够进行充分的沟通,但是却没有机会和工程师聊一聊。
|
||||
|
||||
回答要得体,因为你代表的不是你个人,而是公司和团队。我觉得比较可信和诚恳的回答,都是面试官从自己的角度出发,举例而谈的。一般这种情况下,**不要使用夸张的表述,也不要去贬损其它公司和团队。**
|
||||
|
||||
有些时候,有些问题属于自己并不熟知的领域,那也可以增加一个“声明”,向对方表示一下自己并不熟悉,以免一面之词误导对方;而还有些时候,那些问题不适合回答,那就直接指出,不要越界。比如,可以说相对于自己,某位其他人更适合回答这个问题,像是候选人询问薪资,一些公司是要求面试官闭口不谈的。
|
||||
|
||||
在具体回答问题的操作上,我在这里给你提供这样几个小技巧:
|
||||
|
||||
- 首先,如果问题含义不清楚,先确认问题。一定要领会候选人具体想问什么,有时候,候选人会绕弯子,隐晦地表达;有时候,则是表意不清,或有歧义。无论是哪种,只要不清楚,就先确认清楚问题。
|
||||
- 其次,先评价问题,再回答。在问题清楚的情况下,可以对于对方的问题适当地表示认可。比如说,可以泛泛地说“这是一个很好的问题”,之后再回答。
|
||||
- 再次,在回答后,可以再次确认。比如可以说,“不知道我的这个回答是否解答了你的疑惑?”。
|
||||
|
||||
**问题 5:怎样在观摩的面试实践中指导其他面试官?**
|
||||
|
||||
观摩(shadow)是一种很常见的快速学习和上手的形式,开会可以观摩,oncall也可以观摩,面试实践也一样。
|
||||
|
||||
具体怎么操作呢?就是新手面试官寻找一位有经验的面试官,像影子一样观摩其组织和参与面试流程的整个过程,从中学习并加以思考。因此,如果有别的面试官希望shadow你的面试,或者说观摩你的面试过程,学习你的经验方法,那么祝贺你,这是对你能力的一种认可。
|
||||
|
||||
具体操作上面,我相信你会有自己的“套路”,我在这里给你分享一下我的做法。**简单来说,就是把自己的面试流程完整地呈献给对方,并提供面试前、面试后和决策会后的三次沟通机会答疑解惑。**
|
||||
|
||||
首先我会跟该新手面试官做一个简短的沟通,叙述一下大致的流程,从面试计划、面试进行到决策会,都有大致的哪些内容。如果他有问题,也顺便做一个解答。面试计划等过程中的邮件传递、材料发送等,也要抄送给他。
|
||||
|
||||
在面试过程中,主面试官需要向候选人介绍这位shadow的面试官,但他在面试过程中,通常是较少参与沟通的,而是在一旁安静地观察和思考,并做记录。这主要是因为,一旦参与了沟通,就容易影响到主面试官的计划安排。在面试之后,可以和这位新手面试官一起快速碰个面,趁着面试的过程在脑海中还新鲜,交流一下彼此的想法。
|
||||
|
||||
在决策会的环节,shadow的面试官通常是不参与投票的,但是可以表述他的观察,但是大家需要清楚,他的表述和主面试官的表述,针对的都是同一轮次而得到的反馈,不能算做两个独立的数据点。在决策会之后,两位面试官还可以第三次碰头,在沟通中做个回顾,这三次交流的用时都很短,也许每次10分钟,但作用却很关键。
|
||||
|
||||
今天,我和你聊了聊我对面试实践环节的几个热点问题有什么看法,希望这些内容对你有所帮助。如果你有问题,也欢迎在留言区提出来。
|
||||
|
||||
好,我是四火,我们下一讲见。
|
||||
Reference in New Issue
Block a user