Categories
程式開發

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


本文最初发布于Jared Nelsen的个人博客,经原作者授权由InfoQ中文站翻译并分享。

考验

我的电话响了。

“你好,我是Jared。”

“嗨。我打电话是想做一下巨人搜索和广告公司的电话面试。”

“是的!我一直在等我们的电话!”

“好的。你能写一个算法来找出一棵二叉树中第K个最大值吗?“

我卡克了。我完全想不起来了。我从来没见过这样的。空白的谷歌文档里,光标在缓慢的闪烁。我东拼西凑写出了第一个版本。

“你能为这个算法写一个测试用例吗?”

当然。如果我没有被这样捉弄,如果我内在的自我没有因为梦想在眼前消逝而为怒火所融化,我是有可能做到的。这就是我过去几个月努力工作的结果吗?2019年1月前后,我决定找一份新工作。就好像软件工程之神保佑一样,一家大型搜索和广告公司的招聘人员在LinkedIn上联系我,告诉我电话面试的事情。完美!

这种事情已经不是第一次发生了。作为一个刚从学校毕业的年轻而聪明的工程师,我最近开始了我的第一份工作,而且做得很好。但后来,我的世界被彻底颠覆了。我正在处理一个特别讨厌的Bug,做了任何一个有自尊的软件工程师在尝试自己解决它之前都会做的事情:Google它。当我在搜索框中输入了一个不很明确的查询并按下回车时,屏幕就变成了黑色,我被丢进了一个shell中。

你说的是我们的语言…你愿意接受一项挑战吗?

  1. 是的
  2. 不,谢谢

我差点把不冷不热的好市多咖啡喷出来。我正要跳起来,大声叫同事过来看看。但后来我突然担心自己产生了幻觉,并且意识到,如果事实证明这是真的,我会非常尴尬。我担心自己就会有灵魂出窍的体验了,于是按了1。

给定一个包含n+1个整数的数组,其中每个整数都在1和n之间(包括1和n),证明至少存在一个重复的数值。假设只有一个重复的数值,则找出这个数值。

你有24个小时!

我要心脏病发作了。当我又喝了一杯好市多咖啡后,我意识到我完全可以做到这一点。我脑子里已经有了一个解决这个问题的计划。所以我做了。当我点击提交,我就收到了另一个需要解决的问题。每一次,挑战都变得越来越难,这样又重复了5次。在我提交了最后的挑战后,我收到了另一条信息:

恭喜你!这个代码很强大!你希望获得巨人搜索和广告公司的面试机会吗?

就是这样。我的整个职业类别都改变了。世界上最强大的组织之一已经深入我22岁的大脑,并改写了一份记录表。我之前的职业目标都不重要了。在此之前,我没有意识到,像这样的顶级公司会是我的一个选项。但显然,我已经证明了自己可以考虑这个选项。

电话面试很像我之前做的噩梦。我被要求在45分钟内编写出康威的游戏人生。实际上,我做得很好。我写了整个程序,并测试了它,证明它是可以工作的。第二天我就被拒绝了。我内心既沮丧又困惑。我到底做错了什么?难道我做过的所有挑战都没有任何意义吗?为什么我要在这么短的时间内写出这么有挑战性的算法?

鉴于我第一次参加该级别面试的经历,我决定这一次之后要提高自己的水平。我的面试是在今年四月。我给自己制定了一个为期3个月的学习计划,然后拼命地去执行。我早上起来先做三道练习题,然后去上班,工作一整天,然后回家跑步,吃点东西,然后回到办公室,找一个安静的工作环境做更多的练习题。在三个月的时间里,我总共做了114道练习题。数组、回溯、二叉搜索、二叉树、广度优先搜索、深度优先搜索、动态规划、图形、贪婪算法、哈希、链表、概率、排序、堆栈和前缀树都是我研究的主题。有了这些准备,我怎么可能不成功呢?

磨难

搜索与广告巨头公司的面试以失败告终。我没能解决这个问题。但这只是今年疯狂的开始。一开始,我对自己申请的公司很有策略。我不只是想要一份“工作”,还想要一份“合适的”工作。

接下来是一家自动驾驶汽车公司。在提交了申请并准备进行初次编码筛选后,我几乎立即收到了回复。面试官怒气冲冲,带着浓重的口音让我编写一个非常复杂的图像过滤算法。我写了,并希望获得反馈。“这看起来很好!”,他说。第二天我收到了一封事先准备好的拒绝邮件。

然后一家分析公司邀请我做一个带回家的挑战。这个挑战只有三句话的简单说明。我尽我所能写了一个非常复杂的多线程图像处理系统。招聘人员礼貌地拒绝了我,当我要求反馈时,他们告诉我,我的实现“太低效了”。

之后是一家支付处理公司。我跟招聘人员进行了很好的电话沟通,她对我的简历与职位描述的吻合度赞不绝口。第二天,我收到了她的一封电子邮件,说他们找不到适合我技能的职位。

另一个例子是大型社交媒体平台公司(Giant Social Media Platform Company)。“Jared!感谢您的申请!我认为您对大型社交媒体平台公司是一个很好的补充!我已经把您的申请直接寄给您所在地区办事处的招聘经理了!”收到这封邮件八分钟后,我收到了一封自动拒绝邮件,说我的技能不适合这个职位。

有无数的第三方招聘人员联系我。所有这些都以失败告终。也许我最喜欢的是一家音频处理公司。招聘人员主动联系我,说在看完我的简历后,团队很愿意和我交谈,她会给招聘经理打个电话。一个星期过去了,我跟他们联系看看发生了什么事。招聘人员说她已经和招聘经理取得了联系,他认为我的技能与岗位不匹配。我完全理解,我的日子还得继续……不过,作为测试,我把我的简历提交到他们一个不同的招聘职位,有一个不同的招聘人员立即联系了我。我很吃惊,他们立即对我进行了电话面试。我不得不承认,我在这次面试里表现平平。第二天我收到了一封事先准备好的拒绝邮件。

然后,我终于获得了一个大型社交媒体平台公司现场面试的机会。在四场不同的面试中,我和许多人讨论了一系列的编程问题,并提出了正确的编写方案。整个过程中,他们问了我一系列令人费解、难以回答的问题:“讲讲你某一次……”。这让人耳目一新,因为这是我第一次在求职过程中被问到有关我作为工程师的经验和智慧的问题。然后是最后的系统设计面试。面试官很快给了我一个小系统让我设计。我开始讲述我的解决方案,整个过程中他们都会提问。最后,他说:“好吧,假设我们有一个微服务架构……你能设计……吗?”我马上告诉他,我对微服务没有任何经验。他疑惑地看着我,问道:“你没有经验?”我说:“对。我在简历上列出了我在桌面、嵌入式系统和移动开发方面的技能和背景”。当人们意识到他或她犯了错误时,便会停顿一下。好极了!这人是在告诉我,为了这次面试,我花了4个月时间学习,工作之余几乎每一小时都用来完成练习题,演练如何在软技能问题中展示我的背景,而他都懒得花十分钟时间来看我的简历。

分析

我可以继续为我在找工作的过程中所经历的许多令人失望的经历而抱怨。许多。23次面试,我没有得到一份工作。关于自己的能力,对自己和他人,我总是力求完全诚实和谦逊。我没有申请那些需要多年经验的工作,也没有申请那些我暂时不具备相应技能的工作。当然,我曾打算从嵌入式领域回到Web领域,但是,除了作为移动应用程序开发人员和机器学习算法研究人员的经验外,我还有两年的Web工程师经验。我完全承认,我有无数种成长的方式,也有很多在职学习的机会。但另一方面,我非常确信,我必须掌握技能,才能快速适应新的工作。在我看来,软件工程是一种由学习和新经验定义的艺术形式。没有哪个软件工程师稍微精通就止步不前了。至少我不希望这样:这样做的人很快就会被甩在后面。这到底是怎么回事呢?在经历了这么长时间的反乌托邦过程之后,我认为我应该分解并分析我的观察结果,然后重新评估以获得更清晰的认识。

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

为了在一个有着共同目标的群体中取得成功,个人必须:

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

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

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

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

综上所述,对于招聘过程的结构,似乎是软件工程师的流行概念发挥了更大的作用,而不是使软件工程师在工作中取得成功的特质。

  1. 我们都知道算法挑战是一个精心设计的游戏——这一点很难解释,因为它有许多方面。

    a. 算法到底有多大价值?——关于这个问题,有很多观点。无论我多么不同意他们的观点,总有一些人认为,即使你对算法的工作原理一无所知,甚至连一台数字计算机都不知道,你也可以成为一名完美的软件工程师。我的观点是,飞机机械师和航天工程师是不同的。哪一个更有价值,你更愿意成为哪一个?我这个问题留给你思考。一个更好的问题可能是算法到底有多重要。

    b. 算法到底有多重要?——虽然我相信算法和计算机工作原理知识对于成为一个成功的、有价值的软件工程师来说很重要,但我也知道,而且每个人都知道,这些知识很少在工作中用到。“非我发明”的心态在团队中非常普遍。对于许多应用程序来说,这是一个很好的策略。如果有一个经过良好测试的、万无一失的库能够满足需求,那么相比重新发明轮子,引入这个库才是更安全、更恰当的做法。可以说,圆轮子就是好轮子。所以,如果你考虑与这个问题相关的算法挑战,你就会想知道我们为什么要问这些问题。如果许多业内人士都认为这些算法在软件工程师的日常工作中没有价值,那么我们为什么要用它们来评价软件工程师呢?

    c. 算法挑战的阴暗面——就像生活中许多哲学问题一样,这些有害的算法挑战也有其阴暗面。事实上,有大量的人正试图投身于科技行业。LinkedIn上发布的招聘信息,一天之内就有100多位求职者。事实上,没有一家公司有足够的资源来面试他们所有人。事实是,这些算法挑战是作为一种机制,用于避开不适合该工作或没有基本编程技能的申请人。问题是,每个人对于“基本”这个词在这里的意思似乎有不同的理解。

    d. 我们不知道它们应该多难——在我过去7个月的面试中,我遇到了各种各样的算法难题。比较简单的,我被要求写一个函数来反转一个字符串。比较难的,我被要求模拟一个社交网络,并编写一个图像过滤算法。有一家公司让我做两次单独的编码面试。在第一次面试中,他们要求我写一个简单的排序算法,我写好了。第二次是用动态编程的方法编写递归排列生成器,这不是一件容易的事。我完全被那个问题难住了。面试结束时,我问面试官:“这个问题对电话面试来说似乎有点难以回答。您经常在支付处理公司编写递归算法吗?”他回答说:“不,我们不用递归。”“那排列呢?您什么时候用这些?”他回答说:“我们的算法不需要排列。我们这里的大多数工程师都从事用户界面和基础设施方面的工作。”对我来说,这完全说得通。这两个例子适用于不同公司中技能级别类似的角色。那么,为什么一家公司选择的算法比另一家要难呢?

    e. 这个衡量方法仅比俄罗斯轮盘赌好一点点——假设你是候选人。在过去的几个月里,你研究了所有你能想到的与编程面试相关的主题。假设你申请了A公司,A要求你写一个二叉树搜索算法。太棒了!你上周刚学完二叉树!你以优异的成绩通过了考试。现在,假设你申请了公司B。B要求你编写一个Trie树的实现。不要啊!你忘记学习Trie了!因为你没有研究那个主题,所以面试失败了。现在把顺序颠倒一下,假设公司B问你二叉树算法,而公司A问你Trie树算法:很明显,在某些公司,应聘是否成功完全是取决于你碰到的问题。

    f. 时间限制是有害且不公正的——通常,在电话面试时,你有45分钟的时间来解决编码挑战。对于一个简单的问题来说,时间足够了。但当你被要求编写一个复杂的算法时,这显然是荒谬的。当我被要求编写康威的游戏人生时,我花了50分钟去编写一段能够运行的代码,而几乎没有时间去测试它。当我被要求写一个图像过滤算法时,我只花了15分钟来理解问题。我没时间了。如果要在现实世界中编写如此复杂的算法,可能需要一周的实现时间和一个多月的实际测试时间。最少这么多。为什么我们要求工程师在45分钟内完成?

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

  2. 为什么我们评判他人而不去了解他人?——几个星期前,我看了一个人的演讲,他在一家顶级公司做了大量的面试。用他的话来说,他演讲的目的是“提炼出一种在面试中‘提取信号’的策略”。“什么?!人们在认识他人的过程中发生了什么?这种态度似乎完全是机械的,坦率地说,完全是反乌托邦的。这里的逻辑是什么?我们要扫描候选人的大脑来寻找当前表现良好的候选人之间的相似性吗?这种态度散发出一种混合了可怕的利己主义和组织大男子主义的气味。在我看来,现在的公司更害怕聘用糟糕的候选人,而不是对有机会聘用优秀的候选人感到兴奋。在企业对招聘再次表现出更大的热情之前,我不认为那能给应聘者带来多少好处。最糟糕的是,求职者从招聘人员那里听到的第一句话是,你看起来很优秀,但一旦你进入面试,你发现的只是他们怀疑你是个骗子。我认为应该用谨慎的乐观取代怀疑。我确信我能继续写下去。我的本子上还有八个要点要写。但是,这篇文章看起来更像是无休止的指责,而不是一篇博客文章。我希望,至少我能够传达一些我在过去七个月里经历的困难。最后,我发现自己相当矛盾。我现在的老板刚刚解雇了我们整个办公室的人,让我失去了工作,让我独自一人写下这一切对我而言有多痛苦。我不太确定我是否想再经历一次这个过程。我做了很多思考,根据经验得出了一些简单的结论:

  • 我知道如何编写软件——在过去的两年里,我已经编写了大约85000行Java代码,对我正在开发的产品产生了非常积极显著的影响。我用Python编写了一些非常复杂的机器学习算法实现,还编写了一些脚本。我为嵌入式图形等多种底层应用程序编写了嵌入式C和C++。我自学了Flutter并发布了几款应用。我自学了Clojure,这让我的思维开阔了很多。我使用C#做过一些开发。我知道如何建立一个静态网站。我有计算机科学学位。
  • 我不知道为什么其他人不让我写软件——公众认为企业迫切希望招聘软件工程师,而软件工程候选人面临着残酷的现实,这两者之间存在着根本性的失配。这些生死攸关的高压编码挑战看起来更像是一种欺骗机制,而不是有价值的评估工具。使用它们就像雇佣了一名警察,他们会在你问他对法律了解多少之前就开枪。
  • 我不知道桌子另一边是怎样的——事实是,我所批评的面试过程可能是公司辨别好的候选人和坏的候选人的唯一方法。我从来没有加入过招聘团队,肯定有些事情我不知道。

最后,我有几个想法:

  • 适者生存是真的——尽管我很想去一家知名的科技公司找一份薪水不错的工作,但现实是,还有很多人在竞争这些工作。就像生活中的其他事物一样,资源少而需求大。人人都想通过写代码获得丰厚的报酬。我怀疑,设置如此激进的筛选障碍的原因是,客观上(不管这意味着什么)技能水平较低的人的占比比确实拥有这些技能的人的占比要大得多。遗憾的是,这意味着无论你多么有经验,都必须和这么多的人竞争。任何一个学习过编程的人都知道,即使是最低限度地精通基本技能,其学习曲线也很陡峭。除此之外,在工作中取得成功所需的核心能力的知识体系更是庞大。此外,要熟练掌握一套符合市场需求的相关技能是很困难的,更不用说精通它们了。不管一个人通过什么途径成为一名软件工程师,很明显,竞争是生活的一部分,而且在这个行业中相当激烈。
  • 等级制度是真的——我对软件工程师的招聘广告中的分级相当困惑。似乎只有两个等级:非高级和高级。一般来说,招聘广告要求应聘者有5年的工作经验,这样才能被认为是资深员工。这里似乎缺少了一些分级。我们怎么称呼一个有20年工作经验的人?他们真的和有5年经验的人一样吗?就我来说,我们怎么称呼有4年工作经验的人?我不是应届毕业生。我知道如何独立编写软件。我知道如何使用版本控制,以及如何在敏捷环境中工作。根据情况,我需要人们为我的工作设定方向。还有一个问题进一步增加了这个问题的复杂性,就是关于一项技术的多年经验。如果一个人有5年的Java编写经验,并且加入了一个使用Python的团队,而且这个团队的成员都只有不到两年的Python编写经验,那么这个人应该被视为初级开发人员吗?这是一个令人困惑的话题,有必要单独写一篇完整的文章,即使这样,我也不确定我是否能够理解。我的观点是,我处于初级和高级之间,以我的经验水平,这似乎是一个渺茫的选择。
  • 抱怨没有任何好处——我早晚得另找工作。即使我不喜欢这种方式,我也不得不再次经历这个循环。但现在我已经受够了。一遍又一遍的重复同样的过程,似乎不太可能让任何事情发生。我最终会回到快乐的循环中,但现在,我要做出唯一一个让我保持理智的选择:我要暂时退出这个循环。

作者简介:

Jared Nelsen是科罗拉多州博尔德市的一名软件工程师。他有Web应用程序开发、嵌入式系统开发和移动应用程序构建的经验。他对机器学习也特别感兴趣,在机器学习算法和策略的研究与实现上花了大量的时间。

原文链接:

The Horrifically Dystopian World of Software Engineering Interviews