软件工程面试中的反乌托邦

在面试中,我经常会被要求写一个算法或者为某个算法编写测试用例。去年的 1 月份前后,我决定找一份新工作,一家大型搜索和广告公司的招聘人员在 LinkedIn 上联系我,告诉我电话面试的事情。我被要求在 45 分钟内编写出康威的游戏人生。我完写了整个程序,并进行了良好的测试,但我还是被拒绝了。

磨难

搜索与广告巨头公司的面试以失败告终。我没能解决这个问题。但这只是今年疯狂的开始。一开始,我对自己申请的公司很有策略。我不只是想要一份“工作”,还想要一份“合适的”工作。
接下来是一家自动驾驶汽车公司。在提交了申请并准备进行初次编码筛选后,我几乎立即收到了回复。面试官让我编写一个非常复杂的图像过滤算法。我写了,并希望获得反馈。“这看起来很好!”,他说。第二天我收到了一封事先准备好的拒绝邮件。
然后一家分析公司邀请我面试,我尽所能写了一个非常复杂的多线程图像处理系统。招聘人员礼貌地拒绝了我,当我要求反馈时,他们告诉我,我的实现“太低效了”。
之后是一家支付处理公司。我跟招聘人员进行了电话沟通,她对我的简历与职位描述的吻合度赞不绝口。第二天,我收到了一封电子邮件,说他们找不到适合我技能的职位。
另一个例子是大型社交媒体平台公司(Giant Social Media Platform Company)。“Jared!感谢您的申请!我认为您对大型社交媒体平台公司是一个很好的补充!我已经把您的申请直接寄给您所在地区办事处的招聘经理了!”收到这封邮件八分钟后,我收到了一封自动拒绝邮件,说我的技能不适合这个职位。
然后,我终于获得了一个大型社交媒体平台公司现场面试的机会。在四场不同的面试中,我和许多人讨论了一系列的编程问题,并提出了正确的编写方案。整个过程,他们问了我一系列令人费解、难以回答的问题:“讲讲你某一次……”。因为这是我第一次在求职过程中被问到有关作为工程师的经验和智慧的问题,然后是系统设计面试。

分析

在经历了这么长时间的反乌托邦之后,我认为我应该重新评估自己,以获得更清晰的认识。
我们被自己的神话所消费,关于软件工程师的几乎每一个流行概念,尤其是在今天这个科技狂热的世界里,都钟爱独行侠程序员的理念,认为他们可以很轻松地编写任何需求的算法。典型的软件工程师是脱离社会的、反结构的和高度理想主义的。他或她非常独立,不需要与任何人沟通就能完成工作。因此,由于我们无意识地相信这种原型,作为一名工程师,我必须通过一个测试这些特质的筛选,才能与了解该职位的人交谈。但是,据我们所知,这些特质实际上并不能帮我们找出那些高绩效的候选者。软件公司由一个或多个软件团队组成。软件团队是个体的集合。
为了在一个有着共同目标的群体中取得成功,个人必须:

  1. 相互沟通。如果一个团队成员不知道目标是什么,就会拖累整个团队。

  2. 与非软件工程师沟通。不管有多少软件工程师不喜欢这个观点,事实是,运营一家软件公司需要的不仅仅是软件工程师。

  3. 确定方向。产品的发展方向通常来自软件团队之外。毕竟,在某种程度上,这就是为一个组织工作的意义所在:把一个不属于你的愿景带入了自己的生活中。

  4. 相互学习。在一个团队中,谁知道什么谁不知道什么总是存在不平衡。产品知识和技术技能都是如此。集体团队的集体技术技能需要一个加权平衡。这就是为什么我们有不同的经验层次和责任分配。这种平衡从来都不是,也不应该是静态的。总有人需要学,总需要有人教。

综上所述,对于招聘过程的结构,似乎是软件工程师的流行概念发挥了更大的作用,而不是使软件工程师在工作中取得成功的特质。
此外,算法到底有多大价值?关于这个问题,有很多观点。无论我多么不同意他们的观点,总有一些人认为,即使你对算法的工作原理一无所知,甚至连一台数字计算机都不知道,你也可以成为一名完美的软件工程师。我的观点是,飞机机械师和航天工程师是不同的。哪一个更有价值,你更愿意成为哪一个?我这个问题留给你思考。一个更好的问题可能是算法到底有多重要。
算法到底有多重要?虽然我相信算法和计算机工作原理知识对于成为一个成功的、有价值的软件工程师来说很重要,但我也知道,而且每个人都知道,这些知识很少在工作中用到。“非我发明”的心态在团队中非常普遍。对于许多应用程序来说,这是一个很好的策略。如果有一个经过良好测试的、万无一失的库能够满足需求,那么相比重新发明轮子,引入这个库才是更安全、更恰当的做法。可以说,圆轮子就是好轮子。所以,如果你考虑与这个问题相关的算法挑战,你就会想知道我们为什么要问这些问题。如果许多业内人士都认为这些算法在软件工程师的日常工作中没有价值,那么我们为什么要用它们来评价软件工程师呢?
算法挑战的阴暗面,就像生活中许多哲学问题一样,这些有害的算法挑战也有其阴暗面。事实上,有大量的人正试图投身于科技行业。LinkedIn 上发布的招聘信息,一天之内就有 100 多位求职者。事实上,没有一家公司有足够的资源来面试他们所有人。事实是,这些算法挑战是作为一种机制,用于避开不适合该工作或没有基本编程技能的申请人。问题是,每个人对于“基本”这个词在这里的意思似乎有不同的理解。
我们不知道它们应该多难。在我过去 7 个月的面试中,我遇到了各种各样的算法难题。比较简单的,我被要求写一个函数来反转一个字符串。比较难的,我被要求模拟一个社交网络,并编写一个图像过滤算法。有一家公司让我做两次单独的编码面试。在第一次面试中,他们要求我写一个简单的排序算法,我写好了。第二次是用动态编程的方法编写递归排列生成器,这不是一件容易的事。我完全被那个问题难住了。面试结束时,我问面试官:“这个问题对电话面试来说似乎有点难以回答。您经常在支付处理公司编写递归算法吗?”他回答说:“不,我们不用递归。”“那排列呢?您什么时候用这些?”他回答说:“我们的算法不需要排列。我们这里的大多数工程师都从事用户界面和基础设施方面的工作。”对我来说,这完全说得通。这两个例子适用于不同公司中技能级别类似的角色。那么,为什么一家公司选择的算法比另一家要难呢?
这个衡量方法仅比俄罗斯轮盘赌好一点点。假设你是候选人。在过去的几个月里,你研究了所有你能想到的与编程面试相关的主题。假设你申请了 A 公司,A 要求你写一个二叉树搜索算法。太棒了!你上周刚学完二叉树!你以优异的成绩通过了考试。现在,假设你申请了公司 B。B 要求你编写一个 Trie 树的实现。不要啊!你忘记学习 Trie 了!因为你没有研究那个主题,所以面试失败了。现在把顺序颠倒一下,假设公司 B 问你二叉树算法,而公司 A 问你 Trie 树算法:很明显,在某些公司,应聘是否成功完全是取决于你碰到的问题。

时间限制是有害且不公正的。通常,在电话面试时,你有 45 分钟的时间来解决编码挑战。对于一个简单的问题来说,时间足够了。但当你被要求编写一个复杂的算法时,这显然是荒谬的。当我被要求编写康威的 游戏人生
时,我花了 50 分钟去编写一段能够运行的代码,而几乎没有时间去测试它。当我被要求写一个图像过滤算法时,我只花了 15 分钟来理解问题。我没时间了。如果要在现实世界中编写如此复杂的算法,可能需要一周的实现时间和一个多月的实际测试时间。最少这么多。为什么我们要求工程师在 45 分钟内完成?
围绕着如何通过面试,一个山寨产业已经涌现。所有这些算法挑战都始于像谷歌这样受欢迎的公司。有几个在这些受欢迎的科技公司工作的工程师看到了一个赚钱的机会,他们提供了一些准备材料。关于这个主题有两本很有影响力的书:《程序员面试金典》和《编程面试习题集》。这两本书都提供了指导性的面试准备材料。问题是,这个行业得到了这些书,并根据书中的材料定制了他们的面试。然而,一旦人们开始通过这些书中列出的基本面试问题,这些公司就意识到,他们的招聘是在刮桶底了,不过换了个新桶。因此,他们编了一些新的、更具挑战性的算法问题,让自己与众不同,并从所有看似合格的候选人中挑选出“更合格的候选人”。关于某些公司的现任和前任顶级工程师,有很多趣闻轶事,他们声称,面试过程已经变得如此艰难,如果他们现在去面试,可能永远都无法通过。我看了一场故事精彩的演讲。在某家“顶尖”的科技公司,面试流程是这样的:当求职者通过面试时,他(她)就会有一个关于其面试表现的信息包。然后,信息包会被交给一个委员会,该委员会的工作是公正地审查信息包,并做出聘用决定。有一次,一个特别委员会特别挑剔,他们拒绝了几个月来的每一个信息包。当人力资源部得知此事后,他们决定进行一次测试。他们给委员会寄去了新一轮的信息包,委员会再次全部拒绝。然后,HR 把他们召集到一个会议上,并解释说,他们刚刚看到的信息包实际上是招聘委员会成员自己在面试该公司时收到的信息包。他们不知不觉地抛弃了自己!谁又能过这一关呢?

为什么我们评判他人而不去了解他人?

几个星期前,我看了一个人的演讲,他在一家顶级公司做了大量的面试。用他的话来说,他演讲的目的是“提炼出一种在面试中‘提取信号’的策略”。“什么?!人们在认识他人的过程中发生了什么?这种态度似乎完全是机械的,坦率地说,完全是反乌托邦的。这里的逻辑是什么?我们要扫描候选人的大脑来寻找当前表现良好的候选人之间的相似性吗?这种态度散发出一种混合了可怕的利己主义和组织大男子主义的气味。在我看来,现在的公司更害怕聘用糟糕的候选人,而不是对有机会聘用优秀的候选人感到兴奋。在企业对招聘再次表现出更大的热情之前,我不认为那能给应聘者带来多少好处。最糟糕的是,求职者从招聘人员那里听到的第一句话是,你看起来很优秀,但一旦你进入面试,你发现的只是他们怀疑你是个骗子。我认为应该用谨慎的乐观取代怀疑。我确信我能继续写下去。我的本子上还有八个要点要写。但是,这篇文章看起来更像是无休止的指责,而不是一篇博客文章。我希望,至少我能够传达一些我在过去七个月里经历的困难。最后,我发现自己相当矛盾。我现在的老板刚刚解雇了我们整个办公室的人,让我失去了工作,让我独自一人写下这一切对我而言有多痛苦。我不太确定我是否想再经历一次这个过程。我做了很多思考,根据经验得出了一些简单的结论:我知道如何写代码。
在过去两年,我编写了大约 85000 行 Java 代码,对我正在开发的产品产生了非常积极显著的影响。我用 Python 编写了一些非常复杂的机器学习算法实现,还编写了一些脚本。我为嵌入式图形等多种底层应用程序编写了嵌入式 C 和 C++。我自学了 Flutter 并发布了几款应用。我自学了 Clojure,这让我的思维开阔了很多。我使用 C#做过一些开发。我知道如何建立一个静态网站。我有计算机科学学位。
公众认为企业迫切希望招聘软件工程师,而软件工程候选人面临着残酷的现实,这两者之间存在着根本性的失配。这些生死攸关的高压编码挑战看起来更像是一种欺骗机制,而不是有价值的评估工具。使用它们就像雇佣了一名警察,他们会在你问他对法律了解多少之前就开枪。事实是,我所批评的面试过程可能是公司辨别好的候选人和坏的候选人的唯一方法。我从来没有加入过招聘团队,肯定有些事情我不知道。
最后,我有几个想法:

  • 适者生存是真的,尽管我很想去一家知名的科技公司找一份薪水不错的工作,但现实是,还有很多人在竞争这些工作。就像生活中的其他事物一样,资源少而需求大。人人都想通过写代码获得丰厚的报酬。我怀疑,设置如此激进的筛选障碍的原因是,客观上(不管这意味着什么)技能水平较低的人的占比比确实拥有这些技能的人的占比要大得多。遗憾的是,这意味着无论你多么有经验,都必须和这么多的人竞争。任何一个学习过编程的人都知道,即使是最低限度地精通基本技能,其学习曲线也很陡峭。除此之外,在工作中取得成功所需的核心能力的知识体系更是庞大。此外,要熟练掌握一套符合市场需求的相关技能是很困难的,更不用说精通它们了。不管一个人通过什么途径成为一名软件工程师,很明显,竞争是生活的一部分,而且在这个行业中相当激烈。

  • 等级制度是真的,我对软件工程师的招聘广告中的分级相当困惑。似乎只有两个等级:非高级和高级。一般来说,招聘广告要求应聘者有 5 年的工作经验,这样才能被认为是资深员工。这里似乎缺少了一些分级。我们怎么称呼一个有 20 年工作经验的人?他们真的和有 5 年经验的人一样吗?就我来说,我们怎么称呼有 4 年工作经验的人?我不是应届毕业生。我知道如何独立编写软件。我知道如何使用版本控制,以及如何在敏捷环境中工作。根据情况,我需要人们为我的工作设定方向。还有一个问题进一步增加了这个问题的复杂性,就是关于一项技术的多年经验。如果一个人有 5 年的 Java 编写经验,并且加入了一个使用 Python 的团队,而且这个团队的成员都只有不到两年的 Python 编写经验,那么这个人应该被视为初级开发人员吗?这是一个令人困惑的话题,有必要单独写一篇完整的文章,即使这样,我也不确定我是否能够理解。我的观点是,我处于初级和高级之间,以我的经验水平,这似乎是一个渺茫的选择。

  • 抱怨没有任何好处,我早晚得另找工作。即使我不喜欢这种方式,我也不得不再次经历这个循环。但现在我已经受够了。一遍又一遍的重复同样的过程,似乎不太可能让任何事情发生。我最终会回到快乐的循环中,但现在,我要做出唯一一个让我保持理智的选择:我要暂时退出这个循环。

作者简介:

Jared Nelsen是科罗拉多州博尔德市的一名软件工程师。他有 Web 应用程序开发、嵌入式系统开发和移动应用程序构建的经验。他对机器学习也特别感兴趣,在机器学习算法和策略的研究与实现上花了大量的时间。本文最初发布于 Jared Nelsen 的个人博客,经原作者授权由 InfoQ 中文站翻译并分享。

原文链接:

The Horrifically Dystopian World of Software Engineering Interviews