总结受浣花西剪录和射雕英雄传的启发,本文通过武侠小说中的人物和事件,对目前程序员面试的弊端进行剖析分析,试图给出一个更好的程序员面试程序。我猜你会觉得我在胡说八道,程序员面试和浣花洗剪录怎么可能有关系,但它们确实有关系,而且是很有趣的关系:古龙中期作品的两个故事浣花洗剪录这样的一个故事:东营白衣人为了追求武功,漂洋过海来到中原,挑战各路高手。他看到人杀人,佛杀佛,但紫衣侯也受了重伤,不久就死了。紫衣侯的子孙(也就是主人公)在哥哥紫衣侯的指点下,历经种种奇遇,学会了绝世武功。人打。相较于楚留香系列和陆小风系列,浣花洗剪录的故事情节并不精彩,但白衣人初来中原挑战各路高手——一个死人,我觉得还是很有意思的分枝:白袍男子眼中却流露出不屑之色,猛地后退数步,只见剑光一闪,随即收鞘,拔剑,挥剑,插入一剑,三个动作眨眼间就完成了。等八名清平宗弟子定睛一看,他的手中已经多了一根枯枝。原来,刚才他拔剑的时候,已经砍断了这根枯枝。只听他缓缓道:“拿去给你师父看看!”他转身就走,坐在树下的一块青石上,一言不发,仿佛安定了下来。在场的清平宗弟子,并没有察觉到这枯枝的特殊之处,但自家师尊却被这一幕吓了一跳:白三空眉头一皱,接过枯枝,先是随意扫了一眼,随即目光忽然落在了那道切痕上。枯枝,他惊呆了。后来,清平门弟子胡不愁将这根枯枝送给了中原武林宗师紫衣侯,以此激励他拯救中原武林。众人不知道枯枝究竟有何妙处,为何紫衣侯如此着迷,三四杯茶后,紫衣侯缓缓叹息道:“好高明的剑法!好快的剑法!”玄剑诀……”其他人不明白一根枯枝有多大的吸引力。紫衣侯解释说是因为你功力不够。灵儿却忍不住问道:“侯爷刚刚看过了吗?”看这根枯枝,就知道那人的剑法好不好?”紫衣侯道:“正是!”灵儿道:“你从哪里看到的?”紫衣侯叹息道:“你的剑法,我能有如此造诣,从砍下这枯枝便可见一斑。否则,我给你解释三天三夜,你也不会明白。”灵儿一愣,苦笑道:“看来我这辈子都不会明白了。”于是紫衣侯一剑七刺一人,将此人当战书递给白衣人:白衣人道:“这是什么战书?”虽然他无论看到什么意外都能保持镇定,但此时语气中还是忍不住露出惊讶之色。王半夏双手叉开,撕开岑邹的衣襟,只见他的肩膀上有七道剑痕,胸口处,伤口已经结了疤,一眼看去,和普通的伤疤没什么区别,只不过剑痕都在肩井、乳泉等大穴位上,纵横交错,路径清晰,而且还有剑痕之间,那淡淡的红线,仔细一看,也是被剑刃划过,白衣人不等王半夏说话,目光顿时被剑痕吸引,脚步一顿开始移动,一步一步的朝着岑邹而来,同样的,旁人无法理解这道伤疤有什么特别之处,白衣人却异常的兴奋:白衣人没有再看他一眼,挥了挥手带s尖的长剑字仰天,微微颤抖。白衣人的声音也微微一颤,抬头仰天道:“天地无边,终于有人可以成为我的对手了……”忽然他低头跪下,他的长长的头发披散在他的头上,他似乎在庆幸老天总算给了他一个对手,也似乎很佩服老天的力量,能够创造出一个可以与他一战的英雄!另一个故事出自金庸的《神雕侠侣》,郭靖和黄蓉去陆家庄时,裘千丈(但大家都以为他是裘千仞)嘴里冒着烟,手掌捏碎砖头等“绝技”身手”让所有人都觉得他身怀绝世武功,口中冒烟,壮壮生怕自己再不去,这人又开始撒娇,还得吓着裘千仞,所以连忙吩咐庄鼎放轻脚步扶他过去,低头将一张窗纸从黄蓉弄出的小洞里塞进去。我不禁惊叹。只见裘千仞盘膝而坐,双目微闭,口中不断吐出缕缕青烟。裘千仞起身走进了院子,回到座位上的时候,手里已经拿着一块砖头。他手里没怎么用力,却听得哗啦啦一声响,两块砖碎成小块,他再用力一捏,碎片化作粉末,哗啦啦掉在桌上。桌上四人顿时惊得脸色发白。但“绝技”并不是真正的技能。就连当时的初出茅庐的郭靖,也是一掌将裘千丈打得落花流水。飞:裘千仞见他左臂扫来,道:“拿我手掌来”,心想:“你臂上有拳头,谁不知道?”抱住他的胳膊,来了撞到他的左臂。谁能想到,郭靖的这一招“斗龙斗地”是降龙十八掌中非常玄妙的一招,左臂右掌可真可假,不僵硬,当敌时挡住他的左臂,右掌猛地一扬,同样轰的一声,就在他右臂与胸口相连的地方,裘千仞的身体如同风筝断线一般,直飞出了门外。后来大家才发现,这个“裘千仞”是个冒名顶替的人:嘴里冒出的烟是他点燃了毛,藏在袖子里吸,又吐出来;隐藏的赌注。程序员面试你可能想知道这两个故事和程序员面试有什么关系。还是拿白衣人来说吧:东瀛修的是绝世武功(在学校学的功夫);去中原挑战英雄(即将毕业并开始求职);拔剑斩枯枝。实战本(写简历并进行面试);惊动中原武林高手(投简历/面试);决战海战名扬天下(getanoffertogetajob)。写到这里,不用说,你也知道为什么会提到金庸小说中略带滑稽的人物邱千章了。对应一个程序员,这大概是一个简历很华丽,面试时口才很好,能流利回答一些面试常见问题的人(因为他查过题库),但在实际工作中却错误百出。毋庸置疑,没有哪个公司愿意招到仇千丈这样的“高手”,而像白衣人这样真正的高手,更是任何公司的梦想。那么问题来了——如何认定一个人是像白衣人这样的真正的高手,而不是邱千章这样的“高手”?你永远不会明白,浣花洗剑录中有这样一个细节:灵儿忍不住问道:“莫非,侯爷光看这根枯枝,就能看出此人的剑法高低?”紫衣侯”曰:“正是!灵儿道:“你在哪里看到的?”紫衣侯叹息一声,道:“你的剑法,已经达到了我的境界,从这枯枝的砍痕,便可窥见一斑。”不然,我跟你解释三天三夜,你也听不懂。”灵儿一愣,苦笑道:“看来我这辈子都弄不懂了。”据我所知,有些公司把程序员的招聘决定权交给HR,无疑是最愚蠢的决定。HR和猎头可以根据求职者过往的经历来判断程序员的背景,推测程序员的能力,但是就像灵儿是看不到干涩的一样。分支、HR、猎头之谜无法识别程序员的能力(除非他们之前也是优秀的程序员)。最好把鉴定程序员能力的工作交给程序员。优秀的程序员通常至少需要同样优秀的程序员去发现。但是即使程序员自己去面试程序员,也还是有问题,就像射雕群侠传中邱千章忽悠群雄一样。在《神雕侠侣》中,仇千丈“表演”了漂浮在水面上、嘴里抽烟、手指轻拂酒杯、手掌捏碎砖头的“绝技”。要是被人识破,若不是郭靖这个混蛋傻乎乎地冲上前比划,只怕大家还要继续上当。回到程序员面试,大部分的笔试/面试题都可以在网上找到,甚至有的公司为了省事直接在网上搜题,这就导致程序员面试看似高门槛其实已经变得很low了——找一份好工作不需要系统学习计算机技术一两年,只需要一两个月刷leetcode、CareerCup、无名求职板上的题。原本差别很大的算法题目也变得一文不值——谁知道是自己想出来的还是背的。就像用轻功浮在水面上一样,谁知道你的功力是不是真的高深,还是提前在水底做了个隐蔽桩。所以算法题是一个很尴尬的存在——为了检验程序员的水平,不考算法题是不可能的,但是一旦考了算法题,求职者就可以通过背题来答题,使得检查毫无意义。面试官接下来会找更难的题,但是面试题的数量无法和求职者的数量相提并论,所以***还是会陷入这种做题-背题的怪圈。直接的结果是,公司招了一票“仇千丈”,而一些水平不错但不背题的程序员则被拒之门外。没有别的办法吗?我觉得不是,还是说说浣花溪涧录中的枯枝吧:#p#浣花溪涧录中,白衣人赴中原挑战群雄。他没有施展漂水或嘴里冒出青烟的华丽“绝技”,只是为了砍断一根枯枝作为战甲。然而,这根在众人眼中再普通不过的枯枝,却让中原宗师紫衣侯大为震惊:众人不知道枯枝有什么好,紫衣侯为何如此痴迷它,并通过了三四盏灯。茶歇间,紫衣侯方子缓缓叹息一声,道:“好高明的剑法!好快的剑法!好高深的剑法……”重剑无锋,灵巧得不行。编程也是如此。编程能力不一定需要通过复杂的算法来体现。程序员面试需要考察深度。这里的深度是程序员对编程和编程语言的理解,也是他在多年的编程经验中得到的感悟。这么说还是很玄乎,所以我在这里举个例子:这道题恐怕是你见过的最简单的面试题——用C语言把字母转大写,不能用库函数。以至于很多面试官听到这个问题的第一反应是:不过我不是故意开玩笑的,你可以试试用C写个大写转换,然后继续看这篇文章。比较有意思的是,有的受访者是这样回答的:#includeintmain(){charc='a';printf("a的大写是%c\n",c-32);return0;}其实如果这样写像这样就不用再问了-_-#当然很多面试官比较靠谱:chardaxie(charc){returnc-32;}这时候我会建议面试官不要用拼音命名,并且会提示输入的字母不是小写程序怎么办?一般来说面试官这时候会引入范围检查,但也有人会这样写:charto_upper(charc){if(c>='a'&&c<='z'){returnc-32;}else{printf('Inputerror!');return0;}}要这样写就不用再问了(个人怀疑是看谭浩强学的C)-_-#比较靠谱部分面试官会给出这个答案:charto_upper(charc){if(c>='a'&&c<='z'){returnc-32;}returnc;}这个已经很接近我的及格要求了,接下来我会问面试官是否他可以提高它的可读性(Readability)。有些面试官会命名上下文章节(比如将参数c重命名为input):charto_upper(charinput){intoffset=32;if(input>='a'&&input<='z'){returninput-offset;}returninput;}这时候我会提示这个奇怪的32能不能去掉。一般来说,能到这一步的面试官可以回复:charto_upper(charinput){if(input>='a'&&input<='z'){returninput-'a'+'A';}returninput;}这是我的通过要求。一般来说,我会提醒面试官他们是否可以继续提高可读性,但不幸的是,到目前为止,没有面试官能在这一步给我一个满意的答案:charto_upper(charinput){if('a'<=input&&input<='z'){returninput-'a'+'A';}returninput;}其实就是用'a'<=input&&input<=input="">='a'&&input<='z'——这个技术来自代码百科全书,其中有一个专门的部分介绍如何编写可读的布尔表达式。从这里可以看出,这些受访者都没有看过代码百科全书。考虑到代码百科几乎是编程的必读书籍,我可以推断,这些面试官很可能没有阅读的习惯,一般不阅读的程序员也不会太优秀。刚才说到这里,我刚过及格线(如果你能写出可读的布尔表达式,我会在心里提前给你打个优分),然后我会问我能不能进一步提高性能,少数面试官会在提示时想到使用数组:charto_upper(charinput){staticcharconvert_table[]={...};returnconvert_table[input];}如果面试官能提到他从C语言标准库学到的这个技能,加10分:-)有的面试官会想到用宏:staticcharconvert_table[]={...};#defineTO_UPPER(input)convert_table[input]这时候我会问宏的优缺点,这里使用宏不会出错。简而言之,就是要确保面试官真正理解宏,而不是从某个地方死记硬背一个答案(比如编程之美之类的面试书)。有的面试官一开始会直接给出使用数组+宏的最佳方案(我几乎可以确定他已经背过题了),然后让他给出一个函数+非数组的实现。如果他写不好这个功能,他还是过不了。也许你认为它就在这里,但它不是。考虑C语言的EOF(即-1)和to_upper的应用场景。下面的代码会发生什么?charc=to_upper(getchar());如果getchar()返回EOF,由于to_upper接收到的类型是char,如果系统的char是unsigned,就会出现转换问题,这就是为什么toupper函数签名中的C标准库(ctype.h)是inttoupper(intc)而不是chartoupper(charc)。接下来我们来回顾一下这道简单的题都考察了哪些要点:函数的概念(而不是写在main中);缩进和命名(而不是拼音);使用可读文字('a'-'A'而不是32);API设计(to_upper接收到非小写字母应该返回什么?0?报错?还是返回原值?考虑到to_upper的应用场景是将字符串中的小写字母转为大写,显然更合理返回原始值);是否有阅读习惯(至少可以看出自己是否认真阅读过代码百科);是否阅读过C标准库的源码(指出toupper数组的实现来源);数组的使用(使用转换表);理解宏,以及宏的危险(使用宏);你有没有背过这道题(给出最晚用array+macro的最佳解法);EOF和C标准库风格。接下来我也会请面试官测试这个功能,并给出测试代码,这里就不赘述了。这个题目和浣花洗剪录里的枯枝很像——看起来很简单,其实不简单——每个人都可以剪一根树枝,长什么样子又是另外一回事;每个程序员都会写大小写转换,但是写到什么程度就是另外一回事了。我觉得这种题目最适合程序员面试了:看似很简单,做起来却很难;可以反映出很多问题——比如大写字母和小写字母转换的问题,至少反映出10个问题。.不像复杂的算法题,不会让面试官卡住(或无从下手),从而避免一些经验水平不错的程序员被误拒;它没有标准答案——所以即使面试官把问题放到网上也不会有丝毫影响,因为面试官的评价标准对面试官来说是不透明的;死记硬背是没有用的——这样才能保证不会招到“仇千丈”这样的应试程序员;可能有人会问,既然有很多好东西,为什么这些公司还要用复杂的算法题作为面试题呢?我的回答是排除对算法的盲目崇拜,因为这样的题很难出,而且对面试官的要求很高,所以大部分面试官都选择在网上搜索问题,而不是自己提问。.殊不知,这条捷径正是人才招聘失败的根源——优秀的程序员因为不背题而被拒绝,而平庸的“仇千丈”因为背题而被录用。这些被聘用的“仇千丈”,又会用同样的手段招揽下一批更差的“仇千丈”,讽刺至极。结论招聘程序员的决定权应该掌握??在程序员手中,而不是HR;优秀的程序员通常至少需要同样优秀的程序员去发现;复杂的算法题是一种非常糟糕的评价程序员的方式;面试面试官应该自己想出问题,而不是在网上搜索现成的问题;面试官(和公司)应该花大量时间在程序员面试的问题上,拒绝以假乱真,保证招聘质量。多于。
