专栏名称: ImportNew
伯乐在线旗下账号,专注Java技术分享,包括Java基础技术、进阶技能、架构设计和Java技术领域动态等。
目录
相关文章推荐
芋道源码  ·  线上问题排查指南 ·  2 天前  
Java编程精选  ·  前微软员工吐槽:如果严禁企业996,那么大部 ... ·  5 天前  
芋道源码  ·  Spring Boot3集成 ... ·  5 天前  
51好读  ›  专栏  ›  ImportNew

初级开发者面试中的不合理问题

ImportNew  · 公众号  · Java  · 2017-05-20 12:01

正文

(点击上方公众号,可快速关注)


编译:伯乐在线 - Ivyw

如有好文章投稿,请点击 → 这里了解详情


我有很多初出茅庐做开发的朋友,其中一位给我讲了他在应聘 Ruby 初级开发工程师时的事。下面就说说我和我的一个朋友是如何解决这个面试题的,两个高级工程师来解决这个初级工程师的面试题,显得有点大材小用,但结果令人出乎意外。在这个领域我还是有点见解的,我会详细描述一下我的解题思路。


面试题


那个面试的朋友需要在 30 分钟内用 Java 实现一个链表,他的第一反应是小菜一碟,我也一样。即使是对没有 CS 学位的人来说,链表也是一种很通俗易懂的数据结构。


链表是含有一串节点的链表,每个节点带有一个指向下一个节点的指针,这样你就大概能清楚它的工作过程了:插入节点时前后节点的信息和引用前后关系的指针都会发生改变;删除节点时移除这个节点和它的指针即可;查找节点时按顺序查看指针信息直到找到你需要的那个节点。如果你大学是 CS 专业的,那么这可能是你最初接触到的非嵌入式数据结构。链表的用处很大,C 语言的标准库为接下来的编程工作提供了必要的支持。


对初级开发人员来说这是一个很好的面试题。这个试题涉及了算法技巧,但没有 CS 专业学的那么深奥。其次,这也是非常切合实际的编程测试,因为工作后你肯定要写代码、调试、输出并运行代码。你不会被点名去白板上写点什么来展现自己的能力,这不是白板编程。



我很好奇,为什么那个朋友对这样的面试感到困扰,随后他说出了这道题目的附加条件:面试官希望这个链表能符合 List 的特性。我立马被这道题的复杂性吓到了,完全不像一开始的毫不在意。


救命


可能有人对 Java 标准库接口了解不多,所以让我来普及一下 List 。List 是 Java 的泛型接口,可以用来实现包含很多相同数值的有序集合。这是一个功能强大的接口,提供我们可能会用到所有的定位列表数据类型。它有 25 个公共方法,其中两个方法返回另外的接口含有12 个公共方法,也就是说,你在实现过程中需要构建和测试 37 个公共方法。其中 t 意味着这是一个泛型接口,数据类型没有限制。这简直太荒谬了,而我的朋友仅有 30 分钟的时间来解答。


那么,这个问题是否适合那些经验不足两年的新人呢?当然不适合,而且相当不合理,我就“严肃认真地分析下”(我可以好好施展一番了,我对自己还是很有信心的)。我可以很轻易地完成这项任务,毕竟我是一个“资深”的开发人员,我这半辈子都在和 Java 编程打交道,虽然对工具有些生疏,但领悟很强。只是我不值得为这个任务花费太长时间。


然而这还不够,我们还要精益求精。Pair programming (结对编程)是我最喜欢的一种工作方式,可以协助我们更快地完成工作。你需要向同伴解释自己的思路,当你累了还可以得到同伴的帮助。所以,我找到 Stephen Best 来一起解决这个问题。前20分钟我们没有安装工具,而是做出问题草图、搭建测试环境等等。我们假装是在面试环境中解决这个问题。


很快我们就开始了。Stephen 曾和我一起工作了6个月,其中有三分之一的时间都是这种模式。我们使用 TDD 工作流程协同工作。


首先我们用 Eclipse 自动生成完整的界面框架,然后准备开始实施了。不幸的是,我们没有意识到这个任务的艰巨程度。


这个过程的艰难险阻,简直难以形容。List 接口有个好处,你可以在一些方法之上实现另外一些方法,但 List 接口的复杂度太高。大约 6 小时后,我们放弃了,我们失败了。我们非但没能在 30 分钟内完成实施,我们根本没法解决这个问题。


我们使用了 listIterator() 方法,它必须返回一个 ListIterator 对象并声明注销时间,但是当你几乎快要完成一个复杂接口时,不知道又从哪冒出另外一个。


我们所有的基本操作都已完成,并具有良好的测试覆盖率。我可以指出实现 List 所必须的但 Java 类型系统无法支持的部分,这些部分留给实施者去实现就好。我们没有做范围检查的接入,当你查询任意位置的元素时会报空指针异常,而不是提示范围错误。我们跳过这部分是因为这不是必要的而且我们时间有限。


我想象不出那些初级开发人员在遇到这样的问题时脑袋里会想什么。这是一个 Ruby 的开发岗位,我搞不懂为什么让一个新人去实现如此复杂的接口。当然,很多面向对象的想法可以从 Java 移植到 Ruby,也许这才是面试的侧重点。我和 Stephen 能够承担这项任务的唯一原因是我很熟悉如何构建 Java 通用系统。当你写出如下代码时:


private A reduceNodes(A accumulator, NodeCallback callback) {


其中涉及一个类类型参数、一个方法类型参数和一个匿名回调接口,好像并没有用到 Java 语言。这个命令可以让后面的实现更简单直接,在面试中这样做的话,我很确定面试官一定会很困惑。如果 Stephen 和我这样解答的话,可能无法通过这次面试,这是个危险信号。


继续上面的话题,这究竟说明了什么。这是一个压力面试,面试官给出一个问题,而很显然求职者无法在规定的时间内解决。再次重申一下,我很肯定没人能在 30 分钟内实现 List 链表。这很不公平,那些擅长某种思维的人才会被过滤掉,因为平常很少有程序员会遇到这样的测试。更糟的是,这会打击很多人的信心。下一节中,我们将探讨一下这样给初级开发人员带来的影响。


常春藤 CS Shibboleth


如果一个面试题无法筛选出合适的应聘者,那它还有什么意义,难道是要看应聘者面对无法解答的问题时的反应么?与其这样,还不如选一些合适的面试题,可以让面试官判断出应聘者是否成功解决了问题。


人类很奇怪,喜欢建立部落群居生活。部落是史前最接近现代社会(在地理意义上)的人类群体。这意味着他们是很接近我们的人,我们都喜欢进行筛选。给面试官主观决定的权利意味着他们会选择最接近他们的人。这就是为什么很多公司用白板编程的方式筛选应聘者,那些从名校毕业有 CS 学位的求职者在白板面试环节表现出色,这应该是好学历的特权吧。


有个问题不得不提。在过去几年中,非 CS 专业(考虑到我们这个行业兴起的年头,称之为非传统似乎有点可笑)的技术人员大幅增加。这些初级程序员大部分来自训练营。训练营不会教你如何构建红黑树或如何用 C 语言实现哈希表,他们没必要教这些,因为很少有学员毕业后会用到这些。这并不稀奇,因为当我开发 Rails 应用时,我的 CS 学位根本没有任何帮助。


白板编程面试在大多数情况下是很令人苦恼的事。我自己也经历过很多次,而且从来没收到过回信。我是一个拥有 CS 硕士学位的顺性男,所以,至少在这件事上「选择像我们这样的人」的准则似乎没有奏效。我认为白板编程面试与大多数人的实际工作内容是相背离的。


我发现一些问题,因为人们认为从事这个行业要有 CS 学历才可以,所以很多初级技术岗位并没有考虑训练营的学员。这样做有害无益,特别是在行业多样性方面。据我观察,训练营的学员比拥有 CS 学历的人涵盖更广泛的社会阶层,而且训练营的费用肯定比美国的「常春藤联盟」大学少得多,当然还有英国类似的大学(抱歉,英格兰中心论的读者)。合理的学费也有助于实现(但不完全)民主化和权利平等。


我听说很多训练营都有专门的课程,教初级开发者用死记硬背的方式学习白板编程,用他们不理解的数据结构来操作指针、构建 rails 应用程序等等。如果没有这些课程,在面试时 CS 专业的人就会更吃香。我也面试过很多训练营的学员,跟 CS 专业的毕业生比起来,我更倾向于雇佣前者。


因为,训练营的学员:


  • They’re a thing (他们有能力)

  • 他们确实很优秀。

  • 如果你想招一个初级 Ruby 开发,找训练营毕业的是不错的选择。


面试除了要找到合适的人,你也应该为应聘者留下一个良好印象。如果你给他们出一些不可能完成的白板问题或编程任务,可能直到面试结束后他们都会感觉很糟糕。如果他们接受这份工作,面试时的压力也会一直伴随他们,这样的雇员雇主关系可不是一个好的开头。


资深开发者的面试趣事


我想讲一些关于「资深」开发人员的面试,有我自己的经历,也有别人的。据我观察,这个级别的招聘基本没有白板编程环节了,甚至(但并不总是)完全不用写代码了。这些面试过程大多是以双方进行某种技术讨论的方式进行。我发现,有时应聘者可能比面试官更老练。因此,面试官很愿意倾听应聘者的想法,并礼貌地询问处理某个问题的方法。


对我来说这种形式的面试好得多,白板编程对我来说就是地狱。因为我并不擅长,如果一个面试是以白板编程的方式来进行筛选,那我肯定没法通过。我的好友 Justin Searls 也有同样的顾虑。尽管这样,大多数与我合作过的开发人员都认为我是很有效率的。如果某些技术牛人因为无法解答你给出的问题而面试失败的话,你就需要反思一下是不是面试方式出了问题。


我们可以采用技术讨论的方式展开面试。求职者会感觉很轻松,他可以表达自己的观点,还有机会纠正前面犯的错误,倾听面试官并给出回应,这个过程可以加深双方的了解。沟通是程序员需要学习的最重要的事情。计算机出现的所有问题,归根到底都是人的问题。这样的面试方式才会让求职者感觉很舒服。


求职者表达自己的见解,面试官倾听并给予回应。这个过程可以检测出双方是否适合在一起工作,双方是否会在自己犯错时让步,与此同时展示一下平常的工作状态。


最重要的技术工作都是在良好的沟通下完成的,因此,我们应该围绕这个模型规划面试过程。


结论:更好的初级开发者面试过程


我有个朋友最近参加了一轮初级开发人员面试,并且在疯狂地学习 CS101 课程,的确很有效果。但我认为不应该这样。两年多来,很多像我朋友一样的人编写出了面向成千上万个用户的生产代码。他们不应该被强迫去「学习」后才能获得一个与他们现有水平相匹配的工作。他们应该自由地谈论日常生活、喜欢的事和讨厌的事。他们应该讨论正在学习的东西、团队中的同伴,以及他们喜欢什么样的工作环境。


计算机科学是迷人且趣味无穷的,技术人应该都能感受到。大多数人在日常工作中并不会用到太多他们在学校学的知识。不过没关系,这提醒我们在面试时不要刷掉那些获得 CS 学位的人。


不要用招聘来折磨初级开发者,强迫他们做一些高深的编程,就像逼一个高中生去学习《麦田的守望者》或《红字》长篇小说那样。我们可以从程序员的角度和他们进行交谈,考察他们是否愿意学习、善于沟通,以及是否适合团队合作。


看完本文有收获?请转发分享给更多人

关注「ImportNew」,提升Java技能