面试了 20 个初/中级 iOS 工程师之后(下)

7,472 阅读18分钟

最重要的话写在前面:本文不允许任何公众号、论坛社区、微博转载。原因请见上一篇开头。

(上)篇说过我的面试方法经过三个阶段的变化,下面说说最后一个阶段。

第三阶段:现场写代码

面试的历程开始之初,请面试者现场写代码这个想法就不时在我的脑海里浮现。毕竟同样是程序员,水平如何,看一眼代码是最快了解的方法(所以所有附 github 链接的简历我都给过了,总共只有两人)。但一直比较犹豫,开始没有采用这个方法,最主要的原因是怕面试者会累。因为写代码总归是比较累的,尤其是在短时间内高度集中精力写代码。之前我自己去下家公司面的时候,几轮面试总共让我写了三个小时的代码,紧张到我怀疑人生。候选人当天可能还会有别家公司的面试,我实在怕累着人家。还有一个原因是写代码耗时长,而面试者太多,老大让我 40 分钟过一个;40 分钟够写什么呢?

但有一位先生让我下定决心要请后面的面试者现场写写代码,哪怕只写两三行。当时我还在采取第二阶段的问题,我问:“您在开发方面感觉遇到过什么难点?” 他回答:“平常主要工作是画画界面,感觉没什么难点。有一次做横屏的时候感觉挺麻烦,因为总体要求竖屏,只有一个界面横屏,然后键盘会有问题……”

我觉得这个回答挺靠谱的,因为单个界面横屏确实有点麻烦。另外一个问题:“您做过哪些重构?” 对方回答,上家公司把外包代码直接拿回来用,mvc 分层不清,一个 viewController 好几千行,里面大量绘制代码;他把 UI 的绘制都尽量分出去到单独 view 里做了。我一边听一边点头,刚毕业的时候领导也带着我做过类似的事。到这里为止,我对面试者的印象很好。然后后面聊到自己封装过的控件,我随口问了一句:“一般什么时候用 weak?”

对方回答:“weak 啊…… weak 一般就是用来修饰 int 那些的吧。”

这个回答出乎意料。我觉得可能是个小口误,正好电脑就在面前,我说:“weak 修饰 int 肯定会报错的呀。”一边顺手敲出来,果然那一行红了。

然而对方只是呆住了。1 分钟面面相觑的沉默。

送走这位先生,我对自己的面试水平再次产生了深深的怀疑。一个工作三年,重构过几千行 viewController 的工程师,为何会不知道 weak 不能用来修饰 int 呢。这次经历给我敲响了警钟:第二阶段采用的诸如“工作中遇到什么难点”这类一般性问题,虽然比知识性问题聊起来开心很多,但它有一个弱点,就是这些问题都是可以提前准备的。也许这位面试者,先去向开发经验丰富的朋友请教,把他们的回答一一背下来,准备出一套天衣无缝的说辞。如果去面一个没人会 iOS 的公司,他可能会被认定为很优秀、很有经验;如果我没随口问这个问题,我可能也会把他放过去了。

于是我决定,对于后面的每个面试者,都尽量让他/她现场敲几行代码;保证一下招聘的下限,起码要招一个会写代码的人……

既然决定要写代码,出个什么题目呢?我想的是封装一个简单的小控件会比较好,最后选定的是公告栏,就是文字上下自动滚动的轮播。类似蚂蚁金服首页“聚宝头条”后面那样的文字滚动,内容做一行 label 即可,停 2s 滚动一次。只需要向一个方向滚动,不需要用手指能拖。点击时触发点击事件,打个 log 即可。

我对自己选定的这道题还是比较满意的,难度不大,同时可考察的点却不少。出题的时候,我都会先给面试者看我在自家 app 实现的这个小控件,一方面是为了更清晰地说明题目,让对方可以一边看着例子一边想,有助于想到怎么实现;另一方面也是为了防止人家误会我们用面试骗代码,骗他们帮我干活><

虽然功能很简单,但代码写起来也需要时间。我跟面试者说的是,30 分钟随便写,电脑已翻墙,允许上网查任何资料,写多少算多少,写不完也没关系,咱们看看代码。最终做过这道题的 8 位面试者有两位能实现到 90%,有一半直到时间过完对于怎么实现效果还是没有头绪。实际上只要能写出雏形、能口述出后面准备怎么写的,我这边都给过了。

真的让面试者做现场写代码这么辛苦的事,我心里还是比较愧疚。所以对于每一个写了代码的面试者,我都会一行行帮他们 review,但愿他们费了这些时间精力的同时也能得到一点点收获,这是我唯一能补偿他们的了 >< 从大家的代码来看,出现的问题还是比较集中的,主要如下:

速度与编码规范

速度方面,因为给的时间实在不够,所以只要思路可以,并不要求代码量多大。手快的工程师 30 分钟一气呵成写了一百多行代码,我非常钦佩膜拜。也存在略为过慢的工程师,30 分钟只写了不到 10 行代码,就画了两个 label,也没来得及想后面的思路。这种情况会让人不免担心他以后的开发速度,所以就直接不能通过了。

有一位面试者比较特殊。一上来我会先自我介绍,然后请对方也简单自我介绍下,其实一两句话即可,3~5 分钟都比较正常。但这位说了足足 20 分钟,都是前公司如何做业务、如何运营这些跟技术无关的事,而且没有空隙,我都找不到打断的机会。请他做这道题,他一听就说肯定有第三方的实现。我说别找第三方的,尝试自己写一下吧。过了半小时回来,发现他还是从 Github 上下了一个第三方的实现,放进工程里交差。我不太开心,进去第三方的源码问了他几个细节,果然他也没有太深入的考虑。如果在工程开发中,找开源的实现当然没有问题,虽然个人觉得这种简单的控件自己写反而问题少一些。但是在面试中,我都明确说自己写,还坚持用第三方库,难免让人认为是对开发能力不够自信。

编码规范方面,看看大家的不同习惯还是挺有意思的。有些朋友不爱空格,等号、加减号两边一概不空格;有些命名时驼峰与下划线混用;还有几位只用 instance variable 的方法存变量,不用 property。当然无论有什么个人习惯,我觉得都可以用宽容的眼光看待,避免横加批判。但是编码比较符合大众化的规范,命名比较好读,看的时候肯定是更有好感的~

UI 上如何实现轮播效果

其实最简单的实现就是两个 label 循环,一上一下,上面滚出屏幕之后再重回到底部即可。不过实际上大家想到的方案五花八门:有好几位想用 UITableView、 UICollectionView 的,有用 UIScrollView,把每一个 label 排上去的。我觉得选用哪种方案都没关系,用 scrollView 的不重用也不是什么大事,只要能实现效果就行。但是这些思路基本都是把每行文字先从上到下排好,然后再第一行开始,一行行往下滚。这就带来一个共同问题:到最后一行怎么办呢?

有一位工程师想到把第一行文字复制到最后一行;滚动到最后一行之后,不带动画重回开头,我觉得是非常聪明的做法。不过其他人要么没有想法,要么说只能从最后一行哗啦啦 scroll 回第一行了。这样看起来效果是不够好的,我觉得是一个在设计之初就应该考虑到的问题。

传值方式

因为要求在 label 上加点击事件,就会涉及到开发中最基本的问题之一:怎么把点击事件传出去。写到这里的人不多,主要是提问+口述,发现现在大家还是喜欢用 block 的多。有一位很认真地写了一个 delegate:

@protocol ScrollLabelDelegate <NSObject>

- (void)scrollLabel:(ScrollLabel *)scrollLabel didSelectIndex:(NSUInteger)index;

@end

@interface ScrollLabel : UIView

@property (nonatomic, weak) id <ScrollLabelDelegate> delegate;

写得很规范,一下就把我征服了~

在这里我会顺便问一个问题:“如果要用 delegate,一般用什么关键字来修饰 delegate 属性?” 有 3 位面试者都很干脆地回答:“用 assign 呀。”我跟他们讲了为何用 weak 比 assign 好一些,猜测他们可能是看了同一个过时的教学视频,所以留下了相同的错误印象。虽然现在开发中 delegate 用得相对少一些,但这些比较基础的内容还是要知道的~

防止 timer 造成的内存泄漏

像 timer 这种东西,大家肯定觉得都是很简单,虽然 API 记不住,用到的时候现查就好了。这次出的题,我是允许上网查任何资料的。实际上同样是上网现查,开发经验丰富的工程师速度就要快很多,而经验不足的工程师还是免不了踩坑 >< 有一位不知道怎么,30分钟全都用在试图开一个 dispatch 的 timer 上,还把自己带的电脑的代码拿出来抄,到最后这个 timer 还是没调出来……

有好几位用的 NSTimer,把 timer 保存成一个 strong 的属性,然后 timer 的 target 设为 self。当我问到 timer 有些 API 会 retain 它的 target,会不会造成循环引用,这样是不是有内存泄漏的风险?大部分工程师都表示没听说过,还有一位回答:“没关系,只要在 dealloc 方法里把 timer 置为 nil 释放掉就可以了。” 但如果真的形成了循环引用,就不会自然走到 dealloc 方法。

回想上一篇文章,一些评论喷我问的问题是装X,平常开发反正也用不到,用到时候再查不行吗,有什么百度解决不了的问题吗?我个人也不喜欢那种很底层、很偏的面试题,也同意网上很多面试题是平常开发用不到的;但就这个细节来看,开发工程师了解一些内存管理的知识还是有一定必要。这里如果考虑到了内存泄漏,只需 google “NSTimer retain cycle” 就有一堆一堆的结果,很容易就能找到解决方法。但如果对这些没概念,可能都不会意识到有这个问题的存在;或者像回答“在 dealloc 方法里打破循环引用”的那位朋友,想当然地以为问题已经解决。对于这些工程师来说,他们会想到去 google 一下吗?最终结果就是一个隐患埋进工程里。

面对“有什么百度解决不了的问题吗?”,常见的问题确实没有解决不了的,但前提是要大概有个概念。所以虽然上篇文章被喷,过段时间我还是准备学一点底层的知识,就算细节看完了就忘,能补充下知识框架也是有好处的~

印象深刻的面试者

关于面试的经验,我能想到的都毫无保留地跟大家分享了。最后一点篇幅,跟大家闲聊一下印象深刻的面试者吧~

关于史上最短面试

给我印象最深刻的面试者非这位莫属。

双方刚坐下,我说:“您好,很高兴认识您,我先自我介绍一下:我是这公司的 iOS 开发,在这公司快两年了,一直是我一个人做……” 跟每个人我都先说这同一句开场白。

对方打断我:“那咱们公司是独立开发吗?”

我:“是的,不过公司6月会再招1~2个人。”

一段沉默。

我:“您换工作是想找一个不是独立开发的吗?”

对方:“是的。”

一段沉默。

对方:“那要不咱们今天就先这样?”

然后起身走了。留下目瞪口呆的我。

大概是史上最短面试了,哈哈哈。对方非常爽快,也节约了双方的时间,我很感激。从此以后我的开场白多了一句:“这个职位是独立开发的,能接受吗?”

关于培训

做 iOS 的,对培训机构的厉害都或多或少有所耳闻。有些朋友对培训出来的工程师一票否决,我倒是对培训机构没有反感,我们这个级别的公司也无法要求太多。培训本身不是问题,简历造假才是问题。所以对于几位坦承自己是培训出来的面试者,感谢他们的诚实,我都愿意额外多给一些机会。遗憾的是,这几位技术确实也都不过关,不知道是不是一个巧合。

有一些简历明显能看出有伪造的痕迹,比如 95 年的孩子说三年工作经验。我们筛简历筛掉了,不知为何 HR 还是帮忙约来了。自己解释是有个亲戚如何超生云云,最后造成自己身份证年龄小;两年前那时候虽然培训班还不是特别火,他出去面试,人家都不相信,说他是编的…… 一套话说得很熟练。简单问两个技术问题,不知 delegate 为何物。我觉得并不意外,主要是前面的解释过于流利了,有种销售的感觉,感觉就不像真的了。

有一位大哥让我印象很深。他拿出自己带的简历,把自己的学历、学位、四级证书全打印出来附到简历上了,厚厚一大叠。最后竟然还有离职证明,上面还盖着红章…… 面试时,他两手平放在膝盖上,并不看我,直视前方,像背书一样地说:“我叫某某某,5年工作经验,于某某年至某某年在某某科技有限公司工作,某某年至某某年在某某网络公司工作……” 技术问题完全聊不通,问他重构过什么代码,他说每次新建一个 view 都会重构系统的 initWithFrame。我把他送走,觉得心里很难过:大哥年纪比较大,至少 30 多了,一看就是个很实在的人,完全不会骗人的样子;这样去面试,估计没有公司会看不出来。要放弃的话,又不知道他在培训上投了多少积蓄和时间。这件事让我对培训机构产生了很多恶感,为了多赚几个钱,把这些根本不适合入行的人花言巧语骗了进来,让他们陷入这样困难的境地,去做这些不得以的事。

关于妹子

本次招聘共有两位面试者是妹子,只占了不到 1/10。不过她们的表现都不错,技术上都是过关的。一个共同特点是沟通很优秀,聊起来很轻松愉快。虽然最后结果比较遗憾,一位妹子长期严重加班,没什么时间学习,在老大一关没有通过;另一位技术优秀,经验也比较丰富,可惜自己希望转管理,可能感觉在我们这个规模的公司没有发展空间吧。

所以就本次个例来看,感觉妹子普遍技术还不错,沟通也很有优势。但愿她们都能顺利找到理想的工作,也希望业界能少一些偏见,给妹子同等的机会,相信她们也能为公司带来相匹配的贡献。

关于优秀的面试者

上一篇文章被喷了,虽然我很难过,其实想想也能理解。反复列举面试者各种表现欠佳的地方,行文确实容易给人一种盛气凌人、居高临下的感觉,比较招喷。

但真正招聘的过程远没有这些表面风光。尤其是偶尔遇到一位优秀的面试者,聊得很舒服,真是心里深受感动,几乎是乞求的心态求人家来吧 >< 但结果人家可能并看不上我们,绝尘而去。这么来看,突然觉得招聘跟相亲差不多,就是一个反复失望、互相伤害的过程;不仅求职方可能会高不成、低不就,招聘方也容易如此。

公司被拒绝的最主要原因大概是独立开发。上面说过有一位工程师听说是独立开发,扭头就走了。还有两三位优秀的工程师,虽然客气一点,走完了面试的流程,但后面也明确提出不倾向于独立开发。这种想法是很可以理解的,因为他们技术都非常不错,都提到日常级别的开发已经没有任何能难住他们的问题了,可能到了一个独立开发的瓶颈阶段;这时候希望能有技术复杂一点的项目,或者大神带带自己,是一个很正常的想法。小公司招人、留人最大的困难,可能就在于此吧。

即使有幸人家能看得上我们,还可能有各种其他原因导致谈不成。比如 HR 可能会有一些自己的考虑,有位非常熟练的工程师,老大也很满意,HR 以跳槽太频繁、兴趣爱好过多的理由否决了。虽然不知道何为“兴趣爱好过多” >< 但半年一次跳槽,引起 HR 担心也是没办法的事。

再比如一位工程师,我请他自我介绍,他一副垂头丧气、不想说话的样子,不介绍自己,只是发呆望着空气、又反问我工作时间、加班情况。虽然对方不大客气,我还是提醒自己尽最大努力保持耐心和微笑,认真跟他聊。没想到就这样遇上了整个招聘中技术最优秀的面试者:各种底层问题我尽力往深里问都能答出来,能看出水平在我之上;小控件看一眼就说出清晰思路,我一听就不用让他写了,直接过。

虽然技术非常优秀,但面试过程远谈不上轻松,他听到每个问题基本都是皱着眉、一脸不开心,沉默一会才说出答案,不时夹杂着叹息。他坦言上家公司严重压榨过度、连轴加班,自己现在已经非常疲惫、精力完全耗尽了。结果不出意料挂在了老大一关,老大说,他只聊了两句话就把人送走了,说感觉不到任何工作的激情,不适合公司现阶段发展。当然,可能人家也没看上我们公司。唉,还是真心祝福这个哥们换个轻松点的工作吧,或者休个假放松一下也好,这样下去真怕他抑郁了…… 以他的技术找个大厂完全没问题,不过精神状态不调整一下的话,找任何工作都会比较困难吧…… 也提醒广大码农,照顾好自己,小心职业倦怠;如果感觉工作已经耗尽了自己的全部活力,还是多为自己考虑吧,牺牲了健康不值得。

最后说说我们最终招到入职的小伙伴。其实看到他的简历,有不错的公司经验,我内心就踏实一半了;聊了聊果然沟通很轻松、技术很优秀。然后我就开始暗自祈祷,老大给过吧 HR 给过吧老板给过吧让他来吧拜托了…… 所幸后面一路绿灯,三天后就入职了。目前工作了两周,干活超快,各种给力:)一再感谢上天,能遇见一个对的人,会明白前面的所有辛苦都是值得的。

篇幅写到跟(上)篇差不多,也写得很累了 >< 就到这里吧。感谢阅读,要喷的话求轻喷,还有不要转载哈,怕被喷~ 最后还是祝大家都能招到满意的人才,找到理想的工作:)