伯乐在线|初级开发者面试中的不合理问题


_本文原题:初级开发者面试中的不合理问题
编译:伯乐在线/Ivyw
我有很多初出茅庐做开发的朋友 , 其中一位给我讲了他在应聘 Ruby 初级开发工程师时的事 。 下面就说说我和我的一个朋友是如何解决这个面试题的 , 两个高级工程师来解决这个初级工程师的面试题 , 显得有点大材小用 , 但结果令人出乎意外 。 在这个领域我还是有点见解的 , 我会详细描述一下我的解题思路 。
面试题
那个面试的朋友需要在 30 分钟内用 Java 实现一个链表 , 他的第一反应是小菜一碟 , 我也一样 。 即使是对没有 CS 学位的人来说 , 链表也是一种很通俗易懂的数据结构 。
链表是含有一串节点的链表 , 每个节点带有一个指向下一个节点的指针 , 这样你就大概能清楚它的工作过程了:插入节点时前后节点的信息和引用前后关系的指针都会发生改变;删除节点时移除这个节点和它的指针即可;查找节点时按顺序查看指针信息直到找到你需要的那个节点 。 如果你大学是 CS 专业的 , 那么这可能是你最初接触到的非嵌入式数据结构 。 链表的用处很大 , C 语言的标准库为接下来的编程工作提供了必要的支持 。
对初级开发人员来说这是一个很好的面试题 。 这个试题涉及了算法技巧 , 但没有 CS 专业学的那么深奥 。 其次 , 这也是非常切合实际的编程测试 , 因为工作后你肯定要写代码、调试、输出并运行代码 。 你不会被点名去白板上写点什么来展现自己的能力 , 这不是白板编程 。

伯乐在线|初级开发者面试中的不合理问题
本文插图
我很好奇 , 为什么那个朋友对这样的面试感到困扰 , 随后他说出了这道题目的附加条件:面试官希望这个链表能符合 List <T> 的特性 。 我立马被这道题的复杂性吓到了 , 完全不像一开始的毫不在意 。
救命
可能有人对 Java 标准库接口了解不多 , 所以让我来普及一下 List <T> 。 List <T> 是 Java 的泛型接口 , 可以用来实现包含很多相同数值的有序集合 。 这是一个功能强大的接口 , 提供我们可能会用到所有的定位列表数据类型 。 它有 25 个公共方法 , 其中两个方法返回另外的接口含有12 个公共方法 , 也就是说 , 你在实现过程中需要构建和测试 37 个公共方法 。 其中 t 意味着这是一个泛型接口 , 数据类型没有限制 。 这简直太荒谬了 , 而我的朋友仅有 30 分钟的时间来解答 。
那么 , 这个问题是否适合那些经验不足两年的新人呢?当然不适合 , 而且相当不合理 , 我就“严肃认真地分析下”(我可以好好施展一番了 , 我对自己还是很有信心的) 。 我可以很轻易地完成这项任务 , 毕竟我是一个“资深”的开发人员 , 我这半辈子都在和 Java 编程打交道 , 虽然对工具有些生疏 , 但领悟很强 。 只是我不值得为这个任务花费太长时间 。
然而这还不够 , 我们还要精益求精 。 Pair programming (结对编程)是我最喜欢的一种工作方式 , 可以协助我们更快地完成工作 。 你需要向同伴解释自己的思路 , 当你累了还可以得到同伴的帮助 。 所以 , 我找到 Stephen Best 来一起解决这个问题 。 前20分钟我们没有安装工具 , 而是做出问题草图、搭建测试环境等等 。 我们假装是在面试环境中解决这个问题 。
【伯乐在线|初级开发者面试中的不合理问题】很快我们就开始了 。 Stephen 曾和我一起工作了6个月 , 其中有三分之一的时间都是这种模式 。 我们使用 TDD 工作流程协同工作 。
首先我们用 Eclipse 自动生成完整的界面框架 , 然后准备开始实施了 。 不幸的是 , 我们没有意识到这个任务的艰巨程度 。
这个过程的艰难险阻 , 简直难以形容 。 List <T> 接口有个好处 , 你可以在一些方法之上实现另外一些方法 , 但 List <T> 接口的复杂度太高 。 大约 6 小时后 , 我们放弃了 , 我们失败了 。 我们非但没能在 30 分钟内完成实施 , 我们根本没法解决这个问题 。分页标题
我们使用了 listIterator 方法 , 它必须返回一个 ListIterator <T> 对象并声明注销时间 , 但是当你几乎快要完成一个复杂接口时 , 不知道又从哪冒出另外一个 。
我们所有的基本操作都已完成 , 并具有良好的测试覆盖率 。 我可以指出实现 List <T> 所必须的但 Java 类型系统无法支持的部分 , 这些部分留给实施者去实现就好 。 我们没有做范围检查的接入 , 当你查询任意位置的元素时会报空指针异常 , 而不是提示范围错误 。 我们跳过这部分是因为这不是必要的而且我们时间有限 。
我想象不出那些初级开发人员在遇到这样的问题时脑袋里会想什么 。 这是一个 Ruby 的开发岗位 , 我搞不懂为什么让一个新人去实现如此复杂的接口 。 当然 , 很多面向对象的想法可以从 Java 移植到 Ruby , 也许这才是面试的侧重点 。 我和 Stephen 能够承担这项任务的唯一原因是我很熟悉如何构建 Java 通用系统 。 当你写出如下代码时:
private <A> A reduceNodes(A accumulator, NodeCallback<A, T> callback) {
其中涉及一个类类型参数、一个方法类型参数和一个匿名回调接口 , 好像并没有用到 Java 语言 。 这个命令可以让后面的实现更简单直接 , 在面试中这样做的话 , 我很确定面试官一定会很困惑 。 如果 Stephen 和我这样解答的话 , 可能无法通过这次面试 , 这是个危险信号 。
继续上面的话题 , 这究竟说明了什么 。 这是一个压力面试 , 面试官给出一个问题 , 而很显然求职者无法在规定的时间内解决 。 再次重申一下 , 我很肯定没人能在 30 分钟内实现 List <T> 链表 。 这很不公平 , 那些擅长某种思维的人才会被过滤掉 , 因为平常很少有程序员会遇到这样的测试 。 更糟的是 , 这会打击很多人的信心 。 下一节中 , 我们将探讨一下这样给初级开发人员带来的影响 。
常春藤 CS Shibboleth
如果一个面试题无法筛选出合适的应聘者 , 那它还有什么意义 , 难道是要看应聘者面对无法解答的问题时的反应么?与其这样 , 还不如选一些合适的面试题 , 可以让面试官判断出应聘者是否成功解决了问题 。
人类很奇怪 , 喜欢建立部落群居生活 。 部落是史前最接近现代社会(在地理意义上)的人类群体 。 这意味着他们是很接近我们的人 , 我们都喜欢进行筛选 。 给面试官主观决定的权利意味着他们会选择最接近他们的人 。 这就是为什么很多公司用白板编程的方式筛选应聘者 , 那些从名校毕业有 CS 学位的求职者在白板面试环节表现出色 , 这应该是好学历的特权吧 。
有个问题不得不提 。 在过去几年中 , 非 CS 专业(考虑到我们这个行业兴起的年头 , 称之为非传统似乎有点可笑)的技术人员大幅增加 。 这些初级程序员大部分来自训练营 。 训练营不会教你如何构建红黑树或如何用 C 语言实现哈希表 , 他们没必要教这些 , 因为很少有学员毕业后会用到这些 。 这并不稀奇 , 因为当我开发 Rails 应用时 , 我的 CS 学位根本没有任何帮助 。
白板编程面试在大多数情况下是很令人苦恼的事 。 我自己也经历过很多次 , 而且从来没收到过回信 。 我是一个拥有 CS 硕士学位的顺性男 , 所以 , 至少在这件事上「选择像我们这样的人」的准则似乎没有奏效 。 我认为白板编程面试与大多数人的实际工作内容是相背离的 。
我发现一些问题 , 因为人们认为从事这个行业要有 CS 学历才可以 , 所以很多初级技术岗位并没有考虑训练营的学员 。 这样做有害无益 , 特别是在行业多样性方面 。 据我观察 , 训练营的学员比拥有 CS 学历的人涵盖更广泛的社会阶层 , 而且训练营的费用肯定比美国的「常春藤联盟」大学少得多 , 当然还有英国类似的大学(抱歉 , 英格兰中心论的读者) 。 合理的学费也有助于实现(但不完全)民主化和权利平等 。分页标题
我听说很多训练营都有专门的课程 , 教初级开发者用死记硬背的方式学习白板编程 , 用他们不理解的数据结构来操作指针、构建 rails 应用程序等等 。 如果没有这些课程 , 在面试时 CS 专业的人就会更吃香 。 我也面试过很多训练营的学员 , 跟 CS 专业的毕业生比起来 , 我更倾向于雇佣前者 。
因为 , 训练营的学员:

  • They’re a thing (他们有能力)
  • 他们确实很优秀 。
  • 如果你想招一个初级 Ruby 开发 , 找训练营毕业的是不错的选择 。
面试除了要找到合适的人 , 你也应该为应聘者留下一个良好印象 。 如果你给他们出一些不可能完成的白板问题或编程任务 , 可能直到面试结束后他们都会感觉很糟糕 。 如果他们接受这份工作 , 面试时的压力也会一直伴随他们 , 这样的雇员雇主关系可不是一个好的开头 。
资深开发者的面试趣事
我想讲一些关于「资深」开发人员的面试 , 有我自己的经历 , 也有别人的 。 据我观察 , 这个级别的招聘基本没有白板编程环节了 , 甚至(但并不总是)完全不用写代码了 。 这些面试过程大多是以双方进行某种技术讨论的方式进行 。 我发现 , 有时应聘者可能比面试官更老练 。 因此 , 面试官很愿意倾听应聘者的想法 , 并礼貌地询问处理某个问题的方法 。
对我来说这种形式的面试好得多 , 白板编程对我来说就是地狱 。 因为我并不擅长 , 如果一个面试是以白板编程的方式来进行筛选 , 那我肯定没法通过 。 我的好友 Justin Searls 也有同样的顾虑 。 尽管这样 , 大多数与我合作过的开发人员都认为我是很有效率的 。 如果某些技术牛人因为无法解答你给出的问题而面试失败的话 , 你就需要反思一下是不是面试方式出了问题 。
我们可以采用技术讨论的方式展开面试 。 求职者会感觉很轻松 , 他可以表达自己的观点 , 还有机会纠正前面犯的错误 , 倾听面试官并给出回应 , 这个过程可以加深双方的了解 。 沟通是程序员需要学习的最重要的事情 。 计算机出现的所有问题 , 归根到底都是人的问题 。 这样的面试方式才会让求职者感觉很舒服 。
求职者表达自己的见解 , 面试官倾听并给予回应 。 这个过程可以检测出双方是否适合在一起工作 , 双方是否会在自己犯错时让步 , 与此同时展示一下平常的工作状态 。
最重要的技术工作都是在良好的沟通下完成的 , 因此 , 我们应该围绕这个模型规划面试过程 。
结论:更好的初级开发者面试过程
我有个朋友最近参加了一轮初级开发人员面试 , 并且在疯狂地学习 CS101 课程 , 的确很有效果 。 但我认为不应该这样 。 两年多来 , 很多像我朋友一样的人编写出了面向成千上万个用户的生产代码 。 他们不应该被强迫去「学习」后才能获得一个与他们现有水平相匹配的工作 。 他们应该自由地谈论日常生活、喜欢的事和讨厌的事 。 他们应该讨论正在学习的东西、团队中的同伴 , 以及他们喜欢什么样的工作环境 。
计算机科学是迷人且趣味无穷的 , 技术人应该都能感受到 。 大多数人在日常工作中并不会用到太多他们在学校学的知识 。 不过没关系 , 这提醒我们在面试时不要刷掉那些获得 CS 学位的人 。
不要用招聘来折磨初级开发者 , 强迫他们做一些高深的编程 , 就像逼一个高中生去学习《麦田的守望者》或《红字》长篇小说那样 。 我们可以从程序员的角度和他们进行交谈 , 考察他们是否愿意学习、善于沟通 , 以及是否适合团队合作 。