---
title: RADIO框架
description: 以结构化的方式进行前端系统设计面试。 良好的结构是成功的一半。
seo_title: 系统设计的RADIO框架｜适用于任何前端系统设计面试
seo_description: 在前端系统设计面试中应用RADIO框架，以结构化的方式指导自己。 良好的结构是成功的一半。
---

良好的开端是成功的一半。 通过使用**RADIO 框架**回答前端系统设计问题，您已经离面试成功更近了一步。

在前端系统设计面试中，您被要求设计的系统往往是产品，因此我们从这里开始将系统称为 "产品"。 首先了解**R**equirements（需求），定义高层**A**rchitecture（架构）和**D**ata Model（数据模型）。 然后定义产品组件之间的**I**nterfaces（接口），并讨论任何**O**ptimizations or dive deep（优化或深入）到需要特别关注的特定领域。

## RADIO 是什么？

1.  **Requirements Exploration 需求探索**：全面了解问题，通过提出一些明确的问题来确定问题的范围。
2.  **Architecture/High-level Design 架构/高级设计**：确定产品的关键组件以及它们之间的关系。
3.  **Data Model 数据模型**：描述各种数据实体、它们包含的字段以及它们属于哪个组件。
4.  **Interface Definition (API) 接口定义**：定义产品组件之间的接口（API）、每个 API 的功能、参数和响应。
5.  **Optimizations and Deep Dive 优化和深入**：讨论在构建产品时可能的优化机会和感兴趣的特定领域。

## 需求探索

**目标**：全面了解问题，并通过提出一些明确的问题来确定问题的范围。

**建议持续时间**：不超过会议时间的 15%。

系统设计面试问题的性质是开放式的，通常是模糊的，没有明确的目的。 **您需要深入挖掘问题，并通过提出有用的问题来澄清问题中的模糊之处。**将您的面试官视为与您合作开展新项目的产品经理，提出足够多的问题，以便您了解您要解决的问题以及您需要构建的内容。 实际上，有些问题根本不需要任何工程技术就可以解决！

尽管您可能会被问到相同的问题，但没有两次系统设计面试经历是相同的。 面试官的背景不同，可能会优先考虑系统的不同方面。 借此机会了解他们最感兴趣的内容，并据此计划您的回答。

在进入面试的下一环节之前，您应该回答一些一般性问题：

### 我们应该关注哪些主要用例？

想象一下，您被要求 "设计 Facebook"。 Facebook 是一个庞大的平台，有信息流、个人资料、好友、群组、故事等。 您应该关注 Facebook 的哪些部分？ 面试官心中已经有了答案，但希望您通过提问来找出答案。 通常情况下，您应将重点放在产品最独特的方面，即产品的特征上。 对于 Facebook 而言，这将是信息流、信息流分页和创建新帖子。 对于 YouTube 来说，这将是视频观看体验。 其他类型产品的重要区域请参见[问题类型](/system-design/types-of-questions)。

在本页的其余部分，我们将使用 "设计 Facebook "作为问题，并将框架应用于该问题。

假设您没有明确产品的重点，就认为应该谈论结交流程，并开始谈论它。 在最好的情况下，优秀的面试官会引导您回到问题本来的方向，但他们会在心里记下您没有澄清问题。 在最坏的情况下，没有经验的面试官会让您继续说下去，并礼貌地试图找机会纠正您，但您已经浪费了宝贵的几分钟来讨论一个不重要的话题。

### 什么是功能性需求和非功能性需求？

首先，什么是功能性需求和非功能性需求？

- **功能要求**：产品的基本要求，没有这些要求产品就无法运行。 这通常是指用户能否正确完成核心流程。
- **非功能性需求**：被视为产品改进的需求，但不是产品可用性的严格要求，即没有这些需求产品仍然可以使用。 其中包括性能（页面加载速度、交互速度）、可扩展性（页面上可显示多少项目）、良好的用户体验等。

您可以通过两种方式获得这个问题的答案：

1.  主动列出您认为的要求，并获得面试官的反馈和调整（首选）。
2.  直接询问面试官。 然而，在大多数情况下，他们希望您对其进行定义。 即使他们给了您答案，也不会太详细。

最起码，您的设计必须满足功能要求。 在满足所有功能需求后，继续讨论如何满足非功能需求。

### 哪些是需要关注的核心功能？

即使您知道了功能需求，仍可能有大量的小功能组成了大功能。 例如，在创建新的 Facebook 帖子时，应支持何种帖子格式？ 除了常见的基于文本的帖子外，用户是否还可以上传照片、上传视频、创建投票、到某个地点签到等。

您应事先明确核心功能并进行设计，然后再进行额外功能的设计。

### 其他问题

- 需要支持哪些设备/平台（桌面/平板/移动）？
- 是否需要离线支持？
- 产品的主要用户是谁？
- 如果有，性能要求是什么？ (性能需求通常属于非功能性需求）。

上述问题清单应能为您提供一个很好的问题起点，但并非详尽无遗！ 不同的问题将要求您提出特定领域的问题，我们将在案例研究中讨论这些问题。

建议您将商定的要求写在某个地方，以便在整个面试过程中参考，并确保您已经涵盖了这些要求。

---

## 架构/高级设计

**目标**：识别产品的关键部件以及它们之间的关系。

**建议持续时间**：约占会议的 20%。

有了这些需求，我们就可以进行架构设计了。 您的下一项任务是通过确定产品的关键组件、这些组件之间的相互作用以及它们之间的关系，提出产品/系统架构。 切记要关注**客户端架构**，而不是后端。

图表是您的朋友。 每个组件都可以用一个矩形表示，您的高层设计通常最终看起来像几个矩形框，它们之间用箭头表示数据流。 也可以在组件中包含组件，在这种情况下，使用更大的矩形绘制父组件，因为它们需要适合多个子组件。

高级前端设计中常见的组件/模块示例：

- **服务器**：在前端系统设计面试中，我们可以把服务器当作一个黑盒子，假设它暴露了一些 API，您可以通过 HTTP/WebSockets 调用。
- **视图**：表示用户看到的内容，通常包含更小的子视图。 可以只包含客户端状态。
- **控制器**：响应用户交互的模块，以视图期望的格式处理来自存储/模型的数据。 如果应用程序较小，且模块间数据传递不多，则不一定需要该模块。
- **模型/客户存储**：数据存放的地方。 存储包含的数据将通过视图呈现给用户，存储往往是整个应用程序的采访背景。 实际上，您可以在应用程序中拥有多个存储空间，并且存储空间可以包含其他存储空间。

定义组件责任时需要考虑的其他事项：

- **关注点分离**：组件是模块化的，用于封装一系列功能和数据。 考虑每个组件的目的/功能，它应包含哪些数据，以及它如何为系统的其他部分提供服务（它能为其他组件做什么）。
- **计算应在何处进行**：如果需要进行一定量的计算（例如过滤搜索结果，计算购物车的总金额），这些工作应该在服务器还是客户端完成？ 每种方法都有其优缺点，决策既取决于问题，也取决于环境。

重要的是要认识到，并非上述每个常见组件都与每个问题相关，也并非每个问题都需要，这取决于产品。

画出架构图后，口头描述每个组件（图中方框）的职责。

### 架构示例

下面是使用 Excalidraw 绘制的[信息流](/questions/system-design/news-feed-facebook)问题的架构图示例。

![架构示例图](/img/questions/news-feed-facebook/news-feed-architecture.png)

#### 组件责任

- **服务器**：为 Feed 数据提供服务，并为创建新的 Feed 帖子提供 HTTP API。
- **控制器**：控制应用程序中的数据流，并向服务器发出网络请求。
- **客户存储**：存储整个应用程序所需的数据。 在新闻提要中，存储中的大部分数据都是新闻提要用户界面所需的服务器端数据。
- **信息流用户界面**：包含信息流帖子列表和撰写新帖子的用户界面。
  - **信息流帖子**：提供信息流帖子的数据，包含与帖子互动的按钮（喜欢/反应/分享/评论）。
  - **发布器**: 提供给用户创建新的动态的用户界面。

常见的免费绘图工具包括[diagrams.net](https://app.diagrams.net/)和[Excalidraw](https://excalidraw.com/)。 最好事先熟悉一下这些工具。

---

## 数据模型

**目标**：描述各种数据实体、它们包含的字段以及它们属于哪个组件。

**建议持续时间**：约占会议时间的 10%。

现在，我们必须考虑客户端中存在哪些数据字段。 客户端应用程序有两种数据：

### 服务器端数据

源自服务器的数据，通常来自数据库，可供多人查看或从多个不同设备访问。 常见的例子包括用户数据（姓名、个人头像）和用户生成的数据（动态帖子、评论）。

### 仅客户端的数据

客户端专用数据，通常也称为状态，是只需保存在客户端而无需发送到服务器写入数据库的数据。 客户数据可进一步细分为两种：

- **需要持久化的数据**：通常是用户输入，如输入到表单域中的数据。 这些数据通常必须发送到服务器并保存到数据库中才有用。
- **短暂数据**：持续时间很短的临时状态。 常见的例子包括表单验证状态、当前选项卡、部分是否展开等。 关闭浏览器标签页时丢失这些数据通常是可以接受的。

在列出数据字段时，最好能确定该字段是哪种数据，是服务器端数据还是客户端数据。

### 数据模型示例

这是一个使用[信息流](/questions/system-design/news-feed-facebook)问题的各个实体数据模型的基本例子。

| 来源 | 实体 | 属于 | 字段 |
| --- | --- | --- | --- |
| 服务端 | `Post` | 信息流帖子 | `id`, `created_time`, `content`, `image`, `author` (a `User`), `reactions` |
| 服务端 | `Feed` | 信息流 UI | `posts`（`Post` 列表），`pagination `（分页元数据） |
| 服务端 | `User` | 客户端存储 | `id`, `name`, `profile_photo_url` |
| 用户输入（客户端） | `NewPost` | 帖子编辑器 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，允许客户机获取最新的动态帖子。

| 字段      | 值                     |
| --------- | ---------------------- |
| HTTP 方法 | `GET`                  |
| 路径      | `/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 组件的道具。

---

## 优化和深入研究

**目标**：讨论在构建产品时可能的优化机会和感兴趣的具体领域。

**建议持续时间**：约占会议的 40%。

优化和深入研究部分没有固定的方法，您可以自由地关注产品的不同领域。 我们不会有足够的时间来涵盖每一个领域，因此请根据这些指导原则谨慎选择您希望花费的时间：

- **关注产品的重要领域** 对于电子商务网站，性能至关重要，您应该花大量时间深入了解可以进行的各种性能优化。 对于协作编辑器，复杂性在于如何处理竞赛条件和并发修改，因此您需要重点解释这一点。
- **专注于您的优势**展示您的领域知识。 如果您精通无障碍性，请谈谈产品中可能出现的各种无障碍性隐患以及如何解决这些问题。 用您的知识打动面试官。 如果您是性能专家，请解释各种性能优化机会，以提供流畅的用户体验。

### 一般优化/深潜领域

以下是您在本节中可以谈论的话题列表。 请注意，题目的重要性取决于问题，有些题目与某些问题完全无关（有可能，但可能性不大）。

- 性能
- 用户体验
- 网络
- 可访问性（a11y）
- 多语言支持
- 多设备支持
- 安全

有关每个主题的详细信息，请参阅我们的[构建用户界面的最佳实践指南](/front-end-interview-guidebook/user-interface-questions-cheatsheet)。

---

## 总结

| 步骤 | 目标 | 推荐时长 |
| --- | --- | --- |
| 需求探索 | 通过提出一些明确的问题来全面了解问题并确定其范围。 | \<15% |
| 架构/高级设计 | 识别产品的关键部件以及它们之间的关系。 | ~20% |
| 数据模型 | 描述各种数据实体、它们包含的字段以及它们属于哪个组件。 | ~10% |
| 接口定义 | 定义产品的组件之间的接口 (API)，每个 API 的功能、参数和响应。 | ~15% |
| 优化和深入研究 | 讨论在构建产品时可能的优化机会和感兴趣的具体领域。 | ~40% |
