> ## Documentation Index
> Fetch the complete documentation index at: https://meta.niceshare.site/llms.txt
> Use this file to discover all available pages before exploring further.

# 关注点分离

> 关注点分离（SoC）是一种将软件划分为不同模块，每个模块处理特定关注点的设计原则。了解其起源、优势以及如何应用。

<Info>
  **类别**: 原则<br />
  **类型**: 软件架构原则<br />
  **来源**: Edsger W. Dijkstra，1974<br />
  **别名**: SoC，关注点分离
</Info>

<Note>
  **快速回答** — 关注点分离（Separation of Concerns，SoC）是一种将软件系统划分为不同部分，每个部分处理各自独立关注点的设计原则。由Edsger W. Dijkstra于1974年提出，这一原则是现代软件架构的基石，能够实现复杂系统的可维护性、可扩展性和清晰性。
</Note>

## 什么是关注点分离？

关注点分离是一种将软件系统分解为不同模块的实践，每个模块处理一个特定的关注点。"关注点"是指系统中任何感兴趣的领域或职责——如业务逻辑、数据持久化、用户界面、安全或网络。通过隔离这些关注点，开发者可以独立处理各个部分而不影响其他部分。

> "关注点分离是前进的唯一途径。" — Edsger W. Dijkstra

这一原则源于Dijkstra 1974年的论文《论科学思维的作用》，他在文中指出人脑一次只能容纳有限的信息。通过将问题分解为不同的关注点，我们使其变得易于人类理解和处理。

在现代软件开发中，SoC体现在各个层面。在最高层级，你可能会将展示层与业务逻辑层分开。在模块层级，你可能会将数据访问与领域逻辑分开。在函数层级，你可能会将纯计算与副作用分开。每一层都有明确的职责，通过定义良好的接口与其他层交互。

### 关注点分离的三层理解

* **入门**：识别任何代码中不同的关注点。如果你的用户界面代码中包含SQL查询，那就是关注点的混合。将每个关注点移到它自己的位置。

* **实践**：使用强制执行SoC的架构模式，例如用于Web应用的模型-视图-控制器（MVC）或用于企业系统的分层架构。

* **进阶**：在组织层面应用关注点分离。康威定律表明，系统设计往往反映沟通结构。按关注点组织团队，以实现并行开发并减少协调开销。

## 起源

"关注点分离"一词由Edsger W. Dijkstra引入，他是历史上最有影响力的计算机科学家之一。在1974年的散文《论科学思维的作用》中，Dijkstra讨论了人类认知的局限性，以及将问题分解为可管理的部分对于应对复杂性至关重要。

Dijkstra的见解早于现代软件工程，但随着软件系统变得越来越复杂，它变得越来越重要。在接下来的几十年中，SoC被嵌入 numerous 架构模式中：1970年代的模块化编程、1980年代的面向对象设计、2000年代的服务导向架构，以及2010年代的微服务。

该原则也连接了更广泛的政治哲学中的"三权分立"概念——正如民主政府将立法、行政和司法权力分开以防止权力集中，软件系统也分离关注点以防止复杂性变得无法管理。

## 核心要点

<Steps>
  <Step title="提升可理解性">
    当每个模块处理一个关注点时，开发者可以理解和处理各个部分，而无需掌握整个系统。
  </Step>

  <Step title="支持并行开发">
    良好分离的关注点允许不同的开发者或团队同时工作，而不会相互干扰彼此的进度。
  </Step>

  <Step title="便于测试">
    隔离的关注点可以独立测试。你可以单独对业务逻辑进行单元测试，而不需要用户界面、数据库或网络连接。
  </Step>

  <Step title="降低变更影响">
    当某个关注点发生变化时，其影响是局部的。对用户界面的修改不应该需要修改业务逻辑。
  </Step>
</Steps>

## 应用场景

<CardGroup cols={2}>
  <Card title="分层架构">
    将代码组织成层（展示层、业务逻辑层、数据访问层）。每层有特定的角色，通过接口与相邻层通信。
  </Card>

  <Card title="组件设计">
    围绕特定职责设计软件组件。支付组件处理支付；通知组件处理通知。
  </Card>

  <Card title="函数式编程">
    将纯函数（无副作用）与非纯函数（I/O、状态变更）分离。这使代码更容易理解和测试。
  </Card>

  <Card title="横切关注点">
    使用面向切面编程等技术来处理影响系统多个部分的关注点，如日志或安全，而不会污染业务代码。
  </Card>
</CardGroup>

## 经典案例

2000年代初，一个大型电子商务平台艰难应对一个单体代码库，业务逻辑、数据库查询和HTML模板交织在相同的PHP文件中。一个由五名开发者组成的团队管理着数千个文件，但由于破坏无关功能的风险，添加新功能需要数月时间。

该公司采用了模型-视图-控制器（MVC）架构，这强制在数据（模型）、展示（视图）和逻辑（控制器）之间进行分离。他们还实现了一个独立的数据访问层。

结果改变了开发速度。原先需要三个月的新功能在三周内就能交付。开发者可以专业化——一些人专注于用户体验，另一些人专注于业务规则——而不会互相干扰。平台可以扩展，因为每个关注点都可以独立优化或替换：他们从关系数据库切换到NoSQL来存储产品目录，而无需触及展示层。

这个案例展示了SoC的力量：通过围绕不同关注点组织代码，曾经的瓶颈变成了一个可扩展、可维护的系统。

## 边界与失效场景

最常见的失败是创建不符合实际关注点的人为边界。没有逻辑理由地将代码分成不同的文件或模块会增加复杂性而没有好处。关注点应该基于*变更理由*来分离——因不同原因变更的事物应该放在不同的地方。

另一个陷阱是过度分离，当管理多个模块的成本超过收益时。如果两个关注点总是同时发生变化，将它们放在一起通常更合理。

边界条件：当收益——降低复杂性、并行开发、可测试性——超过创建和维护分离的成本时，才应用SoC。从粗粒度的分离开始，随着模式的出现再细化。

## 常见误区

<AccordionGroup>
  <Accordion title="误区：SoC意味着更多文件">
    分离不是关于创建更多文件——而是关于逻辑组织。你可以通过清晰的命名和结构在同一文件内实现分离，尽管单独的文件通常更清晰。
  </Accordion>

  <Accordion title="误区：SoC只适用于代码">
    该原则延伸到代码之外。你可以在系统架构、API设计、文档甚至组织结构中分离关注点。
  </Accordion>

  <Accordion title="误区：SoC消除复杂性">
    分离管理复杂性但不消除它。系统仍然具有相同的总复杂性；SoC通过将其分布在专注的模块中，使其更容易被人类理解。
  </Accordion>
</AccordionGroup>

## 相关概念

关注点分离与其他基本软件设计原则密切相关：

<CardGroup cols={3}>
  <Card title="单一职责原则">
    SoC和SRP密切相关。SRP通常被认为是在类和函数层面实现SoC的方式。
  </Card>

  <Card title="模块化">
    模块化是SoC的实际应用，创建具有明确定义接口的自包含模块。
  </Card>

  <Card title="内聚性">
    内聚性衡量单个模块的职责之间关联程度。模块内的高内聚性与SoC相辅相成。
  </Card>
</CardGroup>

## 一句话总结

<Tip>
  **根据不同的职责领域将系统划分为模块——每个关注点都有自己的位置，使整个系统更容易理解、开发和维护。**
</Tip>
