招聘流程已失效,而人人都知道这一点
这个数字应该让每一位工程经理感到不安:在美国,当你考虑到招聘人员的时间、工程师花在面试上的时间、生产力的损失以及空缺座位的机会成本时,填补一个软件工程职位的平均成本超过30,000美元。然而,行业却坚持采用那些已被证明无法有效预测工作表现的面试形式。
十多年来,我一直在技术面试桌的两端都坐过。我在白板上编写过在生产中永远不会使用的算法,为构建CRUD应用的公司反转链表,为那些最大的架构决策只是在Express和Fastify之间做选择的角色设计系统。我们所测试的内容与实际工作要求之间的脱节令人震惊。
LeetCode产业综合体
让我们从房间里的大象开始。算法编程挑战已成为技术面试的既定标准,不是因为它们有效,而是因为它们易于标准化。谷歌等公司在2010年代初初期推广了这种方法,而行业的其余部分则盲目地模仿它,而没有考虑这是否适合他们的情境。
考虑一下典型的LeetCode风格面试实际测量的是什么:
- 在时间压力下解决特定类型的算法难题的能力
- 对数据结构及其时间复杂性的记忆
- 在人为限制条件下的表现(45分钟,没有IDE,没有文档)
现在考虑大多数工程工作实际需要的是什么:
- 阅读和理解现有代码库
- 与其他工程师合作做出设计决策
- 在模糊条件下调试生产问题
- 在速度和质量之间做出务实的权衡
- 向非技术利益相关者传达技术概念
这两份清单之间的重叠基本上为零。密歇根大学2023年的一项研究发现,算法编程面试的表现与候选人的焦虑水平的相关性,比与其实际工作表现的相关性更强。让你好好思考一下这一点。
无人计算的隐藏成本
大多数公司将每次招聘成本作为一个关键指标来追踪,但他们系统地低估了其面试流程的真实成本。以下是更诚实的计算:
| 成本类别 | 典型范围 | 被忽视的部分 |
|---|---|---|
| 招聘费用(外部) | 年薪的15-25% | 内部招聘人员薪资分配 |
| 每位候选人所需的工程师时间 | 整个团队需4-8小时 | 准备时间、复盘会议、校准会议 |
| 假阴性 | 无法计算 | 通过你们流程的优秀工程师 |
| 招聘周期影响 | 每天损失500-2000美元产出 | 团队因人员不足导致的士气下降 |
| 错误入职的培训成本 | 3-6个月薪资 | 团队在适应期的生产力损失 |
| 候选人体验损害 | 难以量化 | 在当地工程社区的声誉 |
假阴性问题值得特别关注。每个面试流程都有假阳性率(通过本不应通过的人)和假阴性率(未通过但本会很优秀的人)。大多数公司痴迷于减少假阳性,却完全忽视了假阴性,因为假阴性是看不见的。你永远不会看到那位本会成为你最佳雇员的工程师,因为他们在一道动态编程题上栽了跟头——那道题他们上大学时最后一次接触。
真正有效的方法:基于证据的面试形式
好消息是,我们有几十年的工业-组织心理学研究告诉我们什么真正能预测工作表现。坏消息是,大多数科技行业忽视了这些研究。
工作样本测试
预测工作表现的单一最佳指标是工作样本测试——给候选人一个任务,该任务与他们实际要做的工作紧密相关。对于后端工程师,这可能看起来像这样:
# 不要:"实现一个红黑树"
# 尝试:"这是我们API的简化版本。添加一个新端点
# 用于获取用户订单并支持分页和过滤。"
# 提供真实的代码库(或逼真的模拟)、真实的工具、真实的文档。
# 给他们2-3小时的时间,可以访问互联网。
# 他们将使用的示例起始代码:
from fastapi import FastAPI, Query, HTTPException
from typing import Optional
from datetime import datetime
app = FastAPI()
# 他们需要理解现有端点
@app.get("/users/{user_id}")
async def get_user(user_id: int):
user = await db.fetch_user(user_id)
if not user:
raise HTTPException(status_code=404)
return user
# 任务:添加 GET /users/{user_id}/orders,包含:
# - 分页(limit/offset)
# - 按状态过滤(待处理、已发货、已送达)
# - 按日期范围过滤
# - 适当的错误处理
# - 测试
这比任何算法谜题更能让你了解候选人。你可以看到他们如何阅读代码、如何处理边界情况、是否编写测试以及如何组织他们的工作。
结构化行为面试
非结构化面试——那种”介绍一下你自己”的面试——在预测工作表现方面几乎和抛硬币差不多。结构化行为面试,即每位候选人都回答相同的问题并依据相同的评分标准进行评估,其预测能力要强得多。
# 不好的:"讲一个你参与过的有挑战性的项目。"
# (考察:讲故事的能力、外向程度)
# 好的:"描述一次你必须在信息不完整的情况下做出技术决策的经历。
# 当时的情况是什么,你做了什么决定,现在回顾的话你会做哪些改变?"
#
# 评分标准:
# - 他们是否清晰地阐述了约束条件?(1-4分)
# - 他们是否展示了结构化思维?(1-4分)
# - 他们是否在权衡取舍方面表现出智力上的诚实?(1-4分)
# - 他们是否从结果中学到了东西?(1-4分)
针对实际问题的结对编程
与其看有人在白板上为算法题抓耳挠腮,不如和他们一起解决一个实际的bug或功能。这是你能最接近地观察一个人日常工作方式的场景。一些公司担心知识产权问题,但你可以使用开源项目或实际任务的去敏化版本。
系统设计面试的问题
系统设计面试常被吹捧为LeetCode的”成熟”替代方案,但它们自身也有其缺陷。典型的形式——”45分钟内设计一个Twitter”——奖励的是一种非常特定的表现:能够快速画出方框和箭头同时点名各种技术的能力。
更有用的方法是将问题限制在更现实的范围内:
# 不好的:"设计一个每天处理10亿请求的URL缩短服务。"
# (考察:记忆那些你永远不会面对的问题的架构模式)
# 更好的:"我们有一个webhook投递系统,在负载情况下目前会丢失
# 大约2%的webhook。这是我们当前的架构:
#
# [API] -> [Redis队列] -> [3个工作Pod] -> [客户终端]
#
# 请告诉我你会如何诊断这个问题以及你会考虑做哪些改变。
# 这是我们监控仪表板上的一些真实指标..."
#
# 然后进行一次关于权衡取舍的实际对话。
关键区别在于具体性。通用的系统设计问题考察的是模式匹配能力。而具体、有限制的问题考察的是工程判断力。
家庭作业:雷区
家庭作业可以是优秀的工作样本测试,但它们经常以具有剥削性或排他性的方式实施。常见的失败模式:
- 无限制的范围: “构建一个包含身份验证、实时更新和部署的全栈应用程序。” 这需要20多个小时,并且对有家庭责任或多份工作承诺的候选人存在歧视。
- 没有报酬: 要求人们提供4-8小时的免费劳动而不提供任何回报,这表明你不重视人们的时间。
- 主观评估: 没有明确的评分标准,家庭作业会沦为对代码风格的审美判断。
如果你使用家庭作业,请严格限制(最多2-3小时),支付报酬(200-500美元是合理的),并根据书面的评分标准进行评估。
如何在30天内改进你的面试流程
这是一个为想要做得更好的工程管理者提供的具体可行的计划:
第一周:审核你当前的流程
收集你最近20次招聘的数据。对于每次招聘,比较他们的面试分数与6-12个月后的实际绩效评估。如果没有相关性(很可能没有),你就有了变革的依据。
第二周:定义你实际需要的能力
写下新员工在前90天将要做的五件最重要的事情。不是理想化的未来工作——而是实际的、具体的任务。你的面试应该直接测试这些能力。
第三周:构建新的面试模块
至少用一个工作样本测试替换一个算法环节。为你的行为问题创建结构化的评分标准。培训面试官使用新格式。
第四周:校准和迭代
运行新流程一个月,收集面试官和候选人的反馈,并进行调整。目标不是第一次尝试就完美——而是在你的招聘流程中建立持续改进的文化。
候选人体验比你想象的更重要
工程人才市场竞争激烈,候选人们会互相交流。糟糕的面试体验不仅会让你失去那个候选人——还会毒化你在当地工程界的声誉。我曾亲自引导同事远离那些面试感觉不尊重或脱离现实的公司。
相反,那些运行周到、尊重的面试流程的公司在招聘中建立了真正的竞争优势。当候选人觉得你的面试公平且相关时,即使他们没有得到录用通知,他们也会告诉他们的朋友。
底线
技术面试行业是一个建立在可疑有效性基础上的数十亿美元的生态系统。LeetCode、HackerRank以及面试准备课程的小型产业之所以存在,是因为公司将招聘标准外包给了一系列感觉严格但实际上并非如此的仪式。
解决方案并不复杂。使用反映实际工作的样本测试。为行为面试制定评分标准。将系统设计问题限制在现实场景中。为家庭作业付费。最重要的是,通过跟踪面试信号是否能预测实际工作表现来形成反馈闭环。
您的工程团队是公司最昂贵也是最重要的投资。它值得拥有一个至少与您用于拉取请求的代码审查流程一样基于证据的招聘流程。
