在計算機科學中，**關注點分離**（Separation of concerns，SoC），是將計算機程序分隔為不同部份的設計原則。每一部份會有各自的關注焦點。關注焦點是影響計算機程式程式碼的一組資訊。關注焦點可以像是將程式碼優化過的硬件細節一般，或者像實例化類別的名稱一樣具體。展現關注點分離設計的程序被稱為模組化程序。模組化程度，也就是區分關注焦點，通過將資訊封装在具有明確界面的程序代碼段落中。封裝是一種資訊隱藏手段。資訊系統中的分層設計是關注點分離的另一個實施例（例如，表示層，業務邏輯層，數據訪問層，持久數據層）。

关注点分离，是對只与「特定概念、目标」（關注點（英语：））相关联的软件组成部分進行「标识、封装和操纵」的能力，即标识、封装和操纵关注点的能力。是处理复杂性的一个原则。由于关注点混杂在一起会导致复杂性大大增加，所以能够把不同的关注点分离开来，分别处理就是处理复杂性的一个原则，一种方法。分离关注点使得解决特定领域问题的程式碼从业务逻辑中独立出来，业务逻辑的程式碼中不再含有针对特定领域问题程式碼的调用（將针对特定领域问题程式碼抽象化成較少的程式碼，例如將程式碼封裝成function或是class），業務邏輯同特定领域问题的关系通过侧面来封装、维护，这样原本分散在整个应用程序中的变动就可以很好的管理起来。

關注點分離的價值在於簡化計算機程序的開發和維護。當關注點分開時，各部份可以重複使用，以及獨立開發和更新。具有特殊價值的是能夠稍後改進或修改一段代碼，而無需知道其他部分的細節必須對這些部分進行相應的更改。

實作
--

編程語言提供的物件導向設計或模块化编程機制，就是允許開發人員提供SoC的機制。例如，C#，C++，Delphi和 Java等物件導向的編程語言可以將關注點分解為物件，像MVC或MVP這樣的架構設計模式，將內容從呈現和數據處理（模型）與內容分開（呈现与内容分离）。服務導向（英语：）的設計可將關注點分解為服務（英语：）。諸如C和Pascal之類的程序式編程語言可將關注點分成過程或函数。面向切面編程語言可以將關注點分解為方面（英语：）和對象。

在許多其他領域，例如城市規劃、建築或信息设计，分離關注點也是一個重要的設計原則。目標是更有效地理解，設計和管理許多功能相互依存的複雜系統，以便功能可以重用，獨立於其他功能進行優化，並且避免其他功能的潛在故障。常見的例子包括將一個空間分隔成多個房間，這樣一個房間的活動不會影響其他房間的人；或是配電將爐子保持在一個電路，而燈光則保持在另一個電路上，這樣爐子的超載就不會影響燈光。房間分隔的例子顯示了封裝，其中一個房間內的資訊（無論有多混亂）不會用於其他房間，除非通過界面（門是接口）。電路的例子表明，一個模組內部的活動是一個電力消費者附加的電路，不會影響不同模塊中的活動，因此每個模組不會額外去關注另一個模塊發生的情況。

起源
--

这个概念是1974年，艾茲赫爾·戴克斯特拉在他的文章《On the role of scientific thought》中提出的。

> 让我告诉你，对我来说所有聰明的思考的共通特性是什么。一个人要有系统地深入研究一门课题；必须將這們課題獨立出來，記住在任何時候都只能关注其中一个方面。 比如说，我们知道一个程式必须是正确的，因此我们可以只抓这个点来研究；我们同时也清楚它应当是高效率的，我们可以改天来研究它的效率，等等。我们也可以问自己，程式是否是可取的（desirable）？如果是，为什么？相反的，同时应对好幾個个方面不會得到任何結果！这就是我有时提到的「the separation of concerns（关注点分离）」。这个技巧就算不是完美可行的，也仍是我知道有效地组织思维的唯一可用技巧。这是就是我说的「将一个人的注意力集中在几个方面上」。这并不是说忽略其他方面，只是表明从这个方面来看，其他方面並无关紧要这一事实。这即是同时拥有单任务和多任务思维。
> 
> 

15年之后，这个概念已经被人们所接受。1989年，Chris Reade写的《Elements of Functional Programming》有这样的描述：

> 一个程式在執行的时候一定会同时做以下几件事情：
> 
> 
> 1. 描述所要解决的问题
> 2. 按照计算的顺序分成几个部分执行
> 3. 同时处理内存管理
> 

Reade 接着说,

> 理想情况下，程序员应该只关注第一个問題（所要解决的问题），因为这个问题是更应该被关注。很明显的，我们可以通过解決重要的問題來得到更可靠的结果。
> 
> 
> 分离关注还有其它的好处。比如，程式可以分離内存管理和执行顺序。然后我们只去一步步的解决问题，不管机器的物理架构。当我们用高速平行的机器或者分布式系統的时候，只需要改动很小的一部分。
> 
> 
> 这就意味着编程语言的实现者必须在不同的机器和机制下，实现相关的功能。
> 
>

例子
--

### 互聯網協議堆疊

关注点分离是網路設計中的重點。在TCP/IP协议族的設計時，有許多心力用在关注点分离，因此有良好定義的OSI模型。這可以讓通訊協定的設計者專注在每一層的關注點，不考慮其他層的影響。例如應用層的協定，關注的是如何將郵件資料在可靠的傳送服務上傳輸的細節（一般會是传输控制协议），不會關注传输控制协议旳細節。TCP不會關注資料封包的路由，路由是由網路層處理的內容。

### HTML，CSS和JavaScript

HTML、层叠样式表（CSS）和JavaScript（JS）是開發網頁及相關服務時會用到的語言，彼此的機能是互補的。HTML主要是用在網站內容的結構、CSS是用在內容呈現方式的定義、JS定義網頁和用戶互動的方式，以及網頁的行為。以往的設計不是如此，在導入CSS之前，HTML同時要定義網頁的內容以及顯示方式。

### 主題導向的編程

主題導向的編程（英语：）可以用分開的軟體結構來處理關注點分離，每一個關注點之間都是平等的。每一個關注點會有自己的類別結構，這些類別結構組成物件、也會提供狀態和方法給複合各關注點的結果。相依性關係會描述這些不同關注點中類別和方法，彼此之間的關係，讓許多關注點可以聯合產生複合式的行為。多維度关注点分离（Multi-dimensional Separation of Concerns）可以用多維「矩陣」的方式來進行各關注點之間的分析及複合，每一個關注點提供一個維度，上面會列舉各個點，其中的矩陣元素會有適當的軟件工件（software artifacts）。

### 面向切面的程序设计

面向切面的程序设计可以將横切关注点視為主要关注点進行處理。例如，大部份旳軟體都需要某程度的安全性及数据记录。安全性及数据记录一般會視為次要關注點，主要關注點一般是實現業務目標。不過在設計程式時，其安全性需要在一開始就考慮進來，而不是視為次要關注點。若在程式開發後再考慮安全性，多半會有安全模型不足的問題，會有很多後續被攻擊的風險。這可以用面向切面的程序设计來解決。例如，有一個切面可以寫成強制呼叫特定API時一定要记录，或是在丟出例外時，一定要記錄錯誤，不論哪一段程式的程式碼丟出錯誤或是傳播錯誤，都不會遺漏。

### 人工智能中的分析水準

在认知科学及人工智能中，常常會用到大卫·马尔的levels of analysis。研究者可以專注在 (1)需要計算人工智慧的哪一個層面 (2)使用的演算法 (3)演算法在硬體中實現的情形。关注点分离類似軟體工程及硬體工程中的介面/實現的差異。

### 規範化系統

在規範化系統（normalized system）中，关注点分离是四個指導原則之一。堅持此一原則可以減少組合性的效應。組合性的效應會在維護軟體時，漸漸的進入系統中。在規範化系統中，可以用工具積極的支持关注点分离。

### 关注点分离和部份類別

关注点分离可以用部份類別（英语：）的方式實現

#### 关注点分离和Ruby中的部份類別

bear\_hunting.rb

```
class Bear
 def hunt
 forest.select(&:food?)
 end
end

```

bear\_eating.rb

```
class Bear
 def eat(food)
 raise "#{food} is not edible!" unless food.respond\_to? :nutrition\_value
 food.nutrition\_value
 end
end

```

bear\_hunger.rb

```
class Bear
 attr\_accessor :hunger
 def monitor\_hunger
 if hunger > 50
 food = hunt
 hunger -= eat(food)
 end
 end
end

```

相關條目
----

* 抽象原則 (程式設計)（英语：）
* 面向切面的程序设计
* 關注點（英语：）
* 主关注点
* 耦合性 (計算機科學)
* 横切关注点
* 整全觀
* 模組化設計
* 模块化编程
* 呈现与内容分离
* 单一功能原则
* 機制與策略分離（英语：）
* 保護和安全分離（英语：）

參考資料
----

1. ↑  Laplante, Phillip.. CRC Press. 2007  [2020-12-16]. ISBN 978-0849372285. （原始内容存档于2021-05-29）.
2. ↑  Mitchell, Dr. R. J.. IEE. 1990: 5  [2020-12-16]. ISBN 0863411711. （原始内容存档于2021-05-31）.
3. ↑ . Microsoft Press. 2009  [2020-12-16]. ISBN 978-0-7356-2710-9. （原始内容存档于2021-05-29）.
4. ↑  Painter, Robert Richard.. Penn State. CiteSeerX 10.1.1.110.9227 可免费查阅.
5. ↑  Dijkstra, Edsger W.. . New York, NY, USA: Springer-Verlag. 1982: 60–66. ISBN 0-387-90652-5.
6. ↑  Reade, Chris. 需要免费注册. Boston, MA, USA: Addison-Wesley Longman. 1989. ISBN 0-201-12915-9.  含有內容需登入查看的頁面 (link)
7. ↑  Jess Nielsen.  (PDF). June 2006  [2012-02-08]. （原始内容存档 (PDF)于2016-04-16）.
8. ↑  Tiago Dias.  (PDF). DSOA 2006. October 2006  [2007-09-25]. （原始内容存档 (PDF)于2016-10-03）.

外部連結
----

* Multi-Dimensional Separation of Concerns （页面存档备份，存于）
* TAOSAD （页面存档备份，存于）
* Tutorial and Workshop on Aspect-Oriented Programming and Separation of Concerns （页面存档备份，存于）