关注点分离
在计算机科学中,关注点分离(Separation of concerns,SoC),是将计算机程序分隔为不同部分的设计原则。每一部分会有各自的关注焦点。关注焦点是影响计算机程式程式码的一组资讯。关注焦点可以像是将程式码优化过的硬件细节一般,或者像实例化类别的名称一样具体。展现关注点分离设计的程序被称为模组化程序[1]。模组化程度,也就是区分关注焦点,通过将资讯封装在具有明确界面的程序代码段落中。封装是一种资讯隐藏手段[2]。资讯系统中的分层设计是关注点分离的另一个实施例(例如,表示层,业务逻辑层,数据访问层,持久数据层)[3]。
关注点分离,是对只与“特定概念、目标”(关注点)相关联的软件组成部分进行“标识、封装和操纵”的能力,即标识、封装和操纵关注点的能力。是处理复杂性的一个原则。由于关注点混杂在一起会导致复杂性大大增加,所以能够把不同的关注点分离开来,分别处理就是处理复杂性的一个原则,一种方法。分离关注点使得解决特定领域问题的程式码从业务逻辑中独立出来,业务逻辑的程式码中不再含有针对特定领域问题程式码的调用(将针对特定领域问题程式码抽象化成较少的程式码,例如将程式码封装成function或是class),业务逻辑同特定领域问题的关系通过侧面来封装、维护,这样原本分散在整个应用程序中的变动就可以很好的管理起来。
关注点分离的价值在于简化计算机程序的开发和维护。当关注点分开时,各部分可以重复使用,以及独立开发和更新。具有特殊价值的是能够稍后改进或修改一段代码,而无需知道其他部分的细节必须对这些部分进行相应的更改。
实作
[编辑]编程语言提供的面向对象设计或模块化编程机制,就是允许开发人员提供SoC的机制[4]。例如,C#,C++,Delphi和 Java等面向对象的编程语言可以将关注点分解为物件,像MVC或MVP这样的架构设计模式,将内容从呈现和数据处理(模型)与内容分开(呈现与内容分离)。服务导向的设计可将关注点分解为服务。诸如C和Pascal之类的程序式编程语言可将关注点分成过程或函数。面向切面编程语言可以将关注点分解为方面和对象。
在许多其他领域,例如城市规划、建筑或信息设计,分离关注点也是一个重要的设计原则。目标是更有效地理解,设计和管理许多功能相互依存的复杂系统,以便功能可以重用,独立于其他功能进行优化,并且避免其他功能的潜在故障。常见的例子包括将一个空间分隔成多个房间,这样一个房间的活动不会影响其他房间的人;或是配电将炉子保持在一个电路,而灯光则保持在另一个电路上,这样炉子的超载就不会影响灯光。房间分隔的例子显示了封装,其中一个房间内的资讯(无论有多混乱)不会用于其他房间,除非通过界面(门是接口)。电路的例子表明,一个模组内部的活动是一个电力消费者附加的电路,不会影响不同模块中的活动,因此每个模组不会额外去关注另一个模块发生的情况。
起源
[编辑]这个概念是1974年,艾兹赫尔·戴克斯特拉在他的文章《On the role of scientific thought》中提出的[5]。
让我告诉你,对我来说所有聪明的思考的共通特性是什么。一个人要有系统地深入研究一门课题;必须将这们课题独立出来,记住在任何时候都只能关注其中一个方面。 比如说,我们知道一个程式必须是正确的,因此我们可以只抓这个点来研究;我们同时也清楚它应当是高效率的,我们可以改天来研究它的效率,等等。我们也可以问自己,程式是否是可取的(desirable)?如果是,为什么?相反的,同时应对好几个个方面不会得到任何结果!这就是我有时提到的“the separation of concerns(关注点分离)”。这个技巧就算不是完美可行的,也仍是我知道有效地组织思维的唯一可用技巧。这是就是我说的“将一个人的注意力集中在几个方面上”。这并不是说忽略其他方面,只是表明从这个方面来看,其他方面并无关紧要这一事实。这即是同时拥有单任务和多任务思维。
15年之后,这个概念已经被人们所接受。1989年,Chris Reade写的《Elements of Functional Programming》有这样的描述[6]:
一个程式在执行的时候一定会同时做以下几件事情:
- 描述所要解决的问题
- 按照计算的顺序分成几个部分执行
- 同时处理内存管理
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时一定要记录,或是在丢出例外时,一定要记录错误,不论哪一段程式的程式码丢出错误或是传播错误,都不会遗漏[7]。
人工智能中的分析水准
[编辑]在认知科学及人工智能中,常常会用到大卫·马尔的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
相关条目
[编辑]参考资料
[编辑]- ^ Laplante, Phillip. What Every Engineer Should Know About Software Engineering. CRC Press. 2007 [2020-12-16]. ISBN 978-0849372285. (原始内容存档于2021-05-29).
- ^ Mitchell, Dr. R. J. Managing Complexity in Software Engineering. IEE. 1990: 5 [2020-12-16]. ISBN 0863411711. (原始内容存档于2021-05-31).
- ^ Microsoft Application Architecture Guide. Microsoft Press. 2009 [2020-12-16]. ISBN 978-0-7356-2710-9. (原始内容存档于2021-05-29).
- ^ Painter, Robert Richard. Software Plans: Multi-Dimensional Fine-Grained Separation of Concerns. Penn State. CiteSeerX 10.1.1.110.9227 .
- ^ Dijkstra, Edsger W. On the role of scientific thought. Selected writings on Computing: A Personal Perspective. New York, NY, USA: Springer-Verlag. 1982: 60–66. ISBN 0-387-90652-5.
- ^ Reade, Chris. Elements of Functional Programming. Boston, MA, USA: Addison-Wesley Longman. 1989. ISBN 0-201-12915-9.
- ^ Jess Nielsen. Building Secure Applications (PDF). June 2006 [2012-02-08]. (原始内容存档 (PDF)于2016-04-16).
- ^ Tiago Dias. Hyper/Net: MDSoC Support for .NET (PDF). DSOA 2006. October 2006 [2007-09-25]. (原始内容存档 (PDF)于2016-10-03).