好几周没更新过我的博客了,因为这段时间实在是太忙了…… 先是自己换了工作,然后为了给之前公司找个出色的接班人,马上紧锣密鼓地开始了招聘。招聘花了一周时间,总共看了超过 60 份简历,面试了 20 位左右工程师,好在最后结果非常圆满,招到一位很优秀的小伙伴。感慨颇多,与大家分享,希望能对大家之后的找工作或招聘有帮助。
整体感受
现在招人难吗?我的感受是:很累,但不难。
刚看到拉勾上公司挂出的职位时,我还是有些担忧的。这个职位的要求是,3 年工作经验,独立开发,作为创业公司唯一的 iOS 工程师一个人负责整个 app 的全部功能迭代,未来可能还要带一个小组。开发业务要非常熟练,非常需要能独当一面,非常需要能跟产品和后端良好沟通。基本至少是一个中级工程师的要求,而拉勾上挂出的薪水范围是 10~20k。虽然公司的业务是电商类,技术没什么特别的难点,我还是担心给得不够,怕真正有 3 年经验的工程师看见这个薪资连简历都不会投。
事实上,职位一挂出就收到了大量的简历,其中工作经验 3~5 年者比比皆是。算来平均一天面 5 个,连续面了 4 天,面得我累得要死。有几次刚说到一半,视线的余光里看到下一个已经再等了。而来面试的 20 多位工程师,有四成左右在技术方面是没有问题的,其中又有 5 位都可以算非常优秀,完全能满足这个职位的要求,他们期望的薪水也大多落在我们给出薪资范围的中段。而我们只招一个人,只能遗憾拒绝了其他几位。可见现在 iOS 3 年经验左右、中级工程师的人才市场还是买方市场,公司相对强势,招到满意的人还是比较容易的。
所以虽然面试者中有一大半水货,浪费了我不少时间精力,让我这几天时时气恼无奈;但是最后回头看,总体来说还是对面试者心怀愧疚的。才招一个人却约了这么多面试,从某种程度上来说,我也浪费了他们的时间精力。真心抱歉,也祝愿他们都能找到理想的工作。
筛简历的经验
人力部门给我们送过来两拨简历,第一波老大让我筛,我麻烦两位朋友帮我筛的;第二波我没看到邮件,最后老大自己筛的。之后面试过程中,明显感觉老大筛的结果没有朋友筛的好。
帮我筛简历的两位朋友都是 iOS 工程师,其中一位是培训出来的,他说有几份一看就是培训班的模板,帮我过滤掉了。不知道他怎么看出来的,反正这一波靠谱的多、不靠谱的少;而且他只标出一个优秀,结果果然很不错。
而老大筛简历,虽然他也会点 iOS ,不过他说他主要是看工作年限、经验,事实上他选出的简历也主要是年龄偏大、工作年限长的。但这就带来一个问题,我们的薪资范围已经摆在那儿了,而 5 年经验还来投这么低廉的职位,本身就说明一些问题。事实证明,这一波有很多明显简历造假的面试者,弄得我非常烦、非常无奈。老大人非常 nice,只是不了解现在 iOS 环境的险恶。
就我自己筛简历的感想,在没看到这些简历之前,我天真地以为可以看看学校、看看大公司、看看有什么技术亮点什么的。事实证明我想多了。就我们这个级别的招聘而言,收到的简历学校一概没听说过,而后来的面试也证明了硕士未必强于本科、三本未必不如二本。我自己写简历时,写技术点挖空心思、字斟句酌,拿着放大镜找自己工程里用到高大上的东西,力求能让人看到亮点。而事实是看到所有人简历写的技术点都非常非常非常雷同,所以大家也许是绞尽脑汁、洋洋洒洒列出的技术点,看简历的人不过是一扫而过。在实际面试中也发现意义不大,比如几乎每个人都写了熟练使用 SDWebImage,但我问它是怎么缓存的,几乎都说不出,区别只在于有些人坦言知道,有些人凭想象编两句;只要能说出有内存和磁盘两级存储的人,我内心都谢天谢地了。
让我最为意外的是,大部分简历都是做过的项目一大群,三、五个月一个项目。这点完全颠覆了我的认知,以前在我的思维里一个公司就约等于一个项目,项目黄了公司也就倒闭了。我没想到这么多小公司都三个月一个新产品,打一枪换一个地方。这种公司对工程师的发展其实很不利,很累不说,尤其是有些架构上的问题是工程大了、时间长了才能感觉出来的。
招聘结束后再反思筛简历的过程,我发现有一个指标是确定管用、对于筛简历非常有效率的,就是近期项目的质量。对于朋友帮我筛过的简历,我专门花时间下载了每位候选人最近的一个项目。就我们面试的经历而言,项目是听说过的、百度能搜到新闻的,界面整洁美观、能看出确实有一定用户量,有动画或手势交互的设计,对应的工程师技术 100% 过关。而那些一看就设计粗糙简陋、细节不禁看的 app,已经是僵尸状态、内容都疑似测试数据的项目,app store 上更新记录少、评论寥寥,对应的工程师偶尔也有好的,但相对少得多。所以跟我们体量差不多的公司,如果需要筛简历,我会强烈建议下载最近项目看看质量,可能比简历上的其他任何部分都管用。
面试的经验
我用于面试的问题经历了3个阶段的变化。
第一阶段:知识性问题
因为自己最近刚经历了一次面试,加上身边朋友好几个换了工作,我收集了一些如百度、头条、美团等大公司常问的面试题,主要是一些语言知识、内存管理、多线程、稍微有点底层知识等。我想,来这么多人,总有都能回答上来的吧。
事实证明,对我们这个级别的公司,这个级别的要求,这些常见面试题的效果并不太好。区分度非常低,要么大家都会,要么都不会。最简单的问题比如“weak 和 strong 有什么区别”,几乎所有人(确实有不知道的)都能说出 weak 是弱引用,strong 是强引用;“你什么情况下用 weak” 大部分能说出 delegate,防 block 循环引用。然后再问一句 “weak 的实现原理是什么,为啥对象释放掉了会变成 nil” 只有一两个人能说出“哈希表”这三个字,其他人要么是一阵长久的沉默,要么是说一些不着边际的猜测。
再比如多线程,“atomic 和 nonatomic 有什么区别”,很多人就不假思索地回答 “atomic 是线程安全的”(还有好几个人说,不知道 atomic 是什么,反正从来不用)。这已经是一个错误的答案了,我会提醒 NSMutableArray 的线程安全性,但得到的反馈往往是一脸迷茫。再问自己重写 atomic 属性的 getter、setter 方法,能说出加锁,不管是 @synchronized 还是 NSLock,已经寥寥无几了。
还没来得及用上什么大公司的面试题,才刚到我自己想的几个简单的铺垫问题面前,就呼啦啦几乎全倒下了。一旦这种情况发生两三次,明显面试者的情绪就变得低落,我作为面试官也很尴尬。第一天面试结束后,我回去好好反思了一下,为啥这些网上遍地都是、我本以为培训班刚出来的人也能背得烂熟的题,我们找来的人基本全都答不出呢?难道是我们公司太 low 了?然而,我们要找的并不是什么黑客科学家,我们只是要找一个能干活的人,就算不知道 weak 的实现原理又有什么关系呢?这并不影响日常干活,这种面试方法完全可能让我们错过一个编码熟练、沟通能力强的工程师。
想到这里,我决定改变第二天面试的模式。其实从最后的结果来看,优秀级别的那 5 位面试者面对这类问题是能回答得不错的。所以,单就结果而言,如果答不出这种常见面试题,就直接拒掉,这个策略似乎也不会有什么坏影响。不过,对于大多数普通工程师,这类题的区分度不好。因此,在后续的面试中,虽然我基本每个人都还是问了两句这类问题,但再也没有把它们当做重头戏。
第二阶段:一般性问题
再也不想让面试过程的大部分被尴尬的沉默占据了,我决定想几个能让每个人都聊得开心的问题。例如:
您在工程中遇到过什么很难的问题?不论是特殊的交互方式、复杂动画、性能、安全问题…… 最后怎么解决的?
展示您做过最复杂的一个界面 / 自己封装得比较好的组件,介绍它的结构和为什么这么做;
您在工程中做过哪些重构?做出了哪些改变,最后的效果如何?
平常工程中用到哪些第三方开源库?您读过它们的源码吗?讲讲自己最熟悉的一个开源库的源码结构;
下面给您看的这几张图是我上一期刚开发完的需求,如果让您开发的话,您能给出一个估时吗?其中有什么难点和风险点吗?
……
这些问题的好处是显而易见的,每个人都能多少说上几句。回答大部分是“没有”、“没什么”的基本可以 pass 了,而优秀的工程师往往有很多内容可聊。但是这些问题也有一个显著的缺点,就是对我的要求陡然提高:不像知识性问题能简单粗暴地比对标准答案,我必须全神贯注地倾听面试者的回答,尽可能地理解、猜测他讲的技术,同时还要时刻注意寻找能进一步挖掘的点,然后再往深处问下去,还要尽量表达清楚深一层的问题。
这样面试一个人,我比自己接受一次面试还要累。其中一个主要原因,就是努力让对方听懂我进一步提出的问题。
比如一个人讲他封了一个弹框那种 HUD,我就顺便问,如果调起这个 HUD 的方法不是在主线程调用的,是不是会 crash 呢,你是怎么处理的?对方一脸不解,于是开始了数个回合的拉锯纠缠:“调起是什么?” “就是把它显示出来,你总要把它显示出来吧?” “那就把它显示出来呀,不明白您想问什么” “我就问如果不是在主线程做这件事儿,怎么做?” “……没什么区别呀?什么情况不会在主线程,我没遇到这种情况” “比如在网络请求的回调里呀,如果网络请求不是主线程,是不是会 crash 呀,网络失败了我是不是要显示这个弹框弹一个错误呀” “我就是这么用的,没有 crash 呀……”
其实只是想问 dispatch 到 main 这么一个简单的事情,但似乎就是无法表达清楚我的问题。看着对方莫名其妙的样子,我开始后悔提了这个问题,犹豫是放过还是纠缠下去。两三场面试下来,我听到最多的一句话是“我不明白您想问什么”“我不确定我理解了您的问题没有”,仿佛我们说的不是同一种语言。从反复解释到最终语塞,我感到了深深的挫败感,对我的沟通能力产生了巨大的怀疑,仿佛听到对方在想:“这人问的这都什么跟什么,她到底懂不懂技术。”
于是我决定把电脑带进会议室。下一个人我问看过什么开源项目,他说用 JSONKit 把 json 转成 model。我没看过 JSONKit,但看过 JSONModel,感觉应该差不多,就问他 JSONKit 是怎么把 json 转成 model 的。同样的场景又重现了,完全说不到一块儿去,他一直莫名其妙地说:“就是那么转的呀?不知道你在问什么。”
我开始怀疑人生,怀疑这个我看过的库是不是用法别具一格,跟我想象的完全不一样。所幸我带电脑进来了,于是我快速写了一个 Student 类,定义了一个 NSDictionary* dictionary = @{@"name":@"hamster"},让他简单写一下 dictionary 是怎么变成 model。他是这样写的:
Student* student = dictionary;
看到这行代码,我一瞬间明白了很多。就算我没看过这个库,但我也知道 OC 里没有这种神奇魔法;即使我让他现场写 dictionary 转 model 要求太高了,但是任何一个工作过一天的 iOS 程序员的人都是写不出这行代码的。我也一下子明白了为什么前面总说听不懂问题,因为他对我说的东西完全没概念,脑子里一片空白。把责任推给我,假装是我没问清楚,可能是在这种情形下他唯一能做的防御了。
对于后面的面试者,我还是会把这些问题拿几个出来问一问,但再也没有跟对方死磕。事实证明,对于比较优秀的那几个面试者,我从来不用多费口舌,轻轻一点就能马上说出我想要的答案,真是十分畅快。这是我第一次意识到,沟通能力低的背后其实可能只是技术能力低。工程师之间的沟通技巧,背后是工程经验、架构水平和技术知识在支撑的。
就这几个问题而言,我觉得一个比较有区分度的是“做过哪些重构”,因为得到的回答非常明显的两级分化:一种是“基本没怎么做过,我写的时候就很注意了,不需要重构”,或者说做过,但实际上只是因为前面代码质量太差而推翻重写;另一种是“非常常见,经常会做”。在我看来,后一种工程师水平是比前一种要高一层次的。不是代码写得烂所以总要重构去修改,而是随着时间推移、业务变化,重构是必须的,但只有对技术有追求、对自己有要求的工程师才会发现这个问题、才会冒风险去重构。没做过重构,要么说明他做项目没深度、做一个扔一个,要么说明懒惰或过于忙碌,但无论如何是不可取的。
(篇幅已经比较长了,剩余的内容会放在 下 篇里。有兴趣看下去的话可以过段时间再来看。)