---
title: 应用架构
---

上一章节中，我们把硬编码的 `mockData` 改成从 BFF 加载，从 `App.tsx` 里拆分出了 `components/AllContacts.tsx` 和 `components/ArchivedContacts.tsx`，在 `AllContacts` 组件里用 BFF 函数，获取到联系人数据之后，保存在 `AllContacts` 的组件内部状态里，而 `ArchivedContacts` 组件暂时继续使用 mock 数据。

本章节中，为了进一步实现项目功能，我们需要让 `AllContacts` 和  `ArchivedContacts` 都从 BFF 获取数据，还要实现【 Archive 】按钮，点击按钮能把联系人归档。

业务逻辑变复杂之后，相关代码不可避免会变多，如果都写在 AllContacts 组件或其他组件里，都会让这个组件的可读性和可维护性变差，让做不同事情的代码混在一起。

原本可以跟 UI 完全解耦的业务逻辑（比如网络请求、纯数据的操作、状态的管理等）跟 UI 逻辑（比如联系人列表如何展现）混在一起，当需要修改 UI 的时候，不得不跟 UI 无关的业务逻辑代码打交道，反过来也一样，不符合【 [单一职责原则（SRP）](https://zh.wikipedia.org/wiki/%E5%8D%95%E4%B8%80%E5%8A%9F%E8%83%BD%E5%8E%9F%E5%88%99)】，也做不到【 [关注点分离（SoC）](https://zh.wikipedia.org/wiki/%E5%85%B3%E6%B3%A8%E7%82%B9%E5%88%86%E7%A6%BB)】。

从这里开始，我们发现如果这是个真实的项目，继续这样写下去会产生越来越多面条式代码，仅凭 React 组件这一种抽象方式，不足以让代码足够结构化，随着项目不断积累业务逻辑、复杂性和变更，技术债也会积累，最终可能变成没人愿意碰的祖传代码。

像这样的项目，需要更健全的**客户端应用架构**。

Modern.js 提供开箱即用的**应用架构**，支持几种扮演不同**角色（role）**、属于不同**分层（layer）**的代码模块类型，可以把业务逻辑解耦到不同类型的代码模块里，做到高[内聚](https://zh.wikipedia.org/wiki/%E5%85%A7%E8%81%9A%E6%80%A7_(%E8%A8%88%E7%AE%97%E6%A9%9F%E7%A7%91%E5%AD%B8))低[耦合](https://zh.wikipedia.org/wiki/%E8%80%A6%E5%90%88%E6%80%A7_(%E8%A8%88%E7%AE%97%E6%A9%9F%E7%A7%91%E5%AD%B8))。

之前介绍的 `App.tsx` 和 `pages/` 都是其中一种代码模块，通过在最顶层对客户端路由的管理，把其他代码模块最终组织到一起，形成应用。

当前项目里 `components/` 目录中的 React 组件，是一种可以称作【 视图组件 】的代码模块，负责 UI、交互上的界面展现。

本章节我们来把 `AllContacts` 组件中可以跟 UI 解耦的业务逻辑，移到一种叫【 Model（业务模型）】的代码模块里。
