从概念到生产都面临代码挑战

安迪·戴维斯(Andy Davis)的来宾帖子-超级才华的软件工程师,来宾博客和出色的代码挑战创建者!

最近,我一直在谈论很多编码方面的挑战。 什么是好的? 是什么使一个坏人呢? 如何标记一个? 甚至,如何制作一个。

招聘团队要求外面有很多人提出挑战,以测试候选人并找到他们的理想之选。

如果真那么简单就好了…

由于您正在阅读本文,因此您过去可能曾经做过一个,甚至现在需要做过一个。 因此,让我们花一些时间在上面。 它不必太复杂,也不必抓住在线上找到的第一个。

您不应该急于这样做,也不需要创建世界上最好的产品。 这就是为什么…

没有人从一种编码挑战解决方案的背后受雇。

就是说,通常这是第一次在实际编写代码时看到某人的样子的机会。 因此仍然完全值得投资。 可靠的开发人员聘用过程不仅要谈论。

因此,您需要制作一个,应该怎么做?

首先,确定挑战背后的目标。 目标是您可以更快,更公平地评估候选人的最简单,最明显的方法。 您会对Fizz Buzz面临多少挑战感到惊讶-是否真正考虑了他们要寻找的东西? 还是他们只是谷歌搜索并使用发现的第一件事?

例如,您是否需要测试人员来驱动他们的代码,您是否需要铁杆优化专家,您是否只希望可以尽快完成工作的人员。

一旦有了目标,设计挑战就容易得多。

我将设计一个挑战,向您展示我的意思……。

但是在我这样做之前……我想给您留下最后的建议,以便您在挑战时牢记。

您应该尝试从谷壳中分离出小麦,而不是从小麦中分离出小麦。 我的意思是,过滤掉无法编写代码的人员。 在此阶段,请勿通过编码样式或体系结构方法进行筛选。 当您实际上在同一个房间并彼此交谈时,这些才是在您的录用过程中更有价值的东西。

事不宜迟,这里是我尝试从头开始的挑战。

我想选择一些热门话题,所以我搜寻了黑客新闻,以了解常见话题以及是否可以提出相关话题。

我选择了自动驾驶汽车(或自动驾驶汽车)。

它不仅受欢迎,而且似乎也很有趣。 我想知道是否可以编写一个。 还是更好,将部分构建的框架/ api放在一起,让候选人提出一些建议。

经过几次迭代和反馈后,我在评估候选人和确定候选人所属的类别方面很有用。 我说“桶”是有原因的。 尽管所有公司都认为他们只聘用最好的人才,但我相信开发人员实际上并没有好坏之分。 没有“最佳”开发人员。 它们只是属于不同的类别或“存储桶”。

对一家公司而言,最好不是对另一家公司而言。 例如,刚进入行业但没有商业经验的大三学生也不是坏开发商。

好吧好吧,那里有一些糟糕的开发商。 我们都知道那是谁,但有人雇用他们不是吗? 让我们继续前进

TL; DR-如果您认为自己有能力应对挑战,请立即亲自尝试“自动驾驶汽车挑战赛”-我们目前提供C Sharp和Java版本,但是如果有需求,我们还会提供更多版本。 只需向[受电子邮件保护]发送一封电子邮件,说明您是否想要C Sharp或Java版本。

现在是科学……。 这是我的详细思考,也是我提出挑战的背后过程。 挑战仍在进行中,但这就是我认为所有挑战都应该面对的方式,这是我提出挑战的细节和过程。

我从哪里开始?

我应该只用谷歌搜索“编码挑战”并随机选择一个,还是稍微调整一下?

这里是障碍…

编码挑战现在变得越来越流行,发现它变得越来越普遍:

  1. 候选人已经知道最受欢迎的候选人
  2. 候选人忙于应对挑战

让我们解决A点。只要稍稍扭转一下,他们是否已经知道都没关系。 只要挑战不是100%像从网上选择的那样,从Google和StackOverflow获取代码是完全可以接受的。 仍然会显示应聘者喜欢编写代码的方式。 毕竟,在生产代码中,优秀的开发人员很少会在不根据自己的需要对其进行调整的情况下复制代码。

在B点,如果他们太忙了,那就意味着我们也不想雇用他们,对吧?

好吧……不完全是! 太忙可能是一件好事,如果这意味着他们有需求。 毕竟,优秀的开发人员不一定会立即寻找下一个角色。 但是,他们可能很好奇-我们不想消除这种好奇心。

我们希望开发人员真正应对挑战! 因此,我们需要将进入门槛降低到足够低的水平,以使好人感兴趣,尽管他们有多忙。

这并不是说挑战应该很容易!

我们是知识工作者。 必须有一些知识,好人知道而坏人不知道? 经验带来的东西。 像一系列可以凭经验解锁的钥匙吗?

问题在于不同的租用人具有不同的密钥。 例如,当我提出挑战时,我真正想知道的是他们是否具有正确的态度,是否可以与我要招聘的团队有效地合作。 之后,我更喜欢TDD而非Test。 我喜欢干净的代码和SOLID原则,胜过其他思想流派。 这并不是说其他​​思想流派是错误的,这并不是我多年来发现的最有效的方法。

让我们将注意力转移到食物上一秒钟(因为我很饿:))。

您知道Masterchef专业人士吗? 我认为代码挑战相当于Monica或Marcus的“技能测试”。

对于那些不知道的人,Masterchef是一场烹饪比赛,而该节目的“ The Professionals”版本是针对已经专业从事厨师工作的人,而不是业余爱好者。 您会发现,就像我们一样-我们也是专业人士

在技​​能测试中,将对特定技能进行约15分钟的测试。 它可能正在制作豪华的煎蛋,也可能正在切成整个三文鱼。 参赛者事先不知道。

技能测试很快。 参赛者总是无时无刻不在混乱,他们的神经和压力使他们做出愚蠢的事情,但这没关系,评委们正在寻找潜在的种子,而不是最终的文章。

因此,如果我们将这种代码挑战视为像Masterchef这样的快速技能测试,它会将它放在上下文中。 提交的内容不一定是完美的。 这意味着测试本身并不需要太费力就能挑战它们并将它们彼此分离。

那我在“技能测试”中寻找什么?

我个人想看:

  • 测试驱动开发
  • 域驱动设计(或对象模型)
  • 设计模式
  • 清洁代码
  • 可扩展的代码

请记住:此列表可能与您的招聘地点不同。

我也想使好候选人轻而易举地变得非常容易。

因此,我希望完成的代码是

  • 一旦解决方案出现,就很难输入
  • 使用已知的设计模式
  • 完全单元测试(理想情况下为TDD)
  • 使用对象模型

专家提示:我想要有效的代码,一种向自己(和我自己)证明其有效的方法是对代码进行良好的测试。 我可能不会在测试中要求测试,但是除非您知道证明代码有效的更好方法,否则请编写测试。

现在我们要到达某个地方……为了适应新挑战的设计,我需要:-

  • 选择人们知道但不一定从事的明显领域
  • 选择一个四人帮模式

什么? 选择图案? 是的,我将首先选择一种模式,然后再设计挑战。 一种理想的解决方案将使用这种模式-但是,可能只有时间能证明更好的解决方案。

注意:如果我正在为在线赌场招聘,那么我的域名将与赌场相关。 如果我写的一般性挑战更多地是关于测试他们的技术技能,我将尝试选择每个人都听说过的东西,以避免域混淆。

我必须不断提醒自己:如何使优秀的开发人员尽可能轻松地应对挑战?

在这种情况下,干净的代码和TDD是跨领域的关注点,我一直希望看到这一点。 因此,我不会制作任何充满硬依赖性的模板代码,因为期望它们不效仿是不公平的。 即使优秀的开发人员会修复我可怜的模板,这也会带来风险,因此我会避免这种情况。

为了扩展,我还谨记,我希望以后可以很容易地进行“功能请求” —让应试者有机会编写使自己易于扩展的代码(由应聘者预测明显的下一个功能请求)并保留相应的代码)。

专家提示:请勿实际执行该预测(请记住YAGNI)

这里有一些选择

购物车-已死

火星漫游者(Mars Rover)-少见,但大多数优秀的开发人员都知道(不是一件坏事)

电话帐单-一个不错的小域名,可以用多种方式建模,如果需要解析文件,它会变得混乱且冗长

Bowling Kata-做好它需要很长时间,而且解决方案易于在线下载。

如果我们将它们调整得足够短并且足够集中,那么任何一个都可以工作。 但是,这似乎太容易了

让我们现在就去疯狂地挑选一些话题,快速浏览一下黑客新闻就可以告诉我,Self Driving Cars非常具有话题性-例如,前Google开发人员George Hotz刚刚开源了他的项目,当然还有特斯拉来发布新闻此刻几乎每天都有。

大型企业似乎认为这是未来。 他们在全面召回中看到的未来也许是?

说明中的第一枪

“您的豪华轿车公司已购买了第一辆自动驾驶汽车。 该汽车具有雷达,照相机,GPS和车载计算机,并接受简单的命令来控制汽车的所有运动,包括转向,加速,制动等。

您的汽车有一个称为ALFIE的车载助手(需要写)。

车上的乘客只需要说一个位置,车就可以自己开车到那里。

现在这些选项是A和B

您的第一个乘客上车。 请求去目的地A。当她到达目的地时,她改变了主意,意识到自己想去目的地B。ALFIE带她去了目的地A,然后去了目的地B。

背景资料

从总部…。目的地A为北(4个街区)

从总部开始……目的地B为北(2个块),然后为东(2个块),然后为北(2个块)

现在只有4个命令可以使用。

前进(将汽车向前移动1挡)

左转(将汽车向左转90度)
向右转(这会使汽车向右转90度)

在总部,汽车自动转弯并朝北

注意:这是汽车的早期原型,制造商每周都会发布新的可用命令。

假设:

您只在写ALFIE。

您无需处理语音控制

选择目的地A或B后,汽车出发

汽车需要为每个街区指定新命令
您可以一次性将这些命令排队。
除非有明确的停车命令,否则汽车将继续行驶
如果在“停止”状态下发送转弯命令之一,则汽车将自动转弯并面向相反的方向。

在那里,这并不难。

它满足我的标准吗?

  1. 测试驱动开发-嗯,我不小心使它成为一个封闭的系统-我需要考虑一些可以检查的内容,以证明这辆车能够正常工作
  2. 域驱动设计-显然这里有一个域-ALFIE,CAR,DESTINATION是一些显而易见的实体
  3. 清理代码-您始终可以使代码保持某种清理方式-通常以遵循SOLID原则开始-对于初学者,将依赖关系转换为Car命令是明智的。
  4. 设计模式-这里有明显的设计模式选择,这些选择将被使用或完全遗漏,导致违反OCP
  5. 对于一个优秀的开发人员而言,这很容易-可能会变得有点复杂-我必须在实现它的过程中进行一次试运行,以查看提出解决方案需要多长时间。 我会将其发送给一些同行进行尝试。

首先,解决封闭系统问题。

我们需要能够衡量成功。 也许一些日志记录? 听起来太模糊了。 我认为领域中的某些事情会更好。 在现实世界中,什么能告诉我们我们在目的地还是在哪里? 全球定位系统! 是的,GPS是答案……我需要在问题中添加GPS以进行验证

“随着汽车行驶,GPS应该更新其当前位置。 为简单起见,GPS可以是[X,Y]坐标。

好-这意味着也可以进行一些测试,这很好。

接下来,找到一些豚鼠…..

Geektastic的首席执行官里克(Rick)请我与3位同意接受挑战的优秀开发人员联系。

他们是怎么做的…

首先,感谢你们所有人中的三个挑战。 抱歉,本文最后没有任何工作。 但是,现在看了您的代码……我想我可能只是想着将来。

提交的解决方案以它们自己的方式都很好,但是可以通过3种不同的方式来解决。 一个我很熟悉,非常类似于我的编码方式,另一个是我没有想到的方式,第三个真正专注于算法。 尽管池很小,但获得3个不同的解决方案对我来说是个好消息。 这意味着可以在不同的上下文中使用该挑战来找到不同类型的开发人员(当然都是优秀的开发人员)。

来自第一候选人的压倒性反馈是挑战是体面的。 有足够的东西要编写代码,并且有足够的决策可以做出决定,他能够证明自己是如何编写代码的。 但是,他错过了最后期限–显然,没有足够的时间,不够公平,我只给了他30分钟的时间(再加上怪异的表情,给了我一点点的宽限期,毕竟这是一个很好的人与人之间的过程)。 我再次将其发送给他,并在一小时内将其取回。 所以实际上他有大约一个半小时。 不错。

我们决定需要增加时间限制,因为挑战对他来说还可以,但时间不够。 他还没有意识到该API是库参考(没有源代码),所以我要提到这一点,因为这有点令人困惑。 认为完成done

所做的更改:

  1. 增加到2小时的时间限制,绰绰有余。 我认为可以在大约一个小时内完成,因此2小时是一个很好的截止日期。 我希望人们有时间思考,毕竟这是我们真正雇用的思想家。
  2. 明确指出,存在一个模拟代码的编译代码库和汽车制造商提供的API,并且用户无法编辑该代码。 专家提示:依赖倒置原则在这里适用,以防万一发生变化时对其进行抽象。

现在我们准备好让其他2位候选人尝试。 我们称它们为A和B。

这次,时间限制没有问题-太棒了。 2小时就足够了。 这本来不是我的初衷,因为我认为2个小时可能令人讨厌。 由于我认为这一挑战可以在一小时左右的时间内完成,所以我们坚持两个小时。

候选人A的解决方案非常以算法为中心。 候选人B使用了非常基本的算法,但更多地侧重于代码的编码风格和表现力。 在正确的环境下,两者都是100%可接受的解决方案。 这实际上仅取决于客户的需求-即,这2个开发人员分为2个不同的类别,但是他们俩都很好。

其中一个(我不会说哪个)给出了反馈,说他们真的不知道自己生产的是不是想要的。 几乎只需要填写一些代码和一些测试,清理一些东西并提交就太容易了。 他们没有真正感到挑战。

起初,这让我担心,如果每个人都这么认为呢? 如果真的太容易了怎么办?

事实证明,那个开发人员真的很好! 因此,老实说,这就是我想要的……一个优秀的开发人员只需介入并编写代码,似乎没什么大不了的。

当我查看代码时,我想想: “是的,这还不错,我知道他们在那里做了什么。 是的,他们已经很好地清理了一些东西。” 对我来说,这标志着挑战正在奏效-只要所有人当然都没有感觉到这一点。 它已达到适当的平衡。

接下来是什么?

看来挑战现在进行得很好。 尽管如此,我还是一个完美主义者,始终都有改进的空间。 我确实想重复挑战并进一步改进它。

要自我批评我的作品,我认为这太罗…了……在考试条件下,您的思维似乎竞速了,看到描述很长的页面就像是脑子里的大毛毛。 我不希望考生有这种感觉-我认为我的下一个迭代将是将指令长度减少一半。

就目前而言,它就是…我很乐意看到您有挑战性。

目前,我们有C Sharp和Java版本,但是如果有需求,我们会添加更多版本。 只需向[受电子邮件保护]发送一封电子邮件,说明您是否想要C Sharp或Java版本

提交解决方案后,我们将由一名审核小组对其进行审核。