266 lines
15 KiB
Plaintext
266 lines
15 KiB
Plaintext
---
|
||
title: RADIO 框架
|
||
description: 以结构化的方式进行前端系统设计面试。一个好的结构是成功的一半。
|
||
seo_title: RADIO 框架 | 前端系统设计实战
|
||
social_title: 用于构建前端系统设计答案的 RADIO 框架 | GreatFrontEnd
|
||
seo_description: 一个强大的框架,旨在帮助您以结构化的方式回答前端系统设计面试问题。
|
||
---
|
||
|
||
一个好的开始是成功的一半。通过使用 **RADIO 框架** 来回答前端系统设计问题,您将更接近于在面试中取得好成绩。
|
||
|
||
在前端系统设计面试的背景下,您被要求设计的系统往往是产品,因此我们从这里开始将系统称为“产品”。首先要了解 **R**equirements(需求),定义高级 **A**rchitecture(架构)和 **D**ata Model(数据模型)。然后定义产品中组件之间的 **I**nterfaces(接口),并讨论任何 **O**ptimizations(优化)或深入研究需要特别关注的特定领域。
|
||
|
||
## RADIO 是关于什么的?
|
||
|
||
1. **需求探索**:彻底了解问题,并通过提出一些澄清问题来确定范围
|
||
2. **架构/高级设计**:确定产品的关键组件以及它们之间的相互关系
|
||
3. **数据模型/核心实体**:描述核心实体及其数据——每个实体包含的字段以及它们属于哪个(些)组件
|
||
4. **接口定义(API)**:定义产品中组件之间的接口(API)、每个 API 的功能、它们的参数和响应
|
||
5. **优化和深入研究**:讨论构建产品时可能的优化机会和特定感兴趣的领域
|
||
|
||
## 需求探索
|
||
|
||
**目标**:彻底了解问题,并通过提出一些澄清问题来确定范围。
|
||
|
||
**建议时长**:不超过会话的 15%。
|
||
|
||
系统设计面试问题本质上是开放式的,通常是模糊的,并且故意未充分说明。**您需要通过提出有用的问题来深入挖掘并澄清问题中的歧义。** 将您的面试官视为您正在合作进行新项目的项目经理,提出足够的问题,以便您知道您要尝试解决的问题以及您需要构建的内容。实际上,有些问题根本不需要任何工程就可以解决!
|
||
|
||
即使您之前被问过相同的问题,也不会有两次系统设计面试经历是相同的。面试官的背景各不相同,可能优先考虑系统的不同方面。借此机会找出他们最感兴趣的内容,并相应地计划您的答案。
|
||
|
||
在进入面试的下一部分之前,您应该获得一些一般性问题的答案:
|
||
|
||
### 我们应该关注哪些主要用例?
|
||
|
||
假设您被要求“设计 Facebook”。Facebook 是一个巨大的平台,有新闻提要、个人资料、朋友、群组、故事等等。您应该关注 Facebook 的哪些部分?面试官心里有答案,但希望您通过提问来找出答案。通常,您应该关注产品最独特的方面,即定义它的功能。对于 Facebook 来说,它将是新闻提要、提要的分页以及创建新帖子。对于 YouTube 来说,这将是观看视频的体验。其他类型产品的重要领域可以在[问题类型](/system-design/types-of-questions#examples)中找到。
|
||
|
||
在这一页的其余部分,我们将使用“设计 Facebook”作为问题,并将其应用于该框架。
|
||
|
||
假设您没有澄清要关注产品的哪些部分,并且您认为您应该谈论交友流程并开始谈论它。在最好的情况下,好的面试官会引导您回到问题的本意,但他们会注意到您没有澄清问题。在最坏的情况下,经验不足的面试官会让你继续说下去,并礼貌地寻找机会纠正你,但你已经浪费了一些宝贵的时间来讨论一个不重要的话题。
|
||
|
||
### 什么是功能需求和非功能需求?
|
||
|
||
首先,什么是功能需求和非功能需求?
|
||
|
||
* **功能需求**:产品的基本要求,如果没有这些要求,产品就无法运行。这通常是用户是否可以正确完成核心流程。
|
||
* **非功能需求**:被视为对产品的改进,但并非产品可用的严格要求,即没有这些产品仍然可以使用。这些包括性能(页面加载速度、交互速度)、可扩展性(页面上可以存在多少个项目,然后页面才会变慢)、良好的用户体验等。
|
||
|
||
你可以通过两种方式获得这个问题的答案:
|
||
|
||
1. 主动列出你认为的需求,并从面试官那里获得反馈和一致意见(首选)。
|
||
2. 直接问面试官。但是,大多数时候他们希望你定义它们。即使他们给你一个答案,也不会太详细。
|
||
|
||
至少,你的设计必须满足功能需求。在满足所有功能需求后,继续讨论如何满足非功能需求。
|
||
|
||
### 哪些是需要关注的核心功能,哪些是锦上添花的功能?
|
||
|
||
即使你知道了功能需求,仍然可能有很多小功能构成大功能。例如,在创建新的 Facebook 帖子时,应该支持什么样的帖子格式?除了通常的基于文本的帖子之外,用户是否应该能够上传照片、上传视频、创建投票、签到某个位置等。
|
||
|
||
你应该事先明确核心功能,并在继续讨论额外功能之前为它们进行设计。
|
||
|
||
### 其他问题:
|
||
|
||
* 需要支持哪些设备/平台(桌面/平板电脑/移动设备)?
|
||
* 是否需要离线支持?
|
||
* 该产品的主要用户是谁?
|
||
* 有什么性能要求吗?如果有的话?性能要求通常属于非功能性需求
|
||
|
||
上面的问题应该为您提供一个良好的开端列表,但这绝不是一个详尽的列表!不同的问题将要求您提出特定于领域的问题,我们将在案例研究中讨论这些问题。
|
||
|
||
建议你将商定的要求写在某个地方,以便你可以在整个面试过程中参考它们,并确保你已经涵盖了它们。
|
||
|
||
***
|
||
|
||
## 架构/高层设计
|
||
|
||
**目标**:确定产品的关键组件以及它们之间的相互关系。
|
||
|
||
**推荐时长**:大约占总时长的 20%。
|
||
|
||
考虑到这些要求,我们可以继续进行架构设计。你的下一个任务是通过确定产品的关键组件、组件之间的交互方式以及它们之间的关系来提出一个产品/系统架构。请记住专注于**客户端架构**,而不是后端。
|
||
|
||
图表是您在这里的朋友。每个组件都可以用一个矩形表示,您的高级设计通常最终看起来像几个矩形框,它们之间有箭头来演示数据的流程。也可以在组件内包含组件,在这种情况下,使用更大的矩形绘制父组件,因为它们需要容纳多个子组件。
|
||
|
||
前端设计高级设计中常见的组件/模块示例:
|
||
|
||
* **服务器**:在前端系统设计面试中,我们可以将服务器视为一个黑盒,并假设它公开了一些您可以通过 HTTP/WebSockets 调用的 API。
|
||
* **视图**:这代表用户看到的内容,它通常包含其中的较小子视图。可以仅包含客户端状态。
|
||
* **控制器**:响应用户交互并以视图期望的格式处理来自存储/模型的数据的模块。如果应用程序很小,并且模块之间没有太多数据传递,则不一定需要此模块。
|
||
* **模型/客户端存储**:数据所在的位置。存储包含将通过视图呈现给用户的数据,并且存储在面试环境中往往是应用程序范围的。实际上,您可以在一个应用程序中拥有多个存储,并且存储可以包含其他存储。
|
||
|
||
定义组件的职责时要考虑的其他事项:
|
||
|
||
* **关注点分离**:组件旨在模块化,并用于封装一组功能和数据。考虑每个组件的目的/功能、它应该包含什么数据以及它如何为系统的其余部分提供服务(它可以为其他组件做什么)。
|
||
* **应该在哪里进行计算**:如果需要进行一些计算(例如,根据搜索词过滤结果,计算购物车的总金额),应该在服务器还是客户端完成这项工作?每种方法都有权衡,并且该决定既取决于产品,也取决于上下文。
|
||
|
||
重要的是要认识到,上面提到的并非每个常见组件都与每个产品相关且必要,这取决于产品的独特方面。
|
||
|
||
在绘制出架构图后,用语言描述每个组件(图中的框)的职责。
|
||
|
||
### 架构示例
|
||
|
||
这是一个使用 Excalidraw 绘制的 [新闻提要](/questions/system-design/news-feed-facebook) 问题的架构图示例。
|
||
|
||

|
||
|
||
#### 组件职责
|
||
|
||
* **服务器**:提供 feed 数据,并提供一个 HTTP API 以创建新的 feed 帖子。
|
||
* **控制器**:控制应用程序内的数据流,并向服务器发出网络请求。
|
||
* **客户端存储**:存储整个应用程序所需的数据。在新闻提要的上下文中,存储中的大多数数据将是 feed UI 所需的服务器生成的数据。
|
||
* **Feed UI**:包含 feed 帖子的列表以及撰写新帖子的 UI。
|
||
* **Feed 帖子**:呈现 feed 帖子的数据,并包含与帖子交互的按钮(喜欢/反应/分享/评论)。
|
||
* **帖子撰写器**:用户创建新 feed 帖子的 UI。
|
||
|
||
你可能被要求使用的常见免费绘图工具包括 [diagrams.net](https://app.diagrams.net/) 和 [Excalidraw](https://excalidraw.com/)。最好事先熟悉这些工具。
|
||
|
||
***
|
||
|
||
## 数据模型
|
||
|
||
**目标**:描述各种数据实体、它们包含的字段以及它们所属的组件。
|
||
|
||
**推荐时长**:大约占会话的 10%。
|
||
|
||
我们现在必须考虑客户端中存在哪些数据字段。客户端应用程序中有两种数据:
|
||
|
||
### 服务器生成的数据
|
||
|
||
源自服务器的数据,通常来自数据库,供多个人查看或从多个不同的设备访问。常见示例包括用户数据(姓名、个人资料图片)和用户生成的数据(feed 帖子、评论)。
|
||
|
||
### 仅客户端数据
|
||
|
||
仅客户端数据,也常被称为状态,是只需要存在于客户端的数据,不需要发送到服务器写入数据库。客户端数据可以进一步细分为两类:
|
||
|
||
* **要持久化的数据**:通常是用户输入,例如输入到表单字段中的数据。这些数据通常必须发送到服务器并保存到数据库中才能有用。
|
||
* **临时数据**:持续很短时间的临时状态。常见的例子包括表单验证状态、当前导航选项卡、某个部分是否已展开等。当浏览器选项卡关闭时,丢失这些数据通常是可以接受的。
|
||
|
||
在列出数据字段时,确定该字段是什么类型的数据,是服务器生成的数据还是仅客户端数据会很有用。
|
||
|
||
### 数据模型示例
|
||
|
||
以下是使用 [新闻源](/questions/system-design/news-feed-facebook) 问题的各种实体的基本数据模型示例。
|
||
|
||
| 来源 | 实体 | 属于 | 字段 |
|
||
| --- | --- | --- | --- |
|
||
| 服务器 | `Post` | Feed Post | `id`, `created_time`, `content`, `image`, `author` (a `User`), `reactions` |
|
||
| 服务器 | `Feed` | Feed UI | `posts` (list of `Post`s), `pagination` (pagination metadata) |
|
||
| 服务器 | `User` | Client Store | `id`, `name`, `profile_photo_url` |
|
||
| 用户输入(客户端) | `NewPost` | Feed Composer UI | `message`, `image` |
|
||
|
||
根据您在问题中的进展程度以及需求在面试期间的演变和增长情况,您可能需要添加更多字段。这是一个动态和迭代的过程。
|
||
|
||
您可能希望在架构图中拥有它们的组件附近编写这些字段。
|
||
|
||
***
|
||
|
||
## 接口定义 (API)
|
||
|
||
**目标**:定义产品中组件之间的接口、各种 API 的功能、它们的参数和响应。
|
||
|
||
**推荐时长**:大约占会话的 15%。
|
||
|
||
有了每个组件中的组件和数据,我们就可以继续讨论组件之间的接口 (API)。API 是一个重载术语,通常指软件组件之间进行通信以及请求/发送组件之间数据的协议。客户端和服务器通过网络层 API(HTTP/WebSockets)进行通信。客户端组件通常通过浏览器运行时中的函数进行通信。所有 API 都有三个共同点,无论它们是在服务器和客户端之间还是在客户端组件之间:
|
||
|
||
| API 的组成部分 | 服务器-客户端 | 客户端-客户端 |
|
||
| --- | --- | --- |
|
||
| 名称和功能 | HTTP 路径 | JavaScript 函数 |
|
||
| 参数 | HTTP GET 查询和 POST 参数 | 函数参数 |
|
||
| 返回值 | HTTP 响应,通常为 JSON 格式 | 函数返回值 |
|
||
|
||
### 服务器-客户端 API 示例
|
||
|
||
再次使用 [新闻源系统设计](/questions/system-design/news-feed-facebook) 示例,我们有一个服务器 API,允许客户端获取最新的 feed 帖子。
|
||
|
||
| 字段 | 值 |
|
||
| --- | --- |
|
||
| HTTP 方法 | `GET` |
|
||
| 路径 | `/feed` |
|
||
| 描述 | 获取用户的 feed 结果。 |
|
||
|
||
#### 参数
|
||
|
||
feed 响应是一个分页列表,因此 API 期望分页参数。
|
||
|
||
```json
|
||
{
|
||
"size": 10,
|
||
"cursor": "=dXNlcjpXMDdRQ1JQQTQ"
|
||
}
|
||
```
|
||
|
||
#### 响应
|
||
|
||
```json
|
||
{
|
||
"pagination": {
|
||
"size": 10,
|
||
"next_cursor": "=dXNlcjpVMEc5V0ZYTlo"
|
||
},
|
||
"results": [
|
||
{
|
||
"id": "123",
|
||
"author": {
|
||
"id": "456",
|
||
"name": "John Doe"
|
||
},
|
||
"content": "Hello world",
|
||
"image": "https://www.example.com/feed-images.jpg",
|
||
"reactions": {
|
||
"likes": 20,
|
||
"haha": 15
|
||
},
|
||
"created_time": 1620639583
|
||
}
|
||
// ... More posts.
|
||
]
|
||
}
|
||
```
|
||
|
||
### 客户端-客户端 API 示例
|
||
|
||
客户端-客户端 API 可以用与服务器-客户端 API 类似的方式编写,主要区别在于它们是 JavaScript 函数,或者正在侦听的事件。要描述的最重要的部分是 API 的功能、参数和返回/响应值。
|
||
|
||
### UI 组件系统设计的 API
|
||
|
||
如果您被要求设计一个 UI 组件,对于“接口”部分,请讨论该组件的自定义选项,类似于 React 组件的 props。
|
||
|
||
***
|
||
|
||
## 优化和深入研究
|
||
|
||
**目标**:讨论构建产品时可能的优化机会和特定的感兴趣领域。
|
||
|
||
**推荐时长**:大约占会议的 40%。
|
||
|
||
优化和深入研究部分没有固定的方法,您可以自由地专注于产品的不同领域。没有足够的时间来涵盖每个领域,因此请根据以下指南仔细选择您想如何分配时间:
|
||
|
||
* **关注产品的重要领域**:对于电子商务网站,性能至关重要,您需要花费大量时间深入研究可以完成的各种性能优化。对于协作编辑器,复杂之处在于如何处理竞争条件和并发修改,因此您需要专注于解释这一点。
|
||
* **专注于您的优势**:展示您的领域知识。如果您精通可访问性,请谈谈产品中可能发生的各种可访问性陷阱以及如何解决它们。用您的知识给面试官留下深刻印象。如果您是性能大师,请解释可以提供流畅用户体验的各种性能优化机会。
|
||
|
||
### 一般优化/深入研究领域
|
||
|
||
以下是您可以讨论的本节主题列表。请记住,主题的重要性取决于产品,某些主题与某些产品完全无关(可能但不太可能)。
|
||
|
||
* 性能
|
||
* 用户体验
|
||
* 网络
|
||
* 可访问性 (a11y)
|
||
* 多语言支持
|
||
* 多设备支持
|
||
* 安全性
|
||
|
||
有关每个主题的详细信息,请参阅我们的 [构建用户界面的最佳实践指南](/front-end-interview-guidebook/user-interface-questions-cheatsheet)。
|
||
|
||
***
|
||
|
||
## 总结
|
||
|
||
| 步骤 | 目标 | 推荐时长 |
|
||
| --- | --- | --- |
|
||
| 需求探索 | 彻底了解问题,并通过提出一些澄清问题来确定范围。 | \<15% |
|
||
| 架构/高级设计 | 确定产品的关键组件以及它们之间的关系。 | ~20% |
|
||
| 数据模型 | 描述各种数据实体、它们包含的字段以及它们所属的组件。 | ~10% |
|
||
| 接口定义 (API) | 定义产品中组件之间的接口 (API)、每个 API 的功能、它们的参数和响应。 | ~15% |
|
||
| 优化和深入研究 | 讨论构建产品时可能的优化机会和特定的感兴趣领域。 | ~40% |
|