关注点分离

在计算机科学中，关注点分离（Separation of concerns，SoC），是将计算机程序分隔为不同部份的设计原则。每一部份会有各自的关注焦点。关注焦点是影响计算机程式程式码的一组资讯。关注焦点可以像是将程式码优化过的硬件细节一般，或者像实例化类别的名称一样具体。展现关注点分离设计的程序被称为模组化程序。模组化程度，也就是区分关注焦点，通过将资讯封装在具有明确界面的程序代码段落中。封装是一种资讯隐藏手段。资讯系统中的分层设计是关注点分离的另一个实施例（例如，表示层，业务逻辑层，数据访问层，持久数据层）。
关注点分离，是对只与「特定概念、目标」（关注点）相关联的软件组成部分进行「标识、封装和操纵」的能力，即标识、封装和操纵关注点的能力。是处理复杂性的一个原则。由于关注点混杂在一起会导致复杂性大大增加，所以能够把不同的关注点分离开来，分别处理就是处理复杂性的一个原则，一种方法。分离关注点使得解决特定领域问题的程式码从业务逻辑中独立出来，业务逻辑的程式码中不再含有针对特定领域问题程式码的调用（将针对特定领域问题程式码抽象化成较少的程式码，例如将程式码封装成function或是class），业务逻辑同特定领域问题的关系通过侧面来封装、维护，这样原本分散在整个应用程序中的变动就可以很好的管理起来。
关注点分离的价值在于简化计算机程序的开发和维护。当关注点分开时，各部份可以重复使用，以及独立开发和更新。具有特殊价值的是能够稍后改进或修改一段代码，而无需知道其他部分的细节必须对这些部分进行相应的更改。

**实作**
编程语言提供的物件导向设计或模块化编程机制，就是允许开发人员提供SoC的机制。例如，C#，C++，Delphi和 Java等物件导向的编程语言可以将关注点分解为物件，像MVC或MVP这样的架构设计模式，将内容从呈现和数据处理（模型）与内容分开（呈现与内容分离）。Service-orientation的设计可将关注点分解为服务。诸如C和Pascal之类的程序式编程语言可将关注点分成过程或函数。面向切面编程语言可以将关注点分解为方面和对象。
在许多其他领域，例如城市规划、建筑或信息设计，分离关注点也是一个重要的设计原则。目标是更有效地理解，设计和管理许多功能相互依存的复杂系统，以便功能可以重用，独立于其他功能进行优化，并且避免其他功能的潜在故障。常见的例子包括将一个空间分隔成多个房间，这样一个房间的活动不会影响其他房间的人；或是配电将炉子保持在一个电路，而灯光则保持在另一个电路上，这样炉子的超载就不会影响灯光。房间分隔的例子显示了封装，其中一个房间内的资讯（无论有多混乱）不会用于其他房间，除非通过界面（门是接口）。电路的例子表明，一个模组内部的活动是一个电力消费者附加的电路，不会影响不同模块中的活动，因此每个模组不会额外去关注另一个模块发生的情况。

**起源**
这个概念是1974年，艾兹赫尔·戴克斯特拉在他的文章《On the role of scientific thought》中提出的。
15年之后，这个概念已经被人们所接受。1989年，Chris Reade写的《Elements of Functional Programming》有这样的描述：
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）中，关注点分离是四个指导原则之一。坚持此一原则可以减少组合性的效应。组合性的效应会在维护软体时，渐渐的进入系统中。在规范化系统中，可以用工具积极的支持关注点分离。

**关注点分离和部份类别**
关注点分离可以用partial class的方式实现

**关注点分离和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

**相关条目**
 Abstraction principle (programming)- 面向切面的程序设计- 关注点- 主关注点- 耦合性 (计算机科学)- 横切关注点- 整全观- 模组化设计- 模块化编程- 呈现与内容分离- 单一功能原则- Separation of mechanism and policy- Separation of protection and security

**参考资料**

**外部连结**
  Multi-Dimensional Separation of Concerns date=20160809005116 -  TAOSAD date=20161219013600 -  Tutorial and Workshop on Aspect-Oriented Programming and Separation of Concerns date=20080516050058