谈谈如何在面试中发掘程序猿的核心竞争力zz
早两天看了知乎日报的这篇文章《什么是程序员的核心竞争力?》,caoz讲的几点是让我感同身受。这让我联想起了给程序猿的面试,其实也就是通过短暂的接触来发掘程序猿的核心竞争力。接下来我就谈谈我是怎么给程序猿面试的,当然每个公司每个面试官都有自己一套方法,如果觉得我说的有什么不好的,欢迎在评论中跟我讨论。
简历中的核心竞争力
简历是让面试官对你有一个初步印象的介质,每个面试者都应该花点时间研究如何让自己的简历成为一块敲门的金砖。
要方便招聘网站检索
现在大部分人求职都是通过招聘网站,除非是内推这种形式。在简历到达我手里之时,是经过人事部门刷选的,而人事部门的同事对程序猿技术的了解,基本上是通过关键字。作为一个程序猿,查阅资料是必须的,因此,你必须精通信息检索。我跟大部分的程序猿都聊过,基本要写出代码,或者解决疑难杂症,基本是离不开搜索引擎,更有人放言,“离开了搜索引擎,我写不出一句代码”。也有不少人都表示,绝对不去不能上网查找资料的技术公司。搜索的技能在现代的编程中如此重要,那么,通过搜索技能我们可以大致判断一个程序猿在写代码上的水平——这并非是无稽之谈。如果一个程序猿掌握了搜索的技能,那么你应该知道,如何让你的简历顺利通过人事部门的刷选,毫无疑问,这就是展示你其中一个核心竞争力的方面。比如,你想找IOS开发的岗位,但是你的简历中没有一句是关于IOS或者APP开发或者其他有关手机开发的关键字的,即使你拿了几个M$的MVP,即使你是架构设计上的大牛,估计也很难通过人事的筛选。尽量在你的简历中体现出你要应聘的岗位或者所需的技能的关键字,是一个好的习惯。
展现你的学习能力或者项目经验
如果你是个应届生,那么我会关注你所学的课程,所在学校,是否做过一些项目,或者在相关的技术社区或者开源站点中活跃。对于应届生而言,项目往往是薄弱的环节,但是如果你能充分的展示你的学习能力,那么将是最能够吸引面试官的地方。作为一个程序猿,你必须得不断的进行技术充电,要时刻紧跟技术的潮流,否则就会非常容易被时代所抛弃。无论你是想深入学习底层,或者是不断追逐最新的技术,这两种人都非常具有市场,但是,这两种方向,对学习能力要求都非常之高。前者要求你能够静心学习,有较强的悟性;或者要求你有较快的学习能力,并能够快速消化新的知识。
如果你是个有多年经验的程序猿,那么,你应该充分的在简历中展现你的项目,介绍项目的功用,应用的技术,你们解决的难点,你承担的责任。通过项目描述,往往能够发掘一个人的技术广度和深度,同时也能够反应你在过去几年中的成长,而项目中语言的表述,往往也能反应一个人的组织能力。如果我是要招一个架构师,那么你简历中从来没有担任过主程,也没有独立设计过一个系统,甚至对你从事了几年的系统都表述不清楚的,技术也含糊不清,那么我还怎么有兴趣对你面试?
平时招聘时,我都会先扫描一下程序猿的简历,然后做出初步的判断,没错,这就是第一印象,它虽然不能立马决定你这个人,但是基本上能够影响我接下来面试的心情。
大体的流程如下:
读书,写博客,参加开源项目其实是一个很好的习惯,也能让你的简历更加丰富多彩。
笔试中的核心竞争力
有些程序猿认为笔试毫无作用,有些人认为笔试的题目毫无作用。确实,我从来不认为可以通过笔试题目就能为公司招来一个性价比高的开发人员,而且有很多面试题我觉得出的根本毫无意义,尤其算法类的,为什么这么说?有多年工作经验的程序猿都有这种感触,算法在实际编程中用的其实并不多。算法重不重要?非常重要!但是,大部分的时候,我们只需要了解算法的效率,是干什么的,大概能在什么地方用,就已经完全足够了。很多现代的编程语言,都已经内置了许多的算法,而其他很多不常用的算法,网上也有了足够的讨论和现成的类库,如果你不是专门搞底层开发,图形类算法的,没有必要花费太多的精力在算法研究上,所谓术业有专攻。
我举个例子,我在工作中遇到了一个问题,如果有非常大数据量的数据需要绘制曲线时,曲线的绘制非常非常慢,因为有大量的数据点要去渲染,而且绘制出来的曲线时密密麻麻的,很难反应趋势。后来我是怎么办的呢,我研究了下,我们是否可以通过减少非关键点来压缩曲线,只需保留有关键特征的数据点即可?但是怎么压缩,我并不会,也没有理论支持,最后在网上搜索曲线压缩”,立即得到相关的算法,用上去之后,曲线描绘的速度大大的提升,而曲线的趋势又得到了保留,非常完美的解决了相关的问题。
但是,我认为笔试题目还是很有意义的,它的意义在于,能够从侧门反映你对基础知识的了解程度,更重要的是,可以从做题的过程反映你这个人的一些编程的细节,面对困难的解决思路,以及基本的逻辑思维。
注重细节
我们有道题目是这样的:
struct Node
{
string name;
List<Node> children;
}
void Travel(Node root);
Q:函数说明:root是一棵树的根节点,Travel函数可以遍历该树的所有节点,并打印出每个节点的name。
非常非常的简单,但是,很多有经验的程序猿答的并不好。完成这道题可以采用递归的方式,遍历子节点并完成打印,但是中间有个细节是List<Node> children
是一个引用类型,在使用是必须先判断是否为Null
!我看过很多人的试题,大概有60%的人会忽略掉这个细节。而实际上这些人在工作中也真的会写出这种没有任何健壮性的代码,导致程序在使用到非正常数据的时候充满了BUG,每当看见这些代码我都非常非常的头疼,并且不止一次的强调,但是这些人还是没有这种意识。
如何应对困难的处理能力
我们的笔试题目分布也非常有意思。前面两题是一些概念的阐述,紧跟着是考一些细节和简单的算法,然后是一到比较难的算法题和一道全部是英文的ACM算法题,最后是一些TCP和数据库的题目。为什么这么分布呢,我们知道笔试一般都会限定一个时间,我们之所以把难题放在中间,其实就是考虑这个人是怎么面对在工作当中的困难的。
我一般都不会期望面试者能够把所有题目都在有限的时间内完全答出来,但是,你必须要把简单的题目认认真真的回答完,不会的题目要大致的写下思路。
有的人没有一种全局考虑的思维,喜欢一路往下做题,然后和难题死磕,解决导致完成一份试题耗费非常多的时间,最后没有完成,剩下的题目也草草写一下完事。在企业中开发,如何正确的做事比你能够把事做完要重要得多。我遇到过很多的程序猿,都是非常的有能力,但是往往在开发中,会让整体的开发计划偏离甚远,甚至最后无法完成既定的计划。不是能力的问题,而是做事的方法不对。
曾经我让同事负责一个功能模块的开发,产品给出了具体的需求,他粗略看了下之后估计个一周的时间。结果在做的过程中,发现了有很多不完善的地方,然后自己在那里埋头苦干,研究一些非常细节的解决方案。3、4天之后我问解决了没有,他说,这个不行那个不行,这个要几天那个要几天,最终说要多一个星期。开发往往是跟预期对不上的,我也理解。结果下个星期又说不行,然后其他项目事情来了,最终一个月内也没有把这个事情完成。这同事在这当中出现了什么问题呢?
- 开发前没有认真审核
- 没有正确的预估困难
- 出现困难之后不知道灵活变通,先让计划正常运转,把一些困难放在后续的交互中
- 过于在意细节
当然,我不是说我们不应该解决困难,或者不应该完善程序的每个细节。我只是强调做事的一个基本流程,在适当的时候跳过困难以免计划偏离太大,要把更多的细节放在后期完善。为什么这么做呢,因为整个系统不是你一个人在做,还有其他配合的程序,以及测试,如果你在这里卡壳,那么会造成整个计划的无法实施,我们可以预留部分的问题,在计划的最后进行补上。另外,罗马不是一天建成的,QQ也不是在刚开始就安全性这么高,搜索的体验这么好,也没有什么匿名发言之类的,我们很多的细节其实是后期慢慢完善的,如果一开始就太过在意细节,那么往往导致我们没法把事情顺利的完成。再退一步来说,你现在考虑的细节,就一定是满足以后客户的需求的?你能保证你现在想的东西以后一定是不会发生需求变更?
面试中的核心竞争力
面试也是非常有意思的一个环节。有些面试官很喜欢问一些***钻的问题,这个算法怎么实现,那个设计模式会不会,然后揪着某个细节批评人这不行那不行的,完全不考虑别人的想法。我觉这种情况纯属是平常工作苦逼想在面试中寻求存在感的,这种企图通过一些实用性较低或者较为生僻的难题来考察求职者能力的,属于极度偷懒且不负责任的做法,这种面试官缺少对人才发掘的能力。招人的本质是什么,是找一些在各个方面都有比你强的能力的人组成一个团队,相互弥补各自不足,从而发挥1+1>2的作用。如果你要找比你专业能力强的人,那有什么理由问他你擅长的地方?而作为一个管理者或者领导者,应该要有足够的智慧对你手下的人做的取长补短,我们完全没有理由揪着别人的短处问个不停,甚至因此而判断这个人的能力有所欠缺。
在我之前的博文,也有这么些人总是忽略我提及的上下文环境,上来就一通说你这怎样怎样不行,到底怎么不行,他自己也说不清楚。我面试,从来都是从应聘者的项目着手,跟他们一起探讨项目的实现,以及相关的技术,从中真实的了解到这个人的真实水平,而不会在意他是否了解某个算法,是否知道C#的扩展方法怎么写。
要在你擅长的地方做到精通
我喜欢面试别人的长处,一个人如果能够在他熟悉的领域、项目能够做到精通,那么这就足以说明了你的能力。大部分的程序猿其实是宅男,在与人沟通方面或多或少都有一些障碍,当然,在网络中除外。但是一旦说到他擅长的地方,他就会非常的健谈,并且会一直捍卫他自己的观点,在这个领域,他会觉得自己就是神。我有一个同事属于这类人,平常交流起来是有点困难,但是做事非常的麻利,说起他的软件和相关的技术,你根本就插不上嘴。平常交代的事情,都是很快又高质量的帮你完成。
上个月我面试了一个程序员,看简历以及试题,做的都一般般。但是我在面试的时候,这个程序员表现的非常的活跃,给我详细的介绍了他过去一年所从事的一个系统,他只负责其中后台的一个通讯模块,但是他把整个系统的工作机制,以及相关的技术还有选择这些技术的原因跟我做了详细的描述,并把相关的体系架构在纸上画了出来。我当时就觉得这个人是非常有学习能力的,问了他的薪水之后,立马就跟人事拍板说就他了。不过可惜的是,后来这个人给其他公司要了过去,他的薪水比在原来公司整整翻了一倍(比我们公司多了2k,主要是因为预算的问题而没有坚持录用)。
注重编程思想
我一直都认为编程的思想比编程的能力重要。
一个人的编程思想有很多因素构成:对产品的认识,对细节的要求,解决问题的思路,与人沟通的能力,调试的技巧,业务的了解和抽象能力,架构能力等等……
有人说了,与人沟通,也是一种编程的能力?是的,编码只是一种编程能力的最直接的体现,但是影响你编程结果的,编码仅仅只是一小部分。有些人不擅长和人沟通,往往做出来的东西和需求方相差甚远,不但影响了工期,还给用户带来非常不好的印象。还有对产品的认识,对事物的认识,也经常能够影响一个软件的好坏。我举个非常简单的例子:我们现在的软件要求的功能是越来越丰富,定制化的程度也非常之高,但是真正给用户使用的功能,其实并不到软件整体功能的20%,这就是著名的二八定律。了解这个有什么用?了解这个就能够让我们分清楚重点,可以集中精力把用户需求的最重要的部分优先完成,并努力做到最好,这样,我们就能够在顺利按计划把项目完成,因为即使中间有偏差,这80%并不常用的功能,也是在客户的承受范围之内。
所以在面试中,我非常喜欢问的是:你印象最深的项目是什么?你在这个项目中学到什么?你如何解决这些问题的?你们开发的流程是怎样的,你怎么看待你们的这些流程?你是怎么确认你理解的需求跟用户一致的?你是怎么保证你的开发计划是顺利进行的,如果开发计划不能顺利进行你会有什么办法解决?
还有一个是调试的能力。优秀的程序员区别与普通程序员最大的一个特点就是调试能力。调试能力是一种非常综合的能力,不但要熟悉调试工具,还要了解各种问题,了解语言特点。如果你具有优秀的调试能力,那么在开发中将会比一般的程序员更为高效,解决问题的能力也非常之强。
我们之前遇到过一个问题,我同事更新一个版本之后,偶尔会让程序发生以下错误:
因为我们的程序都有对未处理的异常做一个最后日志的记录,但是这种异常是无法记录的,这个同事看到这个问题可能心里就觉得比较棘手,但是项目又催的很急,于是跟现场的同事各种调试,加各种日志,折腾半天。下午的时候我问起这个问题,还说这种偶尔出现的异常,可能是第三方控件的一些BUG。我听了,觉得就有点不对头,这种对待错误喜欢归结于外部原因的态度,很可能就导致这个BUG会迟迟不能解决,最终会影响这个项目的验收。于是,我仔细把上面这个异常看了下,一下就发现了这个:System.StackOverflowException
。然后我查看了最新提交的代码,发现其中新增了一段代码,而这段代码使用了一个递归。我马上就判断,90%是由于这个递归引起的,而且是在一些特殊的数值中会引起这个问题。很快,我同事根据这个判断重现了BUG,然后花费30分钟就修复了BUG。
我相信这个同事肯定是看到这个BUG的,但是,他可能敏感性不强,而导致忽略了这个BUG,另外还有可能是因为平时没有注意把递归和System.StackOverflowException
关联起来,导致浪费了几个小时。要是我不及时去了解,可能会花费一天或者更多。这就是编程的思想在实际工作中所起到的作用。
在面试中,我一般都会设计一些小的例子,让面试者看看是否存在一些BUG,或者干脆提出一个开放式的问题,让面试者设计一个日志记录器,看看他到底会考虑哪些因素,从而判断他是否掌握了相关的调试能力。
专注并自信
最后,我想说的是,面试是一个非常主观的事情。你从上述文字应该也可以看出,我的面试,其实就是我个人的想法,我对跟我共事的同事的一个要求。其他公司或者其他面试官,或许又有其他的要求。但是,这都没有关系。你只要在你的领域有足够深入的了解,而且又有解决问题的能力,那么,你总会找到自己想要的工作的。如果你暂时没有找到,只能说你还没有遇到你的伯乐。就像我们公司一样,拒绝你,或者是因为觉得公司的要求或者方向不适合你,或者是因为公司给不了你这个薪水。无论哪种,都不是因为你的能力的问题,我们没有理由沮丧。优秀的人在哪里都能做出优秀的成果,但不是在哪里都能做出伟大的成绩,我们应该要有足够的耐心等待。
我们在来回顾一下面试中有哪些地方是体现程序员的核心竞争力的,看到结尾的或者直接拉到结尾的,就请默默点个赞吧:
-
简历
- 检索能力,解决问题的能力
- 学习能力,组织的能力以及整体思维
-
笔试
- 编程细节
- 面对困难的能力
- 做事的方法、态度
-
面试
- 技术的深度和广度
- 对项目的了解程度、做事的方法态度、学习能力
- 编程的思想:产品、细节、业务、沟通、架构、调试