ANSI/IEEE 610.12-1990软件工程标准词汇对于体系结构定义是:“体系架构是以构件、构件之间的关系、构件与环境之间的关系为内容的某一系统的基本组织结构以及知道上述内容设计与演化的原理(principle)”。
Mary Shaw和David Garlan认为软件体系结构是软件设计过程中,超越计算中的算法设计和数据结构设计的一个层次。体系结构问题包括各个方面的组织和全局控制结构,通信协议、同步,数据存储,给设计元素分配特定功能,设计元素的组织,规模和性能,在各设计方案之间进行选择。Garlan & Shaw模型[1]的基本思想是:软件体系结构={构件(component),连接件(connector),约束(constrain)}.其中构件可以是一组代码,如程序的模块;也可以是一个独立的程序,如数据库服务器。连接件可以是过程调用、管道、远程过程调用(RPC)等,用于表示构件之间的相互作用。约束一般为对象连接时的规则,或指明构件连接的形式和条件,例如,上层构件可要求下层构件的服务,反之不行;两对象不得递规地发送消息;代码复制迁移的一致性约束;什么条件下此种连接无效等。
关于架构的定义还有很多其他观点,比如Bass定义、Booch & Rumbaugh &Jacobson定义、Perry & Wolf模型[7]、Boehm模型等等,虽然各种定义关键架构的角度不同,研究对象也略有侧重,但其核心的内容都是软件系统的结构,其中以Garlan & Shaw模型为代表,强调了体系结构的基本要素是构件、连接件及其约束(或者连接语义),这些定义大部分是从构造的角度来甚至软件体系结构,而IEEE的定义不仅强调了系统的基本组成,同时强调了体系结构的环境即和外界的交互。
什么是模式
模式(Pattern)的概念最早由建筑大师Christopher Alexander于二十世纪七十年代提出,应用于建筑领域,八十年代中期由Ward Cunningham和Kent Beck将其思想引入到软件领域,Christopher Alexander将模式分为三个部分:首先是周境(Context,也可以称着上下文),指模式在何种状况下发生作用;其二是动机(System of Forces),意指问题或预期的目标;其三是解决方案(Solution),指平衡各动机或解决所阐述问题的一个构造或配置(Configuration)。他提出,模式是表示周境、动机、解决方案三个方面关系的一个规则,每个模式描述了一个在某种周境下不断重复发生的问题,以及该问题解决方案的核心所在,模式即是一个事物(thing)又是一个过程(process),不仅描述该事物本身,而且提出了通过怎样的过程来产生该事物。这一定义已被软件界广为接受。
软件模式的应用对软件开发产生了重大的作用,主要表现在:
- 软件模式是人们在长期的设计软件、管理组织软件开发等实践中大量经验的提炼和抽象,是复用软件设计方法、过程管理经验的有力工具。模式类似于拳击中的组合拳,它提供了一系列软件开发中的思维套路。如,通过模式的使用,有利于在复杂的系统中产生简洁、精巧的设计。
- 软件模式为我们提供了一套简洁通用的设计、管理、组织方面的词汇,同时模式也为我们提供了一个描述抽象事物的规范标准,可大大促进软件开发过程中人与人之间的交流,而软件开发中的交流是至关重要的,“软件项目失败的原因最终都可追溯到信息没有及时准确地传递到应该接收它的人”。
架构和模式的关系
因为架构(Architecture)和模式(Pattern)在当前的软件开发中经常地被提及,可是很多人容易混淆这两个术语,而对此,学术界也没有一个非常统一的定义。
架构和模式应该是一个属于相互涵盖的过程,但是总体来说Architecture更加关注的是所谓的High-Level Design,而模式关注的重点在于通过经验提取的“准则或指导方案”在设计中的应用,因此在不同层面考虑问题的时候就形成了不同问题域上的Pattern。模式的目标是,把共通问题中的不变部分和变化部分分离出来。不变的部分,就构成了模式,因此,模式是一个经验提取的“准则”,并且在一次一次的实践中得到验证,在不同的层次有不同的模式,小到语言实现(如Singleton)大到架构。在不同的层面上,模式提供不同层面的指导。根据处理问题的粒度不同,从高到低,模式分为3个层次:架构模式(Architectural Pattern)、设计模式(Design Pattern)、实现模式(Implementation Pattern).架构模式是模式中的最高层次,描述软件系统里的基本的结构组织或纲要,通常提供一组事先定义好的子系统,指定它们的责任,并给出把它们组织在一起的法则和指南。比如,用户和文件系统安全策略模型,N-层结构,组件对象服务等,我们熟知的MVC结构也属于架构模式的层次。一个架构模式常常可以分解成很多个设计模式的联合使用。设计模式是模式中的第二层次,用来处理程序设计中反复出现的问题。例如,[GOF95][2]总结的23个基本设计模式——Factory Pattern, Observer Pattern等等。实现模式是最低也是最具体的层次,处理具体到编程语言的问题。比如,类名,变量名,函数名的命名规则;异常处理的规则等等。
相对于系统分析或者设计模式来说,体系结构从更高的层面去考虑问题,所以关注的问题就体现在“不变”因素上,比如系统部署中,更加关心应用程序的分层分级设计,而在这个基础之上提出的部署方案,才是架构考虑的重点。体系结构关心应用程序模式,更加体现在通过技术去解决这些业务差异带来的影响,关心是否是分布式应用程序,关心系统分层是如何设计,也关心性能和安全,因此在这样的情况之下,会考虑集群,负载平衡,故障迁移等等一系列技术。
希望通过定义的方式来区分架构和模式是不太可能的,因为本来就是交互交叉和提供服务的,它实际上是架构模式,而不是设计模式。在大部份情况下,表现为下面几个设计模式之一:Strategy模式、Mediator模式、Composite模式、Observer模式。对于熟悉架构设计的系统架构师而言,似乎可以用如下来解释架构和模式之间的关系:架构是Hight-Level Design,着眼于不同业务中共性的解决方案,而模式是General Principle(通用原理)。
企业解决方案的构建模式
企业级业务解决方案是公司实现其业务的赌注,它们通常极其复杂,而且性能必须不负众望。它们不仅必须具有高可用性和伸缩性以应对不可预知的使用,而且还必须具有适应性和预见性以适应快速变化的业务要求。最佳解决方案是那些由一组更小的、简单的、能够可靠且有效地解决简单问题的机制组成的解决方案。在构建更大、更复杂的系统过程中,将这些简单的机制组合在一起,从而形成更大的系统。对这些简单机制的认识来之不易。它通常存在于有经验的开发人员和体系结构设计者的头脑中,并且是他们潜意识中自然带到项目中的重要知识。
模式对于开发人员和体系结构设计者非常有用,因为它们:
- 记录能够正常工作的简单机制。
- 为开发人员和体系结构设计者提供通用的词汇和分类法。
- 允许以模式组合的方式简明扼要地描述方案。
- 允许重复使用体系结构、设计和实现决策。
模式可以记录简单机制
模式描述给定上下文中反复出现的问题,并基于一组指导性影响因素来建议解决方案。解决方案通常是一种简单的机制,是为了解决模式中所标示出的问题而一起工作的两个或多个类、对象、服务、进程、线程、组件或节点之间的协作。
您正在构建一个报价应用程序,其中有一个类负责管理系统中的所有报价。很重要的一点是,所有报价都应与该类的一个(而且只与一个)实例进行交互。如何构造您的设计,以便从该应用程序中只能访问该类的一个实例?
解决该问题最简单的方案就是创建一个具有私用构造函数的QuoteManager类,以便任何其他类都不能实例化它。此类包含QuoteManager的一个静态实例,并使用名为GetInstance()的静态方法返回。此代码大体如下所示:
public class QuoteManager
{
//注意:仅适用于单线程应用程序
private static QuoteManager _Instance = null;
private QuoteManager() {}
public static QuoteManager GetInstance()
{
if (_Instance==null)
{
_Instance = new QuoteManager ();
}
return _Instance;
}
//... QuoteManager提供的函数
}
您可能已经像其他许多开发人员那样通过类似的方式解决过类似的问题。实际上,注意反复出现的问题并寻求解决方案的模式作者已经屡次发现了这种实现,提取出了通用解决方案并将这种问题-解决方案对称为Singleton模式[GOF95]。
问题-解决方案对模式
图1 简化的Singleton模式
通过将图1中简化的模式示例与QuoteManager源代码进行比较,阐明了模式(通用问题-解决方案对)和模式应用程序(针对非常具体的问题的具体解决方案)之间的区别。模式级别的解决方案是多个类之间简单但极其顺畅的协作。模式中的通用协作专门适用于QuoteManager类,提供了用来控制报价应用程序中实例化的机制。显然,您可以稍微修改一下某种模式以满足局部的特定要求,所以同一种模式可以应用于无数个应用程序。
所编写的模式提供了一种记录简单且经过证实的机制的有效方法。模式是以特定格式编写的,这一点对于装载复杂思想的容器非常有用。这些模式在被记载和起名之前,就早已存在于开发人员的大脑及其代码中。
位于不同级别的模式
模式存在于多个不同的抽象级别中。考虑另一个示例(这次所处的抽象级别比源代码要高一级):
您要设计一个基于Web的报价应用程序,其中包含大量业务和表示逻辑,这些逻辑反过来依赖大量平台软件组件来提供适当的执行环境。如何在高级别组织系统以使其在具有灵活、松耦合性的同时仍具有高内聚性?
此问题的解决方案之一涉及到按一系列层来组织系统,每层包含大致位于同一抽象级别的元素。随后,确定每一层中的依赖性,并确定采用严格还是宽松的分层策略。接着,决定是打算创建自定义的分层方案,还是采用以前由其他人记录的分层方案。在本例中,假设您决定使用众所周知的分层策略:表示、业务逻辑和数据访问各占一层。图2显示了分层方案的可能外观。
图2 报价应用程序的层
如果您总是按这种方式设计系统,说明您已经在不依赖于任何广义模式的情况下使用该模式。即便如此,您还可能因多种原因而希望了解支撑这种设计方法的模式。您可能迫切想知道为何经常以这种方式构建系统,或者可能在寻找更理想的方法来解决此模式不能完全解决的问题。使用层作为高级别组织方法是Layers(层)模式[Buschmann96][3]中描述的完善模式。图3显示了该模式的简化版本。
图3 简化的Layers模式
这个简单的应用程序组织策略有助于解决软件开发中面临的两个挑战:依存关系的管理和对可交换组件的需求。如果在构建应用程序时没有一个考虑周全的依存关系管理策略,会导致组件易损坏且不牢靠,从而导致对它们进行维护、扩展和替代时存在较大的困难,而且成本较高。
Layers模式中的工作机制比Singleton中的工作机制更精细。对于Layers,首次协作是在设计时发生在类之间,这是由于分层组织将对更改源代码所带来的影响局部化,从而防止所做的更改贯穿到整个系统。第二次协作发生在运行时:某层中相对独立的组件变得可与其他组件交换,再一次使系统其余部分不受影响。
尽管Layers模式的通用性足以应用于诸如网络协议、平台软件和虚拟机之类的领域,但是它无法解决企业类业务解决方案中存在的某些特定问题。例如,除通过分解来管理复杂性(由Layers解决的基本问题)外,业务解决方案开发人员还需要进行适当组织,以便有效地重复使用业务逻辑并保留与昂贵资源(如数据库)的重要连接。解决此问题的方法之一就是使用Three-Layered Application(三层应用程序)模式。图4显示了该模式的简化说明。
图4 简化的Three-Layered Application
同样,在模式(Three-Layered Application)和模式应用程序(报价应用程序分层模型)之间存在区别。模式是有关应用程序组织主题的通用问题-解决方案对,而模式应用程序是通过创建具体的层来解决非常具体的问题。
模式的优化
Three-Layered Application实际上是在Layers的基础上进行的简单优化;在Layers中确定的上下文、影响因素和解决方案仍适用于Three-Layered Application,但反之不行。也就是说,Layers模式约束着Three-Layered Application模式,而Three-Layered Application模式优化了Layers模式。
您为某个发展迅速的成功企业构建了一个报价应用程序。现在,您希望通过向业务合作伙伴公开自己的报价引擎并将其他合作伙伴服务(如配送)集成到该报价应用程序中来扩展该应用程序。您将如何构造自己的业务应用程序以提供和享受服务?
此问题的解决方案之一是通过将其他与服务相关的职责添加到每一层中来扩展Three-Layered Application。在业务层添加了以下职责:通过Service Interfaces(服务接口)向客户应用程序提供一组简化的操作。数据访问层的职责拓宽到了数据库和主机集成之外,以包括与其他服务提供者的通信。将数据访问层中的这个附加功能封装到服务接口组件中,这些组件负责连接到服务(同步和异步)、管理服务的基本会话状态并向业务流程组件通知与服务相关的重大事件。
Three-Layered Services Application(三层服务应用程序)(图5)记录了该问题-解决方案对。
图5 简化的Three-Layered Services Application
将Three-Layered Services Application模式应用于报价应用程序示例将形成如下模型。
图6 应用于报价应用程序的Three-Layered Services Application
请注意这些模式之间的关系(请参阅图7)。Layers引进了一个用来组织软件应用程序的基本策略。Three-Layered Application优化了此概念,并将它限制在需要重复使用业务逻辑、灵活部署和高效使用连接的业务系统的范围内。Three-Layered Services Application又在Three-Layered Application的基础上进行了优化,并对设计进行了扩展,以便在提供和使用其来源千差万别的数据和逻辑时,将这些数据和逻辑处理为粒状元素。
图7 相关模式的优
向特定层中添加其他类型的组件并不是管理这种日益增长的复杂性的唯一方法。正如复杂性所证实的那样,设计人员通常在应用程序中创建其他层来承担该职责。例如,一些设计人员将服务接口移到一个单独的层中。而另外一些设计人员将业务层分隔成域层和应用程序层。在任何情况下,您有时可能会看到某些设计人员在使用此模式来满足复杂要求时,有时会将这三层扩展到四层、五层或者甚至六层。与之相反,Layers模式也用在相对简单的客户端-服务器应用程序中。
解决方案简述:术语“解决方案”有两种截然不同的含义:其一是表示模式本身的一部分(如某上下文中包含的问题-解决方案对);其二是表示业务解决方案。在使用“业务解决方案”这一术语时,它是指专用来满足一组特定的功能和操作业务要求的软件密集型系统。软件密集型系统意味着您不只是关心软件,而且还必须将该软件部署到硬件处理节点以提供整体的技术解决方案。而且,所考虑的软件不仅包括自定义开发的软件,而且包括购买的软件基础结构和平台组件,所有这些都被集成在了一起。
结束语
以.NET为代表的Microsoft产品线向我们展示了“架构为基础,模式为指导”的企业解决方案设计理念,秉承微软产品一贯以来的简单易用以外,同时我们将看到使用.NET构建企业应用平台上使用.NET的优势。毫不夸张地说,.NET不是第一个体现架构和模式的软件应用平台,确是目前为止最后的实现了架构和模式的平台,在随后的文章介绍中,你将会发现,架构设计和模式应用会是如此简单。
[1] 《软件体系结构(影印版)》,科学出版社2004年1月1日出版。Mary Shaw、David Garlan合著,原文书名《Software Architecture: Perspectives on an Emerging Discipline》。
[2] GoF95,《设计模式——可复用面向对象软件的基础》,Erich Gamma、Richard Helm等著,英文版本《Design Patterns: Elements of Reusable Object-Oriented Software》,这是设计模式领域的经典之作,它结合设计实例从面向对象的设计中精选出23个设计模式,总结了面向对象设计中最有价值的经验,并且用简洁可复用的形式表达出来。
[3] [Buschmann96] Buschmann,Frank,《Pattern-Oriented Software Architecture》,John Wiley & Sons Ltd,1996。中文版《面向模式的软件体系结构》,2003年1月机械工业出版社出版。