终于要讲到答题框架了!
我们说系统设计面试题没有统一的答案,但答题过程还是有一定的规律可寻,这就是第 3 章要讲到的答题框架。
系统设计面试中,经常会被问到如何设计微信、如何设计微博、如何设计百度……我们怎么能在如此短的时间内设计出来一个由成千上万的码农、PM,经年累月地迭代出来的如此优秀的产品?如果面试者这么优秀,那还面试啥?百度、谷歌也不可能只是一个搜索框而已,底下的东西复杂去了。
所以,这种问题的答案一定不可能是全面的,面试官也不会期望我们给出一个满分答案,这点是要首先明确的。
所谓的系统设计面试实际上是在模拟一个场景:两名同事在一起就一个模糊的问题,讨论一番,得出一个还不错的解决方案。
问题是开放性的,没有标准答案。并且最终的设计是怎么样并没有求职者在整个过程中表现出来的能力、思维方式重要。过程中,我们需要“一惊一乍”,需要回答面试官的问题、回应他的质疑、证明我们的选择。
面试官的目标是充分挖掘求职者的能力,并在面试结束时给出过或不过的结论。
那么面试官到底想在一场系统设计的面试中得到关于求职者的什么信息呢?
很多人认为系统设计面试就是考察求职者的技术设计能力。但真实情况要考虑得更多:合作能力、抗压能力、问出高水平问题的能力……甚至有一些面试官非常看重问问题的能力。
另一方面,面试官也在寻找一些“不好的品质”,例如过度设计。求职者倾向于设计出一些完美、不做取舍,不控制成本的方案。这样的人招进来后,最终需要公司买单。其他“不好的品质”还包括:思路狭窄、固执、沟通能力差……这些都是要尽量避免表现出来的。
四步法
虽然系统设计面试是开放性的,且没有“一招吃遍天下”的招式,但一次成功的面试还是会遵循一些步骤:4 步法。
第一步:理解问题,设定边界
当面试官给出问题时,不要马上给出答案。系统设计面试没有标准答案,脱口而出说明求职者并没有考虑清楚。当没有彻底理解面试官意图的情况下就给一个答案通常会给面试官释放一个不好的信号:我很浮躁。
要想厘清问题,弄清面试官真实的意图是什么,就必须要和面试官你来我往地问问题。第一步就是要确定要求和假设。
对于求职者,在弄清问题后,不要马上就给出一个最终的设计版本,因为这通常会是一个错误的版本。始终要记住:最终的设计是什么样并没有那么重要,重要的信息已经整个面试过程中传递给了面试官。
所以正确的做法是:在做设计的同时,问面试官的要求是什么,做出合理的假设、取舍,让面试官看出你的思考过程,最终综合所有的信息完成一个还不错的设计。
不要害怕问问题。那并不会说明我们不懂,而是让面试官理解我们的思考过程。
当我们问出问题后,面试官要么给出明确的回答;要么让我们自己做出假设。当需要做出假设时,我们需要把假设写下来备用。
那我们应该问出什么样的问题呢?这有一些典型的例子:
- 这个系统的核心功能是什么?
- 有多少用户使用我们的产品?
- 公司的业务发展速度怎么样,3 个月、半年、一年后,规模会变成多大?
- 公司的技术栈是什么?有什么现存的服务可以简化我们的设计。
第二步:提出整体设计,达成一致
这一步,目标是画出一个高层次的整体设计,过程中和面试官合作,并和面试官达成一致。
- 想出一个最初版本的设计。询问面试官是否可行。要把面试官当成一起工作的同事,这就是一个平常的讨论。
- 在纸上用线框图画出关键的组件。包括:客户端、API、服务端、数据库、缓存、CDN、消息队列……
- 做一个估算,看第一版的设计是否满足当前的用户规模。当然,是否要做估算可以先和面试官交流。
如果可能的话,设想几个具体的例子,对着图演练一遍。这让我们能更坚定当前的设计,有时候还能发现一些未考虑到的边界 case。
有个问题是:我们需要设计 API 和数据库的 schema 吗?这个取关于面试题是什么,如果面试官让我们设计一个谷歌搜索引擎,那显然是不需要的,这个问题层次太低了。但如果问题是设计一个多人扑克游戏的后端,可能这就是考点了。当然,这些都可以向面试官求证,由他决定。
第三步:深入设计
到达这一步时,我们和面试官应该已经达成了如下的一致:
- 总体目标和要完成的功能
- 一个整体设计图
- 从面试官那里获得了关于这个设计的反馈
- 通过反馈,知道了接下来要对哪些方面做深入细致的设计
我们要和面试官确定接下来应该聚焦到哪些组件,这在不同面试场景中不会相同。即使是相同的题目,不同的面试官想考察的点也可能不一样。有些面试官就喜欢讨论顶层设计,画 PPT 好看