蛮荆

工程师面试指北

项目介绍

项目介绍的时候,不要一上来就说一些复杂的项目方案。因为在不了解的项目的背景和一些问题的情况下,面试官和面试者理解的上下文是不一样的,这样就会造成双方之间理解的误差。 所以项目介绍的时候,首先介绍一下项目的背景。在面试官的了解之后,就可以开始介绍项目的一些整体架构等等。介绍完成之后,面试官就会根据你说到技术点,然后开始提问。

面试者需要提前复盘自己完成过的项目/模块,并在此基础上模拟面试场景,针对项目/模块中的技术细节、难点、设计方案进行提炼并确认是否存在设计缺陷和问题,提前发现并修正, 避免在面试现场 “露怯”。

数据结构和算法

面试前 1 个月就要经常刷题,保持手感,在时间允许的情况下联系白板写代码,因为面试大部分情况下会在纸上写代码,理想情况下是看到题目之后就能条件反射想到对应的考点、数据结构、算法甚至解题模板。

当然对于成熟的面试官来说,除了考察面试者是否熟练数据结构和算法以及可以写出 bug fres 代码之外,同时会考察面试者是否可以判断当前算法 (包括数据结构) 和给定场景 (比如数据量级、数据类型) 的适配程度, 当前问题最核心的瓶颈和解决方案 (如降低时间复杂度、降低空间复杂度)分别是什么。

示例

实现一个算法,确定一个字符串中是否包含重复的字符。

示例 1

输入:s = "leetcode"
输出: false

示例 2

输入:s = "abc"
输出: true

上面这个简单的小问题,站在面试官的角度,他希望看到什么?笔者这里带入角色分析一下。

如果面试者看到题目之后,什么都不说,直接上来一个二层循环搞定并且无 Bug, 可以给 50 分,如果会判断参数的边界异常条件 (例如参数是否为空),可以给 60 分及格。

如果面试者看到题目之后,什么都不说,直接上来就写 bitset 位运算,我会提问: 题目中有没有说明字符串的字符一定是 26 个英文字母? 如果包含 unicode 字符,是不是需要准备 2^16/8 个字节的空间?

实际项目中,风险可控,结果预期更重要,绝对多数项目、绝大多数情况不在乎那点硬件资源。

所以面试者的编码能力和沟通能力同样重要,我希望面试者看到问题之后,可以先提出一些问题,例如字符串的字符集和字符范围:

  • 如果我告诉面试者字符串只包含小写英文字母,那可能在方法第一行直接判断如果字符长度 > 26, 直接返回 true,做到这一点的可以给到 80分
  • 如果我告诉面试者字符串为 ascii 字符集,面试者的代码里有边界检查,并且针对不同的范围有不同的侧重点,比如说 ascii 字符集,那也就是 128 个可能性,16 个字节的位运算就是很不错的方案
  • 如果我告诉面试者字符串为 unicode 字符集并且没有字符范围,先排序再判断是可以接受的方案,因为算法性能稳定,没有额外资源要求,并且实现简单外加可读性很高,基本可以算是通过

当然,本小节只是笔者的个人思路,不能代表所有情况,比如有的面试官就是要着重考察面试者是否可以写出 “速度最快” 的代码,请读者批判辩证看待并根据实际面试情况随机应变。

如何回答系统设计类问题

不管什么样的问题,保持冷静和头脑清醒,并按照如下的流程逐步拆解,并在回答的过程中不断和面试官沟通并获得反馈,用于确认问题的边界点和接下来的回答侧重点。

Step 1 — Understand the Goals Step 2 — Establish the Scope Step 3 — Design for the Right Scale Step 4 — Start High-Level, then Drill-Down Step 5 — Data Structures and Algorithms (DS&A) Step 6 — Tradeoffs

系统设计面试是一个开放式的对话,面试官期望你去主导这个对话,此时作为面试者要充分掌握主动权,通常来说面试官留给一个系统设计类的题目的时间也就是 5 - 10 分钟, 所以面试者只需要保证自己的回答符合场景、架构清晰、实现可行、逻辑自洽、表述清晰 (如果感觉不好表述的部分,可以直接在纸上画出流程图) 即可,切勿生搬硬套 “高大上” 的系统设计案例,弄巧成拙。

第一步:描述使用场景,约束和假设

这是展现面试者沟通能力最关键的一步,毕竟如果需求理解错了,系统设计和实现再漂亮也没有用,面试官听到问题描述之后不要急于回答,应该在仔细理解问题之后给出自己的疑问, 及时追问面试官获得问题的条件边界,并在所有疑问解决之后心里快速复盘一下是否有遗漏,然后开始思考针对问题的整体架构方案。

第二步:架构方案

罗列出所有重要组件以及每个组件的作用,最好在纸上画出基本的流程图,毕竟一图胜千言,而且可以向面试官展示文档构图能力,下面是一个示例架构图。

图片来源: https://github.com/donnemartin/system-design-primer

到了这里,系统的整体 MVP 就呈现出来了,面试者可以开始思考架构图中的核心组件如何设计。

第三步:核心组件

对第二步生成的架构方案中的每一个核心组件进行详细深入的分析。

  • 数据库选型: OLTP/OLAP/Doc/Graph
  • 数据表设计
  • 缓存设计
  • 数据结构和算法
  • 模块/服务拆分
  • Restful API
  • 结合云原生、Kubernetes 等新兴技术方案

第四步:扩展设计

现在完成了系统架构方案中核心组件的设计,系统可以运行起来了,但是为了更贴近真实环境,这里还需要考虑系统的扩展性。

  • 负载均衡
  • 水平扩展
  • 缓存高可用
  • 数据库高性能、高可用、分片分表等
  • 各类问题的 Tradeoffs

这一步的关键在于要充分论述可能遇到的问题和解决方案/代价/取舍,可以使用可扩展系统的设计原则 来处理系统瓶颈。

小结

这个仓库 收集了很多系统设计类面试题并且有多国语言版本,感兴趣的读者可以自行阅读。

遇到过最困难 (挑战) 的事情

笨拙的人讲道理,聪明的人讲故事。

所以面试时我们要摆脱常规回答,学会 “讲故事”,那故事怎么讲,记住以下八个字,然后将自己的经历或想法套进去

  • 目标:就是我想要做什么,我想要成为什么样的人
  • 阻碍:做这件事的难点是什么,有哪些 “质疑” 点
  • 努力:为了克服难点和 “质疑”,我做了哪些事情
  • 结果:通过我的努力,我现在获得了什么样的成就

好印象和坏印象

描述你以前特别感兴趣或难忘的项目经历,后续的问题包括:

  • 为什么你会觉得它有趣?
  • 该项目最具挑战性的部分是什么,你又是如何应对这些挑战的呢?
  • 你从这个项目中学习到了什么?你又希望在项目开始前了解什么?
  • 你有考虑其他的设计或实现方法吗? 你为什么选择你做的那个方案? 如果再次选择做同样的项目,你有什么不同的做法吗?

优秀的候选人

  • 充分地谈论项目经历,在面试中,与面试官的互动应当是对话而不是指导
  • 对整个项目具有一定的了解,而不仅仅是他们所关注的领域,并且能够清楚地表达出项目的设计和意图
  • 无论是什么项目,都要充满激情,并且能够清楚地描述出激发这种激情的项目要素
  • 能够清楚地解释考虑了哪些备选方案,以及他们为什么选择他们所采取的实施策略
  • 是否有从他们的经历中反思并吸取教训

好的候选人

  • 在面试中可能会遇到一些问题,但是能够在面试官的帮助下解决
  • 可能缺乏对项目更广范围的一些了解,但仍然对与他们直接交互的部分和特定领域具有很强的了解
  • 也许看起来充满激情,但无法准确解释这种激情来自何处
  • 也许能够讨论他们所做的替代方案,但是考虑的不够深刻
  • 从他们的过往经历中反思并汲取经验

差的候选人

  • 在面试交流中表现得费劲,面试官觉得面试者是在询问他,而不是与他交谈
  • 即使是在他们工作的领域,也可能缺乏对项目的详细了解。他们可能不了解他们的产品为何这样设计,或者不明白产品是如何与其他系统交互的
  • 当你在询问所做过最有趣的项目时,他们对产品表现得应该很感兴趣,但事实上是,他们看起来可能并不太感兴趣
  • 可能不熟悉潜在替代方案的实现方法
  • 似乎并没有从他们的过往项目经历中反思和学习,而判断这种情况的重要迹象是:“你学到了什么” 和 “你会有什么不同” 的答案很短,或者几乎千篇一律

你会如何考虑引入开源库

  • 项目的活跃程度
  • 项目的业务范畴、接口规格、实现是否符合预期
  • 项目所处的状态,是快速迭代阶段还是进入稳定期、缺陷的数量与严重性如何
  • 项目活跃参与者的背景

演员的自我修养

根据下面列举的问题,思考下你可能会遇到的 20 个相关面试问题,每个问题准备 2-3 种回答。准备点故事,不要只是摆一些你完成的事情的数据。

  • 你为什么想得到这份工作?
  • 你解决过的最有难度的问题是什么?
  • 面对过的最大挑战是什么?
  • 见过的最好或者最坏的设计是怎么样的?
  • 对某个产品提出改进建议?
  • 你作为一个个体同时也是团队的一员,如何达到最好的工作状态?
  • 你的什么技能或者经验是你的角色中不可或缺的,为什么?
  • 你在某份工作或某个项目中最享受的是什么?
  • 你在某份工作或某个项目中面临过的最大挑战是什么?
  • 你在某份工作或某个项目中遇到过的最硬的 Bug 是什么样的?
  • 你在某份工作或某个项目中学到了什么?
  • 你在某份工作或某个项目中哪些地方还可以做的更好?

反问面试官的问题

  • 团队多大规模?
  • 开发周期是怎样的? 会使用瀑布流/极限编程/敏捷开发么?
  • 经常会为截止日期(deadlines)加班么? 或者是有弹性的?
  • 团队里怎么做技术选型?
  • 每周平均开多少次会?
  • 你觉得工作环境有助于员工集中精力吗?
  • 目前正在做什么工作?
  • 喜欢这些事情吗?
  • 工作期限是怎么样的?
  • 工作生活怎么平衡?
  • 部门负责业务权重,技术架构,成员组成,考核方式,开发流程?
  • KPI OR OKR ?
  • 面试官对自己的建议?

反问 HR 的问题 (钱的问题)

  • 岗位晋升空间、晋升路线
  • 工资构成
  • 是否有奖金
  • 年底奖金 (固定方法还是绩效评定)
  • 其他补贴
  • 五险一金缴纳比例
  • 是否有额外商业险
  • 远程办公支持情况
  • 其他和你生活相关/冲突的问题

Reference

转载申请

本作品采用 知识共享署名 4.0 国际许可协议 进行许可,转载时请注明原文链接,图片在使用时请保留全部内容,商业转载请联系作者获得授权。