IT面试经验:程序员面试什么最重要?

程序员面试一直是社区的热门话题。从2006年实习至今,我经历了四家软件公司,都是外企,有世界500强的通讯公司,有从事期权期货交易的欧洲中型金融公司,有为大型汽车厂商开发Android智能汽车的新兴公司。进入IT行业以来,在找工作的过程中经历了很多面试,最近两年也经历了很多和别人的面试。我觉得该是我表达对这个问题的看法的时候了。本文是从面试官的角度进行的阶段性反思和经验总结。

目标

我相信,和很多朋友一样,经过几年的工作经历,我开始面试别人。在这个起步阶段,我只是把“找一个基础好的程序员”、“找一个算法能力优秀的程序员”、“找一个有Android开发经验的程序员”作为我的面试目标。但实际经验告诉我,尤其是那些按照“基础好”“算法好”的目标招进来的人,最后都不会有好结果。比如有的面试官对基础知识和算法掌握得很好,进程、线程、内存等概念清晰,熟悉哈希、二叉树、快速排序等基本数据结构和算法,但进入公司后在实际工作中表现很差。后来发现我的面试目标有问题。我当初的面试方式更像是大学算法或者操作系统的期末考试。按照这种方法,很多不适合的人通过了面试,同时也可能错过很多适合的人。

后来我的反思是,从公司的角度来说,面试的根本目的是找到能做好工作的人,而“学历高”、“算法好”、“基础好”、“经验丰富”都是表象而不是基本面,不能直接等同于“工作好”。

方法

目标很明确,但接下来的问题是假设面试官是一个黑箱系统,“好工作”不是一个直接可观测的变量。你能直接观察到的变量有基础、算法、经验、学历、性格、言谈、年龄等等。所以,其实你只能从“基础好”、“算法好”等直接可观测的量来推断“工作好”的概率,这是一个“好X”条件下“工作好”的条件概率问题:P(工作好|好X)。

根据这个模型,面试中应该考察哪些方面是显而易见的,即选择最有特色的方面进行考察。比如考察面试官的身体特征就没有太大意义,因为P(好工作|高)、P(好工作|矮)、P(好工作|胖)、P(好工作|瘦)的概率都差不多;所以体貌特征不可区分,这不是面试要注意的。

面试官要根据职位的要求,明确哪些因素更好区分。比如你要招聘一个技术门槛相对较高的3D游戏引擎开发工程师,面试官A有3D游戏引擎开发经验,但在基础知识和算法面试中表现一般;面试官B则相反,基础知识和算法面试做的很好,但是没有游戏开发经验,你只能选择其中一个。你选择谁?其实这是两个条件概率问题P(好工作|好经验,基础一般,算法一般)和P(好工作|没经验,基础好,算法好)。这个问题留给面试官自己判断。个人认为,对于技术门槛高,需要技术积累的岗位,经验更能说明问题,所以我更倾向于面试官a。

下面,我就结合自己的经历谈谈面试常见的几个方面。

算法

算法是谷歌、微软等大公司面试的重点..我个人很喜欢算法。曾经参加过ACM/ICPC,北京赛区13。但从我个人的经验来看,对于我接触过的大部分开发岗位来说,算法并不适合作为考察面试官优劣的主要因素。对于普通的非算法开发岗位,考察面试官的算法就相当于考察他乒乓球打得好不好,和“工作好”这个目标的关联度太低了。就我个人经验来说,差不多P(好工作|好算法)=50%,也就是算法面试没有太大歧视。

甚至,有一种非常糟糕的情况,特别发生在算法很好的面试官身上。我称之为“磨刀不误砍柴工。”你什么意思?有些人只对什么A*算法、异步编程、JVM类加载机制之类的纯技术问题感兴趣,对实现用户需求毫无兴趣。这样的人看似有一定的技术能力,但对公司的贡献却非常有限,甚至不如那些技术一般但认真负责的人。所以一旦面试官有了好的算法,我会特别注意会不会是这样一个“只磨刀不砍柴”的人。

另外,虽然我个人不了解Google和MS,但是对他们特别注重算法能力的面试策略持怀疑态度。即使在这样的世界级公司,算法虽然重要,但可想而知,在项目实施过程中遇到的各类问题中,算法问题大部分时间不会是主要瓶颈,也不存在需要每个人都是算法专家的情况。其实大部分项目的真正难点,并不是一两个算法瓶颈,甚至不是单一的技术瓶颈,而是一个系统的组织、协调、设计和开发问题。有很多看起来没那么技术含量的脏活累活,很多问题都是因为信息不足,强大的技术能力无法克服。一个团队最好是优势互补。有的人算法强,商业分析能力强,有的人擅长后端服务,有的人擅长前端接口,有的人聪明,有的人实用。这是最好的。如果按照“好算法”这个单一标准来选材料,很多优秀的人才都会被拒之门外。

基础

基础面试是指考察指针的使用、流程线程的概念等基础知识的面试,与大学期末考试题非常相似。以前觉得基础面试很重要,现在不觉得了。基础在工作中确实很重要,但在面试过程中,一定要区分才有意义,也就是说P(好工作|好基础)的概率高,所以考察指针使用、流程线程区分等基础题目才有意义。我的实践经验是,基本面试没有很好的区分。和算法一样,差不多就是p(好工作|好基础)= 50%。同时,基础面试也是最容易准备的。中国人有长期应试教育的经验,准备几道刁钻的题太容易了。

我曾经遇到过这样一个面试官,他对C语言基础和编译链接原理掌握的非常好,给我留下了深刻的印象。我给出的面试结论是:我只懂C语言,但基础扎实,推荐就业。后来的事件证明,那个结论的前半部分是对的,但是“建议就业”是错的。他在实际工作中一塌糊涂,对需求和整体架构都不了解。同时,工作时间不是花在项目上,而是看《程序员的自我修养》之类的书。最后这个同事因为长期“没工作”离开了公司。

基础不是不重要,但是“基础好”并不足以说明面试官能做好,因为基础属于地方性知识,实际工作需要综合能力,这是很不一样的。c语言和操作系统都能拿高分,但是我们在大学里还看到很少人不会写程序吗?软件开发就像盖房子。综合能力是设计搭建骨架,基础知识是砌砖。张小龙本来是用Delphi开发Foxmail的,但是他不懂C#。如果想招一个开发. NET邮件客户端的人,看他对CLR掌握的好不好有意义吗?张小龙开发一个C#版本的Foxmail真的很难吗?你招一个精通C#但是没有邮箱客户端开发经验的人真的比张小龙靠谱吗?

我说基础知识不重要,古人云“不积一郁,不可行千里。”这是矛盾吗?不矛盾!“卜卜”和“李倩”是一种累加关系,但再多的“基础知识”也加不出“综合能力”来。学习软件开发,和持续集成一样,从一开始就是一个完整的系统。虽然规模小,问题多,但是从小系统发展到大系统,从简单系统发展到复杂系统。

所以基础好本身不足以说明太多问题,还要进一步考察综合能力。对于基础面试表现不好的,如果时间允许,还要进一步考察。有些面试官其实是有能力的,只是没有做好充分的准备。最理想的状态当然是基础好,综合能力强。如果不能兼顾,综合能力优先。

经验

这里说的经历不是用工作多少年来衡量的,主要是指面试官的经历,比如是否作为主要开发人员全面实施过一个软件或者完成过一个项目。经历的重要性在于,它能说明一个人的综合能力。从项目的性质、规模、难度,面试官可以大致判断面试官的综合能力。如果一个面试官已经在大公司负责过一个小模块的开发和维护,基本可以判断他不具备独立承担一个项目或者作为主要开发者的能力,只适合在另一个大公司做类似的事情。相关经验对于门槛高、长期技术积累的岗位尤为重要,比如Linux内核开发、JVM开发、游戏引擎开发、数据库实现、高级ux等等。对于这类岗位,没有经验的面试官即使综合素质再好,也需要长期的学习和积累才能胜任。所以基本上,如果你确定自己的岗位属于这一类,那么相关经验无疑应该是首选。换句话说,P(好工作|相关经验好)的概率很高。

通过项目经验判断面试官的素质比通过基础和算法测试更靠谱。所以面试时,面试官要多花时间听面试官介绍项目经验,进行深入的讨论和交流,了解面试官的知识、思维能力和表达能力。同时可以结合项目问一些基础知识和算法问题。比如面试官做过C++相关的项目,你可以问他如何管理内存。你熟悉智能指针吗?如果面试官的回答不满意,那么基本可以判断他的项目不是很好。

需要注意的是,经验也是一个多维度的东西。比如C++股票交易中间件系统,涉及三个维度:(C++,中间件,股票)。如果面试官A做过C++股票交易客户端,面试官B做过C股票交易中间件。从语言上看,A是最佳搭配,从项目性质上看,B是最佳搭配。你如何选择?这就是多维度中哪个维度更重要的问题。就这个例子来说,我个人更倾向于B,因为我觉得中间件开发的体验是主要矛盾,从C切换到C++不是问题。所以面试官需要判断哪个经历是首要的,哪个经历是次要的。比如我们在招安卓应用开发。这个职位的Android技术门槛并不高,其真正的难点在于做好用户体验(UX)。因此,如果面试官没有Android经验,我们可以接受,但我希望他有在UX的经验,至少做过其他平台的移动应用开发。

倾向

现在,我来说说我认为最重要的因素:性格。这对于很多刚接触面试官的朋友来说可能是不可想象的。性格怎么可能最重要?说实话,当我意识到这一点的时候,我自己都很惊讶!说白了,P(好工作|性格好)概率最高。我的实践经验是,一个人如果性格好,做好工作的可能性最高。好的性格远比好的基础和好的算法靠谱。

如果一个人技术上有缺陷,经验不足,但性格很好,在团队里别人很容易弥补,他也很容易逐渐弥补;相反,如果一个人的性格不好,所有的技术优势和经验优势都发挥不出来,甚至会产生负面作用,性格的缺点很难改变。我一直讲,实际工作需要的是综合能力,而在这种综合能力的发挥中,性格是非常重要的。项目不仅会遇到技术问题,还会涉及沟通协调。不同的人,不同的部门,既有合作,也有摩擦。如何处理这些事情,需要一个好的性格。可以说,让你在开发团队中与众不同的,不是你毕业于哪个学校,也不是你过去的经历,而是你的性格。

当然,性格是一个复杂的东西,包含了很多方面,并不是所有的都需要在程序员的面试中注意。我的经验是,我们可以关注这些方面:

1)积极或消极的态度。有些面试官在谈话中自然会给你积极的感觉,或者你可以在他的经历中找到他的积极因素。这些都不算太丑。相反,你可以明显感受到一些面试官的负面情绪。热情在工作中非常重要。积极的人能给团队带来活力,更容易合作。基本上,如果面试官确定态度积极,他通过我这一关的可能性会大大增加;相反,如果我决心消极,即使技术能力再好,也会非常谨慎。

2)智商。我的经验是,总的来说,聪明人在工作中表现更好。面试的时候不一定要找一些智力型的问题来测智商,像Google和MS,其实你只需要看他讨论问题是否有逻辑,思维和说话是否敏捷,就可以做出大概的判断。另外,眼睛是人们心灵的窗户。一个人是否聪明,眼睛会说话。但是,聪明也不完全是优点。比如一个公司或者一个项目遇到困难,往往是聪明的人先跑了,坚持下来的往往是智商一般的人。

3)语言表达能力。语言表达能力也是程序员非常重要的素质,关系到项目中沟通的顺畅。面试者可以看面试者能否用简洁的语言清晰地介绍自己做过的项目,抓住要点,并考虑听者的相关背景。一般来说,语言能力强的人,综合能力不会太差。

4)是否有用户意识。有人说程序员是搞研发的,那用户呢?只有销售和营销人员会和用户打交道。其实这完全是一种误解。如果你写了一个模块,甚至一个API,只要别人用了,他就是你的用户。有些程序员在设计一个模块或者软件的时候,总是习惯站在用户的角度去思考,这是一种很好的用户意识。用户意识好的人能更好地考虑他人感受和整体需求,而不是单纯从自身和局部问题出发思考。面试官在谈到过去的项目经验时,往往可以从用户的角度提问,从这个过程中观察其是否具有良好的用户意识。

5)如何应对质疑和压力。面试官要合理质疑面试官的回答和过往项目,看他如何回应。有一次一个面试官谈到玩游戏登录服务器的体验,于是我问“登录服务器挂了怎么办?他说虽然一开始没有考虑到这个问题,但是怎么改善呢?其实大家都明白,项目有各种不完美的地方,造成这种情况的原因有很多。只要你能坦然面对质疑和压力,努力往好的方向想,就不需要掩饰缺陷,也不应该有情绪。我见过一些面试官。一旦你质疑他们的项目,他们立刻变得叛逆,或者不高兴,或者拒绝承认有问题。很容易看出他在工作中没有质疑和批评的余地,这样的人很难合作。

6)性格特点。很多面试官喜欢在简历上写“精通C++/Linux”,让人麻木。如果有人写“像C++/Linux”,我会有一种眼前一亮的感觉。“精通”是不带感情色彩的叙述,而“喜欢”包含了面试官的个性,我更愿意看到面试官的个性。我相信对某件事的真正热情远比你目前对它的掌握重要。其实N年的经历告诉我们,同一个班的同学,同一个项目组的同事,每天的知识和工作都是一样的,但其实成绩和表现的差异是非常明显的。那么,本质区别是什么呢?其实就是每个人的性格。是个性让有的人业余时间打球,有的人业余时间看书,有的人喜欢Linux,有的人喜欢Mac。一个人在团队中扮演的角色也和他的性格有很大关系。面试官要引导面试官展现自己的个性,判断是否对团队有利。

摘要

最后总结一下,我的经验是:1)面试官的目标是找到一个工作出色的人,面试必须围绕这个目标进行。如果把面试当成算法或操作系统的期末考试,就会走入误区;2)面试过程是通过学历、性格、基础、经验、算法等可衡量的因素,综合判断面试官“好工作”的概率;3)在各种因素中,人格>;经验>基础>算法。性格是最重要的。性格不好,所有技术能力都会大打折扣,技术缺陷容易弥补,性格缺陷难以改变;经历反映了一个人的综合能力。你可以从面试官过去的经历来判断他能做什么工作,不能做什么工作。基本面和算法主要起到辅助参考的作用。基础好的程序员一般适应能力更强,学习新技术更快,但切忌单纯从基础来判断一个人的能力。