我自己的一生

是你的,是我的,到底是谁的?

导航

关注分离艺术(译文)

Posted on 2009-03-01 10:34  Abbott zhao  阅读(1016)  评论(1编辑  收藏  举报
 

关注分离艺术

 

 

作者:不详

译者:赵向阳(Abbott Zhao)

2009/2/21

 

译者按:

      作为一名软件架构师,我经常需要训练自己的抽象思维能力。需要忽略不关键的细节,从全局考虑问题。当一个事物摆在我面前时,我需要对它进行分析,抓住关键点,搞清楚边界关系;需要从不同的方面进行考虑—数据、行为、环境及其它潜在的隐藏点。我把软件架构的设计和构建当成一门艺术来享受,用哲学的思维来考虑。那么,我们在理论上和艺术上需要有什么那些方面的内容训练我们的这些能力呢?

 

   我思考了很久,自己也有了不少的总结,而且我总想把它写出来。就在某一天,我在网上发现了这篇文章,可惜的是没有找到它的优秀的作者是谁。我所有的哲学性的思考,它已经为我表达了。看过之后,我更清晰了我一直以来盘旋在脑中的答案。

 

   我遇到好东西,总想找出一个方法与你共同分享。我所能作的就是把他翻译出来,放在我的博客上,供大家浏览。如果我的这种行为违反了本文的原始作者或他的委托人的意图,请您发邮件(xyxxgl@gmail.com)给我。我会按照你合理的要求处理他。如果您需要引用,除了不用于商业意图之外,也要注意作者(或他的委托人)所要表达的要求。

 

 

介绍

        在软件工程领域,关注分离指的是达到对逻辑边界构建的定义和描述目的。它可以通过定制、优雅的形态和系统设计功能来提升管理和维护系统的能力。

 

本篇文章的目标是提升对关注分离的理解,建立一批基本概念,有益于开发者和架构师应有到他们的应用程序中。

 

关注分离定义

关注分离是原则和过程。关注分离的原则是作为前论的陈述,相对于他们要存在的事情,这个前论是恰如其分。那就是说,事情要包含本质属性和他们天然的内在行为,但,空置的属性和行为不是它们天然的内在本性。关注分离的过程由包含边界的内部相关性技术和结构组成。边界经常通过使用定义的应用程序的核心行为的方法,对象,组件和服务建立;源代码组织的项目,解决方案和文件夹层次;处理组织的应用程序逻辑层和物理层;产品发布组织的版本化类库和安装程序。



 

分离的价值

应用关注分离会增强稳定性,维护性,扩展性,可用性;甚至会采用,合乎逻辑,审美的系统设计和流。在彼此的成果中,这些优势也扮演了一个支撑的角色。例如,促进系统里的组件可用性策略,如保证单一意图和去耦,这和系统可维护性是相互关联的。由于处理失败经常是脆弱,过度复杂和难以设计的,所以,系统的可维护性常常和他的稳定性直接相关。一个系统的合理和审美性的设计和流动,与系统的可维护性及通过理解提升与和谐处理的采用是相关联。系统的可维护性和审美性设计与它的扩展性的简易化和易理解相关联,扩展性同它贡献给后边的系统的可维护性和稳定性是可互换的。尽管这些优势不是所有的都作为每个努力的特定目标,但,每个都证明了可维护性是整体目标成功的手段。

 

应用在开发组织时,良好的关注分离构思会导致更敏捷的开发结果,最小化团队之间的条件,最大化每个团队的潜在能力来传递他们与聚集能力相关的重要作用。很明显,这是群体为通常关系负责的现实,如整体基础结构,服务部署,集中的用户界面,必须归因于他们增强了所涉及到指定的潜在领域。

 

关注分离原则几乎可以扩展到软件开发的每个方面。它是好的架构和系统管理的基础原则。

 

分离术语

讨论与关注分离有关的关键概念和定义的理解。下面是关注分离主题相关的一些术语列表。

 

     关注 --- 一个固有的或者有影响的特征。关注是被一个事情定义的属性和行为。

 

     边界 --- 围绕一个或多个相关关注的物理或者概念的描述。一个边界可能是一个容易感知到一批构造在应用程序范围的关注轮廓。就像是这样的情况:带有方法,或者组件类库,或者仅是组织上的一个协定,如,可达到的基于范围的成员组。边界使用的动机包括基于他们基础的本质论的实体定义,帮助排除冗余,描绘角色和关系,使用相关的关系相互关联,便利改进和重用。

 

     抽象 --- 一个在非关注术语中的表达。像哲学学习一样,计算机科学领域的抽象过程允许处理思想和实体不需要被不必要的细节所障碍。抽象一般是通过任一个特定结构的语言的使用完成,如,抽象类和接口,或者仅暴露功能性概念层的必需的一批更基础组件。抽象的目标一般允许关系的一边或者两边彼此多种形式的独立。例如,如果一个表现层通过抽象的领域层服务访问数据库,访问数据库和方法的改变不会影响表现层。

     解耦 --- 断开一个结合,或者已知的两个组件或者系统的处理。

 

     松耦合 — 处理一个关联的状态,或者通过抽象的含义处理从一个到另一个已知组件或者系统的状态。松耦合提供一种能力,一个和另一个组件的关联允许他们独立变化。例如,如果组件A和组件B,通过组件B的抽象交换,组件B的实现的改变不会影响组件A。

 

     紧耦合 --- 处理一个直接关联的状态,或者处理一个组件或系统与另一个组件或系统之间已知状态,关联组件或系统独立发生变化时会互相影响。

 

     单边解耦 — 两个组件或系统之间关联断开处理,仅允许一个对另一个独立变化。单边解耦的一个例子是使用“观察者模式”,该模式可以激发事件通知外部观察者,一旦通知被接受,外部观察者调用领域模型的方法。这个场景下,当观察者被耦合到领域模型中时,领域模型从接受消息的观察者中解耦出来。

 

     双边解耦 — 处理两个组件和系统的断开关联,允许二者独立变化。双边松耦合的一个例子是,彼此交互的两个组件通过每个组件的接口。完整的双边解耦的一个例子是,在交换消息的两个或多个组件之间,使用经纪人机制维护它们的关系。组件用基础结构层面组件被耦合起来情况下,允许它们维持和另一个领域层面的解耦。

 

     单块集成 — 缺乏条理或任何组件分离的特性。单块集成应用程序经常导致巨大的,笨重的,刚硬的系统,包含它的功能性不容易与整体应用程序使用的外部其它应用程序的共享。

     模块化 — 拥有条理性的组件隔离特性。模块化应用程序由多个组件或子系统组成,它们一起工作完成全部的系统目标。

     附加件(或插件)--为系统动态使用新能力的组件或者配置模块而设计。附加件为系统提供了能力--委托使用松耦合构成的关注

 

     供应者— 满足一批特定抽象功能契约的组件。供应者是完成应用程序内一批特定关注的专门附加件。

 

     扩展 – 用来增强已存在系统的能力的组件,被设计用来产生控制,或者暴露内部处理的预定点上的数据和功能。一个扩展允许关注的委托不直接来自内部,或者核心系统处理的应用。扩展经常占有一个托管附加件的构成,而且包括任何特定增加到已存在系统新能力的设计处理。

 

     层次化 – 在一个系统中处理目标实体分组之间具有清晰隔离的一般特性。层次化隔离的例子是,应用程序的视图表现的关注和数据访问的关注之间的分割。

 

     反转控制将关系转移到已确定边界之外的过程。反转控制具体化原来包含在一个组件里面的关注,可以用于这样的任务,最小化不重要的关注,或者从直接参与指定抽象策略中解耦出组件。反转控制的一个最常用的实例是使一个组件的主控制流具体化。

 

     依赖注入--从实体中获取依赖关系的隔离过程, 控制反转在获取外部的依赖的过程时,依赖注入是控制反转的特殊情形。依赖注入的一个例子是,系统为系统内的每个实例组件初始化一个对登录服务的引用。这个允许系统应付所有指派给的多样化实现,或者系统内不需要改变正在使用组件的组件子集。

 

     依赖方向 – 一个组件或系统同另外一个之间的路由。依赖方向遵守从一个正在使用组件或者已经应用依赖的系统中拉出的路径。例如,如果组件A调用一个组件B的方法,那么,依赖方向是从A到B。

 

     分解 – 改变一个系统的过程,这个系统外部接口和功能保持不变,但内部组织和处理更有效和更可维护。

 

水平分离

关注水平分离指的是划分一个应用程序到履行应用程序里面相同角色功能的逻辑层中。

 

绘制用户界面应用程序的一般的划分是划分成为表现,业务和资源访问层的过程隔离。这些种类涵盖了大部分应用程序需要关注的主要类型,表现了减少一个应用程序内最小依赖层面的关注的组织。图1描述了一个通常的三层应用程序:

 

Figure 1

 

表现层涵盖了与应用程序用户界面相关的处理和组件。这包括应用程序的可视化显示的定义,包括先进的设计概念,如控制器,展现器,表现模型。表现层的主要目标是封装所有用户界面的关注,目的允许应用程序域是独立变化的。表现层也包括和应用程序可视化显示有关的执行的所有组件和处理,排除所有其它组件和处理。这允许应用程序内的其它层独立于它的显示关注而独立变化。

 

业务层涵盖与应用程序相关的处理和组件。这包括定义对象模型,支配业务逻辑和控制系统的工作流。业务层通过专门的组件表现,这些组件表现工作流,业务过程和应用程序内使用的实体,或者传统的封装数据和行为的面向对象领域模型。业务层主要的目标是封装应用程序的核心业务关注,排除如何暴露数据和行为,或者如何获取数据。业务层要独占性地包括所有和应用程序业务域有关的组件和处理,要排除其它组件和处理。

 

资源访问层涵盖了对外部信息访问相关的组件和过程。这包括本地数据存储或者远程服务接口的组件。围绕明显数据源的指定,资源访问层的目标是提高抽象层。这包括一些任务,如数据的建立,服务的链接,维护有关数据库架构或存储过程的技能和服务协议的技能,在服务实体和业务实体之间数据的封送。资源访问层独占性地包括和系统外部访问数据有关的所有组件和处理,排除其它组件和处理。

 

 

Figure 2


在这个划分中,业务和资源访问层和与前面讨论的目标相同,服务暴露的关注封装进一个服务接口层里。这个层涵盖的服务接口关注,如通过多样协议,服务指定契约的管理和数据类型暴露的业务过程。服务接口层的主要目标是,封装所有服务接口关注,目的允许应用程序域独立变化。服务接口层将独占性包括所有的与应用程序作为服务的暴露,排除其它组件和过程。

 

基于它们在应用程序中的角色,分组处理关注,获取了改进整体系统可管理性的大量好处。这些好处包括,通过组合架构和过程独立使维护减轻,增强了改变冲突的防疫,增强了对变化的适应性,增强了潜在的可重用性。

 

垂直分离

---

关注的垂直分离指的是,划分应用程序成模块,这些模块的功能是相同特征或者应用程序里面的子系统所关联起来的过程。

分离应用程序特征到模块,需搞明白职责和每个特征在帮助测试和整体维护中的可能的彼此依赖。被定义的边界,逻辑上帮助组织,或者物理上赋予开发和维护的独立性。

 

逻辑边界暗指模块化的存在,虽然,在实际部署或应用程序运行时行为方面,使用于表示分离的方法可能没有关系。这个为改善应用程序的可维护性是有益,减轻对于物理分离特征的任何未来的影响。图4描述了包含逻辑边界的应用程序:

 

Figure 4

 

物理边界一般应用在开发插入或组合应用程序的环境中,使特征能够被完全不同的开发团队管理。支持插件模块化的应用程序经常使用如自动发觉,或者初始化基于外部配置源的模块。图5描述了宿主框架,包含被分离开发团队的开发模块:

 

 

Figure 5



    基于应用程序里全部明确特征的执行,当垂直分离集合一批基于它们相关性的关注时,这不排除其它关注分离策略的使用。例如,每个模块自身可能用分层描述模块里面的组件角色来设计。图6使用横和垂直两个关注分离策略描述一个应用程序:

 

Figure 6

 

方面分离

关注方面分离,更清楚的是面向方面编程,指的是从它的核心关注里分离出应用程序的横切关注点的过程。横切关注点,或方面,是散布在应用程序里面多个边界的关注点。日志是一个例子,它执行在横穿多个系统组件的活动。

 

图7描述了数个横切关注点的一个应用程序:

Figure 7

由于横切关注点广泛地放置在应用程序的多个地方,它的维护是困难的。它们把核心关注点进行混合也增加了复杂性,致使应用程序的维护更困难。通过隔离这些关注点,核心关注点和横切面关注点二者更容易管理。

    方面分离与其它分离技术不同,它依赖每个处理,编译时,或与应用程序横切面关注点的运行时的融合。粘合两个关注点在一起的过程被当作“编织(weaving)”看待。通过使用多种策略,横切面关注点可能被分离,且由于运行时的凝集而编织回到应用程序。

    图8描述了一个概念的编织过程--分离地,与核心关注点结合起来的可维护的横切关注点。

 

Figure 8

 

方面分离工具适用于很广泛的编程语言。这个主题更多信息,包括方便方面分离工具,见面向方面编程的Wikipedia Web页面。

依赖方向

    一个好的关注分离的特征是依赖方向创意的建立。一个创意的依赖方向建立了使用者和依赖的角色,以便依赖角色被具有最高潜在可重用的实体所支配。

   说明依赖方向概念的一个简单例子是,在业务组件和工具组件之间的公共关系。考虑一个提供在查询处理中提供订单的系统,经常性需要被有效地缓存在周围的请求数据。为了使订单查询缓存便利,开发一个缓存工具组件,隔离从订单查询处理的其它地方的缓存关注点。

图9描述了带有两个组件的这样的系统:

                                                                 

Figure 9

 

因为缓存功能相对于订单查询处理是一个更一般化的行为,所以,缓存组件在两者之间更具有潜在的可重用性。因此,在这个例子中,最好的依赖方向是从业务组件到工具组件。这个依赖在图10中描述:

Figure 10

 

这样的关系,允许缓存组件维持查询处理组件的不可知,使它能够在未来的处理中被重用。

    与此对比,如果缓存组件被设计为特别依赖被缓存数据的类型,或者业务组件的一些其它方面,那么,缓存组件在未来的处理中不进行修改,就不具有可重用的能力。图11描述了这样的关系:

Figure 11

 

当扩展这种关系到其它组件是可能的时候,这种方法最终会导致一个缓存组件过度复杂和不实用。

    证明依赖方向概念的另外一个例子是,应用程序层之间的关系。图12描述的应用程序,把表现,业务处理和资源访问隔离到分离层中:


Figure 12

 

正如在水平分离章节中讨论的那样,这些层是分离的公共模式,因为它们表现了应用程序里面的最小依赖层次的关注的组织。通过在没拥有相互关系的各个层上仅建立每个层的依赖,直接或间接的,每个层可以被独立地从直接和间接地正在使用的层来改变。图13描述了这种被规定的关系:

Figure 13

 

这改进了应用程序的能力,适合变化和使层在不同环境中能够被重用(如,相同业务处理的多种表现)。
  

与此对比,这种规定的违反导致层适应变化的较弱的绝缘,层较弱的被重用能力。图14描述了访问业务层的资源访问层。

Figure 14

这个依赖的建立认为是违反关注分离原则。这是因为资源访问层,被定义的,本质上不能关注业务处理。组合成资源访问的边界仅应该获取资源,如从数据库或Web服务获取数据。这个违例导致,当依赖的业务层部分发生变化时,资源访问层也将需要发生改变,阻碍了资源访问层被其它不依赖于这个应用程序业务层的应用程序重用。

   在应用程序层里面和直接依赖有关的最好实践的另一个建议是,层的规定限制依赖,在依赖方向链中,层仅直接依赖它下面的。那就是说,各层理论上永远不应该迂回邻近的层。这个限制集中了对每个层的访问,隔离其它层的变化冲突,允许应用在层访问上的一致处理。这样的情况限制了表现层直接访问资源访问层。这样的现在保证对资源访问层的变化不应该影响业务层。另外,允许一致性的处理被应用在数据访问上,如缓存,失败切换,审核,错误检查等等,变化隔离到这些处理。

数据关注

    应用到数据的关注分离原则包括被一个系统管理的适合的模型信息。当数据建模方面同时应用到面向对象和数据库设计时,这个论述关注面向对象数据关注,这个数据关注是经常跟随功能的数据库最基本的需求所构成后的数据。

   当组织对象模型里面的数据时,暴露的信息应该被表现为内部的实体。例如,给定一个销售产品给消费者的系统,定义产品的一个对象应该不包含消费者相关信息。这是因为产品与谁购买产品没有内在联系。更好的方法应该有消费者和产品信息组成概念订单的创建。这个会使产品对象在未来可能不需要与消费者信息关联的其它过程所重用。

   另外考虑在不同环境中的数据模型的潜在重用性,直觉的数据组织也在维护搞复杂性系统时很有用的。例如,如果一个新开发者被分配任务,通过访问被已存在内存中的一个产品对象组合指定部分的序列号,开发者很可能首先尝试定位指定的产品部分和检查一个“序列号”这部分,或者相似命名属性。开发者或许不考虑查找一些如“产品号--序列号”字典定位到产品对象,因此这不是一个很正常数据表现方法。这很类似于,把戴着的支配序列号的手表的好坏看待一个人一样。

    然而,有多次,数据的正常组织没有为信息的查询呈出有效的机制。例如,一个异常复杂的产品对象,需要经常作获取所有铜元素的全部数量的检查,不可能通过检查或它组合元素彼此交叉引用而有效地处理。这种情况,正常的建模是不充分的,一个完整的对象模型可以用补充元素概念来维护,满足特定的需求。例如,如果产品的组合一旦保持为静态组装,概念模型表现了产品的贵金属信息(如,“产品贵金属清单”),可能被组合在同一层次的产品信息中。如果产品的组合经常发生改变,且组合处理被集中在贵金属信息处,作为这个处理的一部分被刷新。另外,一个专门的组件可能被考虑(如,“贵金属推测器”),动态地返回产品贵金属信息。正如第一个例子,来自其它正常模型分离概念的好处是,其它过程可以在没有过渡的非内部特征情况下重用模型,模型很容易维护。

行为关注

     分离行为包括系统过程的逻辑分区,可管理性和代码单元的可重用性。这表现了大部分关注分离的功能类型。在面向对象系统中,当过程行为用对象、组件、应用程序和服务进行分离时,精细的行为用方法来分离。

    正如数据的分离,封装的行为应该内含边界。举个例子,名叫CreateCustomer()的方法仅期望包含与新客户的创建有关的行为。不应该期望,如,为新客户放置订单。类似,名叫ProductAssembler的组件应该期望包含说产品装配有关的数据和行为。类似,不应该期望包含同客户有关的数据或行为。

    完成一个好的行为分离通常是个重复的过程。系统首要的行为通常在设计阶段构思,但系统设计指定的实现经常需要数个分解迭代,使精细关注变得更加明显。

当组织行为时,以下目标应该努力追求:

消除冗余功能。

约束可维护规模的范围。

约束包含边界描述的范围。

约束包含边界内在行为的范围。

最小化外部依赖。

最大化潜在的重用性。

 

扩展关注

扩展是个战略性关注分离,能够增加新的行为到已存在的一批关注中。扩展用于增强没有增加到目标系统的期望的已存在关注,不是系统的内存行为,或在是包含在作为系统核心特征量的一部分的另外理论上的行为。图15描述了一个目标系统扩展的依赖关系:

 

Figure 15


    扩展与目标系统相互作用在反应关键事件的通知中。被扩展提供的行为范例应该包括新视图或者控制,正常过程的变更,或目标系统里的数据变更。扩展通常由托管插件所构成,通常通过配置或动态发觉处理来注册。

    当企业内部有多个客户端应用程序被维护时,可能会发现被一个客户端扩展的行为,增加到另一个客户端也是很有价值。如果扩展对于目标应用程序是高自定义的,且提供的行为是相似的,行为最好的方法会被复制功能到新应用程序里。然而,如果扩展的行为在规模和复杂性方面是真实的,那么,通常更合适的方法是通过企业服务提供行为。如果被服务提供的行为仍然不合适于包括作为宿主系统的核心依赖,那么,新扩展可能要被开发,作为应用程序一边的,与服务进行交互。

委托关注

>     委托关注指的是,分配履行从属组件行为职责的过程。这个策略分离来自执行的职责关注,且对于依赖外部条件的多样性的细节实现的组件设计是有益的。使用这个策略,组件代理了一些或全部数据请求和方法,这些请求和方法是设计在一个专门的方法中另一个组件履行请求的乞求。例如,一个组件被设计返回当前用户分配的角色列表,可以委托请求给一个或多个从属组件,从属组件设计获取角色从本地的XML文件,数据库,和/或一个远程服务。图16举例说明了,专门为不同数据源设计的组件授权关注的委托:

Figure 16

委托容易使用一些模式实现,策略模式、插件模式、微软提供者模型(Microsoft Provider Model),能够使组件行为的一部分被外部执行的不同模式。

反转关注

     反转关注,更出名的是控制反转,指的是转移一个关注在已建立边界的外部的过程。关注反转的一些使用,包括实现的方面分离,最小化非本质处理,从特定的抽象策略中松耦合组件,或重新定位基础结构组件的职责。一些特定的应用程序包括减弱与硬件关注、工作流管理、注册过程、或获取的依赖的附属。

     图17描述了一个关注反转过程,表现组件和领域组件二者具有转移到基础结构层组件的关注。

 

 

理解关注反转的一个范例是模板方法模式(Template Method)的使用。这个模式用于泛化过程的行为,为了允许通过继承的多态。当应用这个模式到一个已存在的组件,期望过程执行的步骤会被泛化,封装在基类中。存在组件然后会从新基类继承,这个基类仅维持特定的行为。其它类型然后会自由地从基类继承,提供多种实现。这是个算法序列反转关注的例子。

    反转关注的另外一个例子要观察在反转一个交互的控制台应用程序到一个GUI应用程序。一个通常的交互控制台应用程序提供一个主循环,DOS命令方式给用户信息,等待输入的数据。当转换到一个GUI应用程序,程序的主控制一般被基础结构组件、使用观察者模式(Observer Pattern)完成用户交互提供。这个转换交互处理的主控制,要依赖于应用程序的基础结构,或这些关注的宿主环境。

    依赖注入(Dependency Injection)是一个应用到有关获取外部依赖关注反转的术语。这个术语的构思,更清晰地反映了与反转构成有关的框架类行为。依赖注入的目标是,分离了如何从边界的核心关注获取依赖的关注。通过使组件能够应用于不同依赖环境的依赖,从而改进了可重用性。

    依赖注入的过程通常包括容器角色,依赖性和接受器。

容器的角色被组件分配给接受组件的依赖性的职责所支配。容器通常使用工厂模式(Factory Pattern)实现,这个模式能够创建接受和依赖组件。

    依赖角色被提供个接受者的资源所支配。容器经常实现能够让存在对象作为一个依赖注册,或者需要时创建新的实例。

    接受者角色被从容器中接受依赖的组件所支配。要求接受者使用容器支持的策略声明依赖。决定依赖信息的策略通常采用反射的用法来检查一个或多个接受者成员类型,可以使用“属性/标识”(attributes/annotations)暗识或明确指定的依赖。一个序列图在图18中展现了这些角色。

 


Figure 18




    一个依赖注入用法的例子是,使用工厂(Factory)或工厂方法(Factory Method)模式的场所,从业务组件中抽象出缓存功能。通过使用依赖注入应用在一个带有缓存组件的接受者,接受者维护了与缓存组件的松耦合,不需要增加与特定工厂的耦合。

   依赖注入用法的另外一个例子,控制被单例模式(Singleton Pattern)的地方创建的缓存组件的数量。这个能够使应用程序保证在应用程序的整个周期内仅单一的实例在使用,或者控制接受者接受到哪个组件实例。通过模仿应用的依赖,这也增加了在它们依赖隔离中的组件的测试能力,而不是请求单例同它们的使用者一起测试。

   使用模式(工厂、工厂方法、抽象工厂、单例、插件、服务定位)的组件抽象出对象创建关注,或依赖取回,是好的考虑补充或替代依赖注入的候选对象。在某些地方,或与这些和其它这们的模式协作,通过使用依赖注入,使用的组件从特定抽象策略中完全抽出来。


夸大的练习

    消极的设计推理是经常发生的现象,特别是与可度量性和重用性有关的,一个系统已经建立之后很长时间这个情况都没有明朗。可度量性和重用性的问题通常根深蒂固的缺乏对关注分离的原则。可以帮助优化关注的一个过程是,考虑在应用在夸大环境下的设计方面。通过这个练习,系统的使用假定是超越已知系统期望之上,是为了显示出设计方法上的潜在弱点。例如,当设计一个被两个存在系统使用的对象模式,一个考虑被五十个系统共享的对象模式的推理结果是什么,通过夸大的设计使用,贫乏组织的职责会经常变得很容易识别。

   举这个练习的例子,考虑下面的例子,关注一个新合成客户关系管理系统的创建:

   在一个公司内部,IT部门要求自主开发一个CRM系统,这个系统将会允许完全不同的团队贡献特定的功能模块。虽然可能有多个开发团队分配来支持每个片段的功能,但是在公司内部有关联的片断的主要客户是销售、账单(billing)和技术支持。已经要求应用程序展现一个主屏幕,允许客户通过输入不同的标准字来查询,包括名字、地址、电话号码、订单编号,和任何已注册的产品系列号。然而,结果视图和工作流应该依赖于在给定时间内执行的业务功能。例如,向上提交客户搜索标准字,销售的使用者可能显示一个与过去有关的购买趋向视图、信用卡等级得分和销售向上趋势的建议;当一个账单使用者可能要展现一个显示客户支付历史的视图时,显示账单争议历史和显著的余额。最初的分析显示有三个工作流从五个不同搜索标准字段来的多种结果,且会有三个包括获取所有区段需要的信息的后端系统。因为变化是慢的,选项被安置到中部的主视图,容易理解,增加新的搜索标准字和工作流需要要求搜索模块开发团队来修改,但相信这些需求是罕见的。

    应用到这个设计选项的夸大训练能使推理承担发生在假设业务区段或后端系统的数量被增加到五十个。作为搜索功能和工作流开始的结果,增强这些关注范围也会增强职责和搜索模块开发团队的负载。这应该所有新特征包括范围、分析、设计、编码和测试和改变与这些相关的要求。依次,这会导致搜索模块团队开发资源数量增加的需求。也可能,同样的最初的假设,对于搜索模块构成的其它做出的设计决策,会引起这些关注的合并。这个可能已经引起设计选项不容易适应那样的职责增强,需要一些内部的重新设计来处理新的关注。

   通过这个训练可以观察到一个显著的问题是,搜索团队要求适合的业务区段与系统支持的工作流的工作量。事实上,最初的解决方案没有度量出增长的需求,增长可能是一个暗示,暗示遍及系统的分布式已经不合适。搜索模块里为巩固搜索功能和做出工作流决策结果的决策是在每个用例之间,重新找出相似的结论。事实是没有给出相等的考虑条件,每个用例必须用特定的方法处理,事实是可能的数量没有真实的边界。因为搜索屏幕提供的是对多个模块集中的功能,即是说,这个支配了内部的基础结构关注。应该,然而,期望所有模块提供公共行为。然而,每个用例的明细没有公共的,且要考虑各自模块的内在关注。在承认内在职责的之上,可供选择的方法包括一个框架的开发,这个框架考虑公共关注,而且使每个领域规格能够分布式。这样的方法的达成,可能需要每个模块提供插件,注册为有效的搜索标准,提供调用适当工作流时的处理能力。那么,框架为展现统一的搜索标准视图负责,为每个搜索标准所关联的工作流处理提供一般的基础结构。通过使用这个方法,搜索模块可以被设计为适应无限量的用例。

夸大训练对创建高可度量设计是有益的,这仅是它最初目标—达到最佳关注分离--的一个副产品. 夸大训练可以比喻为,为病人量体温的医学检查,验证问题下面的可能症状。这个训练通过检查潜在设计的可度量性,试图识别出附着在关注分离上的问题。这可以比喻为使用一个放大镜观察设计的明显,如图19.


Figure 19


    通过对设计实际范围的夸大,小问题可以被放大,而容易识别。一旦识别出,那么,就可以决定采用的什么样的行为路线。

分离的焦虑

    应用关注分离原则经常包括高级概念和带给应用程序领域关注之外的某些复杂层面的结构。对于不熟悉这些编程技术的开发者来讲,在增加一个人的全面设计技能的学习的机会上,起到激发狂热度方面的作用,不利的是,增加了大量的复杂度,包括在许多可能的不合适方法阻碍工作的完成。首次学习中,这些技术经常引起经验的缺乏或更多关注战术层面的开发者,从而刻画出“过度设计”或“过渡工程化”的设计,然后,通过对这样架构的日复一日的操作。更远来讲,经常有来自管理层的从未出现过的压力,这些管理者包括项目经理、产品经理、高层管理、市场,或者为了最终用户的满意而做出的鼓励快速的全面设计。这些条件可能产生妨碍开发好的设计,而仅解决技术问题。

 

    当促进关注分离的设计经常对应用程序增加复杂度时,要指出,他们也要移出一般与关注分离不相关的复杂度。对于许多应用程序,经常发生在有序的复杂度和无序的复杂度之间。没有陈列出合适的关注分离量的应用程序,由于在理解部分之前要理解全部,所以经常学习很困难,维护和扩展很困难。高复杂,缺乏模块化的应用程序也仍然会对开发职员(倾向于未来混合对问题的设计和实现)引起高的流失,或者吸引讨厌事情改变的个人和努力探索在不缺乏“错综复杂”组织里面内建立自己的职业个人。开发团队当然不应该为复杂的风险探索复杂的方案(除非进入了一个困惑的争论中),而且树立一个观点,避免把高级的设计概念等同于避免复杂性。


结论

在某种意义上,关注分离的目标是机制与艺术协调结果之一。一个系统有协调的组件组成,每一个仅执行它内在固有的任务,是混合形态和功能的艺术成就的唯一形态。它是一种努力,满足人类思想的创建和分析的渴望,同时间内,帮助合适的一个人,经常远远超越外部的期望。