4.3 关注点分离
一个关注点是一个特征或行为,被指定为软件需求模型的一部分。通过将关注点分割为更小的关注点(由此产生更多可管理的块),使得解决一个问题需要付出更少的工作量和时间。
考虑两个问题:p1和p2,如果p1的认知复杂度高于p2,结果是:求解p1所需的工作量就会大于求解p2所需的工作量。一般情况下,这种结果是显而易见的,因为求解复杂问题确实需要更多的时间。
另一个结果是:两个问题被结合到一起的认知复杂度经常会高于每个问题各自的认知复杂度之和,这就引出了“分而治之”的策略——把一个复杂问题分解为若干可管理的块来求解时将会更容易。这对于软件模块化具有重要的意义。
关注点分离是软件设计和实现中的一个重要原则,它表明任何复杂问题如果被分解为可以独立解决和/或优化的若干块,该复杂问题就能够更容易地被处理。它意味着应该这样来组织软件,使得程序中的每个元素(类、方法和过程等)只做一件事。这样就能够集中注意力在一个元素上而无须考虑程序中的其他元素。可以通过了解其关注点来了解程序的每个部分,当需要进行某些改变时,变更只局限在少数的元素上。
分离关注点的重要性在计算机科学历史的早期阶段就被人们认识到了。20世纪50年代初期发明了子程序,随后的程序构造机制,例如对象类,也设计用来为实现分离关注点提供更好的机制。
虽然人们普遍赞同分离关注点是一个很好的软件工程实践,但清楚地界定关注点的真正内涵是很难的。有时,它被定义为一个功能概念(比如,关注点是系统中的某些功能要素)。同样,它也可以被定义得非常宽泛,如定义它是“程序中任意一块兴趣点或焦点片段”。这两个定义都不是很有用,因为关注点肯定不仅仅是简单的功能元素。
实际上,关注点是系统信息持有者对系统需求和优先权的真实反映。系统性能可以是一个关注点,因为使用者希望能够得到系统的及时响应;某些项目信息持有者关心的可能是系统应该包括某特殊功能;对系统提供技术支持的公司关注的可能是系统能够很容易地维护。因此,关注点可以定义为一个或一组项目信息持有者感兴趣的或者对他们意义重大的事情。
如果把关注点看做是组织需求的一种方式,可以看出将关注点分离实现在不同的程序元素中是一个很好的方法。当用关注点来表示一个需求或一组相关需求时,很容易在实现这些关注点的程序组件中跟踪需求。如果需求改变了,程序必须改变的部分是明显的。
下面是几种信息持有者关注点。
1)功能性关注点。它是包含在系统中的与特殊功能相关的关注点。例如,在火车控制系统中,一个特殊的功能性关注点是火车制动。
2)服务质量关注点。它是与系统的非功能性行为相关的关注点。这些包括性能、可靠性和可用性等特征。
3)政策关注点。这是与管理系统使用的总的政策相关的关注点,包括信息安全关注点,以及与业务规则相关的关注点。
4)系统关注点。这是与系统总体属性相关的关注点,例如它的可维护性和可配置能力。
5)机构关注点。这是与机构的目标和优先级相关的关注点,例如在预算范围内完成系统构建,对现存的软件资产的利用,或者是维持机构声誉。
系统的核心关注点是那些关系到它的主要目标的功能性关注点。因此,对于一个医院病人信息系统来说,核心功能性关注点是创建、编辑、检索和管理病人的记录。除了这些核心关注点外,大型系统还有第二类的功能性关注点。这些包括与核心关注点共享信息的功能,满足其非功能性需求所需要的功能等。
例如,考虑这样的一个系统,它的一个需求是提供对共享缓存的并发访问。一个进程向缓存中输入数据,另一个进程从同一个缓存读取数据。此共享缓存是数据获取系统的一部分,生产者进程将数据放入共享缓存,消费者进程从中将数据取走。在这里,核心关注点是维护一个共享缓存,所以核心功能是向缓存添加和从缓存删除元素。但是,要确保生产者进程和消费者进程互不干扰,必须有一个第二类的同步关注点。系统设计需要保证生产者进程在数据还没有消费之前不能重写它,消费者进程不能从空缓存中提取数据。
除了第二类关注点之外,其他的关注点如服务质量关注点和机构政策关注点反映的是基本的系统需求。一般来讲,这些关注点是系统关注点——它们作用于整个系统而不是单个需求或对这些需求的程序实现。为了区别于核心关注点,就称其为横切关注点(cross-cutting concern)。第二类功能性关注点也可能是横切关注点,虽然它们不总是横贯整个系统;更确切地说,它们关联于能提供若干相关功能的一组核心关注点。
横切关注点如图4-2所示,此图基于一个网上银行系统,该系统有一些针对新客户的需求,如信用审查和地址检验,它也有关于已存在客户的管理和客户账户的管理等方面的需求。所有这些都是核心关注点,因为它们都和系统的主要目标相关(提供网上银行服务)。但是,此系统也有根据银行信息安全政策的信息安全需求,以及能够确保在系统失败时数据不至于丢失的恢复需求。这些是横切关注点,因为它们会影响系统所有其他需求的实现。
横切关注点使用例(如对象或函数)等构造机制不能被局部化。为了确保对关注点的分离,系统可以设计成核心和扩展两部分,核心系统实现主要关注点,而扩展系统用来实现第二类关注点。
关注点分离在其他相关设计概念中也有体现,如模块化、方面、功能独立和求精等。
图4-2 横切关注点