软件体系结构的五种主要风格类型分析

2013-12-31 00:00:00吴潇璇
考试周刊 2013年39期


  摘要: 本文简述了软件体系结构的定义,探讨了Mary shaw和Daviad Garlan所提出的五种风格,即数据流风格、调用/返同风格、独立组件风格、独立组件风格、虚拟机风格、仓库风格软件体系结构。
  关键词: 软件体系结构定义风格类型
  
  一、什么是软件体系结构
  在所有对于软件体系结构的定义中,我认为最有代表性的就是Hayes Roth所提出的:“认为软件体系结构是一个抽象的系统规范,主要包括用其行为来描述的功能构件和构件之间的相互连接、接口和关系。”这样的定义,我认为从根本上描述了软件体系结构所要做的事情,是一个很概括的规范化公式。与此同时,在定义各式各样的“构件”的时候,人们似乎一直在默认Dewayne Perry和A1ex Wo1f的定义,也就是:“软件体系结构是具有一定形式的结构化元素,即构件的集合,包括处理构件、数据构件和连接构件。处理构件负责对数据进行加工,数据构件是被加工的信息,连接构件把体系结构的不同部分组组合连接起来。”这一定义将处理构件、数据构件和连接构件区分了开来,明确了这三者在软件体系结构中的组件性质,将这三者视为软件体系结构的标准组成及探讨对象。
  在此基础上,反复提到的则是Mary Shaw和David Garlan所提出的:“软件体系结构是软件设计过程中的一个层次,这一层次超越计算过程中的算法设计和数据结构设计。体系结构问题包括总体组织和全局控制、通讯协议、同步、数据存取,给设计元素分配特定功能,设计元素的组织,规模和性能,在各设计方案间进行选择等。软件体系结构处理算法与数据结构之上关于整体系统结构设计和描述方面的一些问题,如全局组织和全局控制结构、关于通讯、同步与数据存取的协议,设计构件功能定义,物理分布与合成,设计方案的选择、评估与实现等。”这样的定义,我认为进一步地提出了软件体系结构的地位和所研究内容的具体情况,它提出了一个对于“控制”和“协议”的具体化要求,在以上定义的基础上强调了软件体系结构对于构架的调配和规划功能,细分了软件体系结构的内容。
  除去Kruchten对于软件体系结构“四个角度”,即概念角度、模块角度、运行角度、代码角度的定义,以及Barry Boehm和他的学生提出的关于强调“互联及约束的集合”的概念之外,还有其他的定义方式。如Bass,Ctements和Kazman在1997年的《使用软件体系结构》书中提出的:“关于一个程序或计算机系统的软件体系结构包括一个或一组软件构件、软件构件的外部的可见特性及其相互关系。”其强调了“软件外部的可见特性”,是指软件构件提供的服务、性能、特性、错误处理、共享资源使用等。这一定义的特点在于把软件体系结构提升,或者也可以说是限制在了软件的“表征特性”上,这使得软件体系结构有了更紧缩、健康的概念。
  我在思考对于软件体系结构的定义的时候,并没有一个标准的答案,因为我在拜读其他名家的定义的时候发现,它们有着很多相似之处,也各自有着突出的特点与不足,这使得我无论是出于尊敬还是出于对自己认识层次的保留,都不愿意给出一个自己所谓的“定义”,但是可以说的是,所谓软件体系结构,是一种思想方式,也是一种分析方式和控制方式,这种方式的对象,是软件(广义)的——主要是创建过程中的—结构和统一规范的建议,其表现形式是构件化的描述体系。这样的一种理解方式,也就是我上面所提及的在前辈们定义的软件体系结构中的三个要素:(1)构件性——软件体系结构由三个构件组成:处理构件、数据构件和连接构件;(2)控制性——软件体系结构的作用是在“控制”和“协议”层次上;(3)表征性——软件体系结构的对象,是“软件外部的可见特性”。
  二、常见软件体系结构风格
  所谓软件体系结构风格是指:“描述某一特定应用领域中系统组织方式的惯用模式。”它反映了领域中众多系统所共有的结构和语义特性,并指导如何将各个模块和子系统有效地组65eeb92b2f48f684fae477c3a96da689织成一个完整的系统。按这种方式理解,软件体系结构风格是指:“定义了用于描述系统的术语表和一组指导构件系统的规则。”对软件体系结构风格的研究和实践促进了对设计的复用,一些经过实践证实的解决方案也可以可靠地用于解决新的问题。体系结构风格的不变部分使不同的系统可以共享同一个实现代码。只要系统是采用常用的、规范的方法来组织,就可使别的设计者很容易地理解系统的体系结构。
  软件体系结构风格有很多种,现在我主要分析的是Mary Shaw和David Garlan所提出的五种主要风格类型,也就是:(1)数据流风格,包括批处理序列,管道/过滤器形式等;(2)调用/返回风格,包括主程序/子程序,面向对象风格,分层结构等;(3)独立组件风格,包括进程通讯,事件系统等;(4)虚拟机风格,包括解释器,基于规则的系统等;(5)仓库风格,包括中心数据库系统,黑板系统等。
  这五种风格各有各的特点,也有共同之处,下面我将逐一分析这些风格。
  1.数据流风格
  这是一种最常见、结构最为简单的软件体系结构。在这样的结构体系下,所有的数据按照流的形式在执行过程中前进,不存在结构的反复和重构。在流动过程中,数据经过序列间的数据处理组件进行处理,然后将处理结果向后传送,最后进行输出,这也就是说,最简单和直接的数据流风格是单向的,没有返回的流水线系统。但是在实际应用中,并不一定限制数据处理组件的顺序,其运算的先后顺序不影响最终系统结构的正确性。这种风格很容易用管道/过滤器的形式(见下图)来解释。
  
  
  
  
  
  
  
  上图所表示的就是一个管道/过滤器的形式,我在随处可见的理论图的原型基础上只保留了其中必要的过滤器块,而用三种不同形式的数据流表示了数据的行进过程,这三种情况分别是单向流水、非顺序流水和回流。其中:
  表示了一种正向的流水方式,也就是最常见的、最直观的数据流方式,在这种方式中,正向数据管道引导数据的正向流动,在此时,我们可以将整个的上方三个过滤器所组成的正向通道作为一个完整的“管道”,这是一种广义的管道。此时,数据从左方,也就是管道的入口处进入,再经过过滤器的处理,最终由“管道”的结尾处流出。
  表示了一种打乱(更改)了顺序的管道方式,交换了其中两个过滤器的顺序,这样的结构在实际中是允许的,并且不影响管道/过滤器输出的正确性。其前提条件是,每个过滤器必须是独立的实体,它不能与其他的过滤器共享数据,而且一个过滤器不知道它上游和下游的标志。同样,也可以把这样的结构视为广义的“管道”。
  表示了一种回流方式,即某些数据可能经由一些管道回流,以通过过滤器的结果数据形式,重新通过过滤器,这种情况下的回流发生在上述广义“管道”内部,而不是像上述两种情况。在上述两种情况之中,也可以存在这种回流方式,只不过回流的情况是返回源头,重新参加数据的流动过程,略有不同。
  此种风格的优点:(1)使得软构件具有良好的隐蔽性和高内聚、低耦合的特点;(2)允许设计者将整个系统的输入/输出行为看成是多个过滤器的行为的简单合成;(3)支持软件重用。主要提供适合在两个过滤器之间传送的数据,任何两个过滤器都可被连接起来;(4)系统维护和增强系统性能简单。新的过滤器可以添加到现有系统中来,旧的可以被改进的过滤器替换掉;(5)允许对一些如吞吐量、死锁等属性的分析;(6)支持并行执行。每个过滤器是作为一个单独的任务完成,因此可与其他任务并行执行。
  
  此种风格的缺点:(1)通常导致进程成为批处理的结构。这是因为虽然过滤器可增量式地处理数据,但它们是独立的,所以设计者必须将每个过滤器看成一个完整的从输入到输出的转换;(2)不适合处理交互的应用。当需要增量地显示改变时,这个问题尤为严重;(3)因为在数据传输上没有通用的标准,每个过滤器都增加了解析和合成数据的工作,这样就导致了系统性能下降,并增强了编写过滤器的复杂性。
  总之,此种风格最大的特点在于简单独立,这就使其具备简便易用的优势及不够丰富灵活的劣势,是一种很基础的风格。
  2.调用/返回风格
  这是一种相对更为常用的风格,在这种风格之中,程序之间不再像“过滤器”那样“必须是独立的实体”,而是有了更为丰富的相互联系,此种情况分很多种,具体到实际应用中的类型,比如子程序调用,面向对象结构化设计,以及分层式系统结构等。这些风格有一个共同的特点,也就是存在一个类似与软件体系结构之对于软件开发的关系的一种迭代关系,即我理解的这种风格,实际上是一种在软件体系结构中套用软件体系结构的过程。
  比如对于主/子程序的调用,在一定环境中,子程序是一段段独立存在的,负责承担相应功能模块功能的个体,而事实上,主程序并不能(指广泛意义上讲)实现其所需要的功能,或者需要重复冗余代码来实现,在此时,采用子程序的调用会给这种情况带来比较好的解决方法,对于一个程序来说,特别是当该程序是由相对独立的功能模块组成的时候,特别是在这种功能模块的调用成为一种长期的、多次的情况的时候,采用将模块设计成子程序由主程序视情况而进行调用,是一种很好的解决办法。
  在面向对象的设计中更是如此,最明显的例子就是抽象数据类型的提出,对于抽象数据类型(A.D.T.)这种描述方式来说,更可以将此种方式作为一种对于软件体系结构的深层套用。而在分层系统中,按照功能模块所处的功能层次进行分解,并由高级调用低级,最终形成金字塔形的整体结构,这样的环境其实在现实的程序环境中是很常见的。对比我们现存的语言环境的分层结构,即高级语言对低级语言的透明调用,也就是这种情况的广义示例,只不过在现实的应用中,我们更多的是在统计的语言环境中,对于所需开发的软件进行功能应用上的分层,而不再注重语言环境上的层次关系(如下图所示)。
  
  
  
  
  
  
  
  
  
  
  
  以上说明的是主/子程序的调用过程,也是最为广泛应用的设计模型。数据抽象和面向对象的风格特点:抽象数据类型概念对软件系统有着重要作用,目前软件界已普遍转向使用面向对象系统。这种风格建立在数据抽象和面向对象的基础上,“数据的表示方法和它们的相应操作封装在一个抽象数据类型或对象中”。这种风格的构件是对象,或者说是抽象数据类型的实例。对象是一种被称作管理者的构件,因为它负责保持资源的完整性。对象是通过函数和过程的调用来交互的。
  此种风格的优点:(1)其可以改变一个对象的表示,而不影响其他的对象,因为该对象对其他对象隐藏其表示,这可以使该对象更独立,对象的更新更安全;(2)设计者可将一些数据存取操作的问题分解成一些交互的代理程序的集合,而不必一切都堆放在一起,提高了进程效率。
  此种风格的缺点:(1)为了使一个对象和另一个对象通过过程调用等进行交互,必须知道对象的标识。只要一个对象的标识改变了,就必须修改所有其他明确调用它的对象,造成了结构修改的复杂;(2)“必须修改所有显式调用它的其他对象,并消除由此带来的一些副作用”也就是说,同时调用一个对象的两者,并不能保证他们对这个对象的操作会不会带来同步上的问题及相互的影响。
  3.独立组件风格
  独立组件的风格很常用常见,在互联网上广为流传的集群计算就是这样的风格,但是不管什么样的表现形式,都有统一的特点,也就是组件的独立性和独立组件间的协同性。在这种风格中,最简单常见,却容易被人忽视的就是基于事件的隐式调用,下面进行具体分析。
  “基于事件的隐式调用风格的思想是构件不直接调用一个过程,而是触发或广播一个或多个事件”。系统中的其他构件中的过程在一个或多个事件中注册,当一个事件被触发,系统自动调用在这个事件中注册的所有过程,这样一个事件的触发就导致了另一模块中的过程的调用。从体系结构上说,这种风格的构件是一些模块,这些模块既可以是一些过程,又可以是一些事件的集合。“过程可以用通用的方式调用,也可以在系统事件中注册一些过程,当发生这些事件时,过程被调用”。基于事件的隐式调用风格的主要特点是事件的触发者并不知道哪些构件会被这些事件影响。这样不能假定构件的处理顺序,甚至不知道哪些过程会被调用,因此,许多隐式调用的系统包含显式调用作为构件交互的补充形式。支持基于事件的隐式调用的应用系统很多,“例如,在编程环境中用于集成各种工具,在数据库管理系统中确保数据的一致性约束,在用户界面系统中管理数据,以及在编辑器中支持语法检查”。
  此种风格的优点:(1)为软件重用提供了强大的支持。当需要将一个构件加入现存系统中时,只需将它注册到系统的事件中;(2)为改进系统带来了方便。当用一个构件代替另一个构件时,不会影响到其他构件的接口。
  此种风格的缺点:(1)构件放弃了对系统计算的控制。一个构件触发一个事件时,不能确定其他构件是否会响应它。而且即使它知道事件注册了哪些构件的构成,也不能保证这些过程被调用的顺序;(2)数据交换的问题。有时数据可被一个事件传递,但在另一些情况下,基于事件的系统必须依靠一个共享的仓库进行交互。在这些情况下,全局性能和资源管理便成了问题;(3)既然过程的语义必须被触发事件的上下文约束,关于正确性的推理就存在问题。
  4.虚拟机风格
  虚拟机的风格在讨论中并没有作为重点,是因为它其实更像是一种软件体系结构中的应用层次。层次系统组织成一个层次结构,每一层为上层服务,并作为下层客户。在一些层次系统中,除了一些精心挑选的输出函数外,内部的层只对相邻的层可见。在这样的系统中构件在一些层实现了虚拟机(在另一些层次系统中层是部分不透明的)。连接件通过决定层间如何交互的协议来定义,拓扑约束包括对相邻层间交互的约束。
  这种风格支持基于可增加抽象层的设计,这样允许将一个复杂问题分解成一个增量步骤序列的实现。每一层最多只影响两层,同时只要给相邻层提供相同的接口,允许每层用不同的方法实现,同样为软件重用提供强大的支持。
  此种风格的优点:(1)支持基于抽象程度递增的系统设计,使设计者可以把一个复杂系统按递增的步骤进行分解;(2)支持功能增强,因为每一层至多和相邻的上下层交互,所以功能的改变最多影响相邻的上下层;(3)支持重用。只要提供的服务接口定义不变,同一层的不同实现可以交换使用。这样就可以定义一组标准的接口,而允许各种不同的实现方法。
  此种风格的缺点:(1)并不是每个系统都可以很容易地划分为分层的模式,甚至即使一个系统的逻辑结构是层次化的,出于对系统性能的考虑,也不得不把一些低级或高级的功能综合起来;(2)很难找到一个合适的、正确的层次抽象方法。
  5.仓库风格
  仓库风格事实上就是一种基于数据库的体系结构,“在仓库风格中,有两种不同的构件:中央数据结构说明当前状态,独立构件在中央数据存储上执行,仓库与外构件间的相互作用在系统中会有大的变化”。控制原则的选取产生两个主要的子类。若输入流中某类时间触发进程执行的选择,则仓库是一传统型数据库;若中央数据结构的当前状态触发进程执行的选择,则仓库是一黑板系统。
  对于这种结构的讨论也不需要太多,因为这种结构太过常用和标准,甚至不用去分析它的优缺点,因为就现实的情况来说,还没有什么系统有可能或者说有希望取代这样的一种风格,其必然会在相当长的时间段里占据主导地位。
  
  
  
  
  
  
  
  
  
  其组成:(1)知识源。知识源中包含独立的、与应用程序相关的知识,知识源之间不直接进行通讯,它们之间的交互只通过黑板来完成;(2)黑板数据结构。黑板数据是按照与应用程序相关的层次来组织的解决问题的数据,知识源通过不断地改变黑板数据来解决问题;(3)控制。控制完全由黑板的状态驱动,黑板状态的改变决定使用的特定知识。
  至此,软件体系结构是一门很抽象的学科,值得研究和大胆探求,接下来需要更加深入地学习其他的相关知识。
  
  参考文献:
  [1]覃征,何坚,谢国彤,王志敏,张丽,王向华.软件体系结构[M].西安:西安交通大学出版社,2002.12.
  [2]Frank Buschmann等著,贲可荣等译.面向模式的软件体系结构[M].卷1:模式系统.北京:机械工业出版社,2003.1.
  [3]谢晓芹,梁邦勇.框架不是框框——应用框架的基本思想[J].计算机世界报,第04期B6、B7.http:∥www.huihoo.com/patterns/framework/4.html.