如果一个项目的系统构架(包括理论基础)尚未确定,就不应该进行此系统的全面开放,只有对构架做出明确清楚的表述,才能使之在整个开发和维护过程中加以充分利用。 -barry
软件架构的确定定义:某个软件或计算系统的软件构架是该系统中的一个或多个结构,他们由软件元素、这些元素的外部可见属性以及这些元素之间的关系组成。
这里所说的某个元素的“外部可见属性”是指其他元素对该元素所做的假设,如它所提供的服务、性能特性、错误处理、共享资源的使用,等等。下面我们深入阐述一下该构架的含义。
- 构架定义了软件元素。构架中包含了关于各元素应如何彼此相关的信息。也就是说,构架必须省略各元素中与其交互无关的某些信息。因此,构架首先是对系统的抽象,该抽象去除了不影响它们如何使用、其他元素如何使用以及如何与其他元素关联或交互的细节。在几乎所有的现代系统中,各元素是通过接口实现交互的,而这些接口又将各元素的细节划分为共有和私有两大类。根据这种划分,构架属于共有部分,而私有部分--即仅与内部具体实现有关的细节--是不属于构架的。
- 该定义明确指出系统可能而且确实由多个结构组成,而且,其中任何一个结构并不能与构架等同。
- 该定义意味着具有软件的每个计算系统都有一个软件构架,这是因为每个软件系统都可以看做是由若干个元素及其相互联系构成的。在最简单的情况下,我们可以把一个系统看做是一个元素。虽然仅有一个元素的构架没有多大价值,而且也不实用,但它符合我们的定义。每个系统都有构架,但这并不意味这任何人都知晓该构架的存在。或许当时参与设计某个系统的所有人员都已故去,文档已经不存在了(或者根本没有将其编成文档),源代码已经丢失(或根本就没发布过),我们所能得到的就是可执行的机器代码。这就是系统构架和对构架具体表述的区别。遗憾的是,构架可以独立于对构架的描述而存在,这也让我们更加认识到构架编档和构架重构的重要性。
- 只要某个元素的行为可以从其他元素的角度观察到或区别开,这个元素的行为就是构架的内容。这是这种行为的存在,才使各元素的交互成为可能,而这种交互显然是构架的一部分。这是被当作构架的框线图其实根本就不是构架的另一个原因。它们只是框线图,提供了所展示的元素做什么的更多信息。 这并不是说在各种情况下都要对各元素的行为和性能给出精确的描述,但如果某个元素的行为对与之交互的另一个元素的代码编写有特定的要求,或者影响到整个系统的可接受性,则该行为就是软件构架的一部分。
最后,我们所给的这个定义并不涉及对构架优劣的评价,这意味着构架将支持或阻止系统满足其行为、性能和生命期需求。我们并不把试错法--即任意选用一个构架,在该构架之上展开系统的开发,并期望得到理想的结果--当作为系统选择构架的最佳方法,因此,这就提出了构架评估和构架设计。
其他观点 大多数常见的定义的要点都是一致的--结构、元素以及元素之间的元素--但它们在细节上有很大不同,不能互换。对系统设计中内在的共性进行抽象是一种尝试,由此它必须说明各种活的、概念、方法、途径和结果。鉴于此,软件工程团体中存在其他构架定义:因为您很可能会遇到其中的一些定义,因此应该理解这些定义的含义并能够对其进行讨论。下面是几个最常见的定义。
- 构架是一种高层设计。与设计相关的其他任务并不是属于构架,如确定将要封装的重要数据结构。访问数据结构的接口肯定属于构架的范畴,但实际做出的选择却不是。
- 构架是系统的总体结构。 这个常见说法(不正确地)暗含的意思是系统只有一个结构。我们知道这种说法是错误的,如果有人持这种观点,不妨问问他所说的结构到底是什么。这种观点不仅仅具有教学上的重要性。后面我们将会看到,不同的结构提供了一个关键的工程设计平衡点,这些平衡点使系统中具有了导致系统成功或失败的质量属性。构架中结构的多样性位于概念的核心。
- 构架是一个软件或系统的组件、组件之间的相互关系以及管理其设计和演变的原理和方针的结构。 任何系统都有一个构架,并且可以独立于设计或演变该构架的过程的知识对其进行探索和分析。
- 构架是组件和连接器。 连接器是指系统运行时为传送控制和数据信息而采用的机制。因此,该定义主要强调了系统运行时的构架。如unix管道就是一个连接器。
构架模式、参考模型和参考构架 在框线骨架和已经填充了关于系统的所有适当信息的构架之间,有很多中间阶段。每个阶段都是执行一组构架决策的结果。其中的一些中间阶段是非常重要的。要讨论构架结构前,我们先给出以下3个定义:
- 构架模式是对元素和关系类型以及一组对其使用方式的限制的描述。可以把构架模式看作是对构架的一组制约条件--即对各元素类型及其交互模式的限制条件,而这些制约条件就确定了一组或一系列能满足它们的构架。 模式最有用的一个方面就是它们展示了已知的质量。这就是为什么设计师选择某个特定的模式,而不是随机选择模式的原因。一些模式代表了性能问题的已知解决方案,一些模式使用于高安全性系统,还有一些模式成功应用在了高可用性系统中。选择构架模式通常是设计师做出的第一个主要的设计决策。 术语构架样式的使用也非常广泛,它用于描述相同的概念。
- 参考模型是一种考虑数据流的功能划分。参考模型是对已知问题的标准分解,分解所得的各个部分相互协作,构成问题的解决方案。产生于实践经验的参考模型是熟知某个领域的体现。
- 参考构架是映射到软件元素(它们相互协作,共同实现在参考模型中定义的功能)及元素之间数据流上的参考模型。参考模型实现了功能划分,而参考构架则将这种功能划分与系统分解对应起来。这种对应可能(但不一定必须)是一一映射。一个软件元素可以实现某个功能的一部分,也可以实现若干个功能。 参考模型、构架模式和参考构架都不是构架,但它们都是捕获构架元素的有用的概念。这三者都是早期设计决策的产物。图2.2给出了这些设计元素之间的关系。 人们经常拿构架这个词与该词的其他用法进行类比,他们对这些用法有更多认识。他们经常将构架与某些物理结构或物理分布联系在一起。建筑设计师在设计大楼时必须要考虑方便性、美观、光照、可维护性等方面的要求。软件设计师在设计中也必须考虑并发性、可移植性、可修改性、易用性、安全性等因素,并且要在这些需求之间进行适当的权衡。
为什么说软件构架非常重要 第1章讨论了构架对企业的重要性。本章将从技术的角度重点讨论构架的重要性。软件构架之所以重要,主要有以下3个基本原因:
- 涉众之间的交流。 软件构架是一种常见的对系统的抽象,绝大多数(如果不是全部的话)系统的涉众都以此作为彼此理解、协商、达成共识或相互沟通的基础。
- 早期设计决策。 软件构架是所开发系统的最早设计决策的体现,而这些早期决策对系统的后续开发、部署和维护具有重要影响。这也是能够对所开发系统进行分析的最早时间点。
- 可传递的系统抽象。 软件构架是关于系统构造及系统各元素工作机制的相对较小、却又能突出反映问题的模型。这种模型可以在多个系统之间传递,特别是可以应用刀具有相似质量属性和功能需求的系统中,并能促进大规模的重用。
构架是可传递、可重用的模型 在整个生命期中,重要的越早,收益就越大。代码的重用能带来极大的便利,而在构架层次上的重用则为具有类似需求的系统开发提供了有利的手段。不仅可以实现代码的重用,还可以实现决定构架选用的系统需求及构建构架的经验的重用。如果构架决策能够在多个系统中得到重用,则也可以获得上面讲到的早期决策所带来的所有好处。 产品线共享一个公共的构架。 软件产品线或家族是一组软件密集型系统,这些系统共享一个公共的、可管理性的特性集,满足了待定市场或任务的具体需要,是 按照规定的方式根据一组公共的核心资产开发的。在这些核心资产中,主要部分就是设计用来处理整个家族需要的构架。产品线设计师通过制定在早期适用与整个家族的设计决策,以及在后期仅适用于单个成员的其他决策,来选择一个满足产品线的所有预想成员的构架。该构架定义了对产品线的所有成员来说,什么是固定的,什么是可变的。对多系统开发来说,软件产品线是一种强大的开发方法,它可以在上市时间、成本、生产率和产品质量方面实现极大的回报。构架的强大源于范例的核心。与其他资本投资类似,产品线的构架将成为开发组织的核心资产。 系统开发可以使用大型的、由其他组织开发的元素。以前的软件范例总是将编程作为最根本的任务,把编写了多少行代码作为衡量项目进展情况的依据。基于构架的开发则更强调对各元素的组合或装配,而这些元素很可能已分别甚至是完全独立地开发实现了。由于构架定义了可以集成到系统中的元素,因此,这种组合是可能的。构架从元素与环境的交互、对控制的接收和释放、所能使用或产生的数据、访问数据的方式、通信方式以及用于通信和资源共享的协议等方面对可能做的更换做了种种约定。 元素结构、接口和操作概念的组织是构架的一个重要方面。互换性是这种组织的最重要的原则。 商业组件、子系统、兼容的通信接口都是基于互换性原则的。 少就是多:限制选择范围是值得的。随着所积累的构架模式和设计模式越来越多,我们将会越来越清楚地认识到:虽然计算机程序可以以近乎无限的方式来组合,但涉及到程序的协调和交互时,有意识地限制在一定范围内选择将使我们受益匪浅。也就是说,我们希望使所构建系统的设计尽可能简单。这种方法的优势包括:重用程度更高、更易于理解和交流的简单规范的设计、更为透彻的分析、更短的选择时间、更强的可互操作性。 软件设计的特性来自于构架模式的选择。那些更适用于某个特定问题的构架模式将改善设计方案的实现,这可能通过更轻松地在相冲突的设计要求之间进行权衡、提高对设计环境的人认识和/或使需求描述中的不一致性更为突出等方式体现出来。 系统构架与软件构架。在过去的5到10年中,我们在很多场合对软件构架进行了讨论。每次总会有人提出如下问题:为什么谈论软件构架?系统构架是否同软件构架一样重要?或者说软件构架和系统构架之间的区别是什么? 在创建软件构架时,通常很少考虑系统。 如果您想让构架具有很高的性能,就需要了解该系统将运行的硬件平台的物理特性以及该系统将与之交互的任何设备的特性,您通常还会关注网络的特性。如果您需要构架具有很高的可靠性,也需要关注硬件,在这种情况下就是关心其故障率和冗余处理或网络设备的可用性。如此等等,不一而足。设计师很少考虑硬件。 因此,设计软件构架时,大概需要考虑整个系统--硬件和软件,否则就是蛮干。当仅规定了系统的一部分时,任何一个工程师都不可能预测系统的特性。 但我们主要谈论的仍然是软件构架而非系统构架。这是为什么呢?因为大多数设计师在软件方面都可以做出选择,而在硬件方面则没有这种*。 构架使基于模板的开发成为可能。构架体现了关于元素交互方式的设计决策。这些决策虽然是每个元素的实现中体现出来的,但却能够局部化,只需编写一次即可。可以在某处用模板将元素间的交互机制描述清楚。 构架可以做为培训的基础。 在对项目新成员介绍所开发的系统时间,可以首先介绍系统的结构,以及对组件之间如何交互从而实现系统需求的高层次的描述。我们曾经指出,软件构架的重要用途之一就是支持并促进各涉众之间的交流,这进一步印证了我们的观点。构架是一个公共的参考点。
构架结构和视图 现代系统非常复杂,很难一下子领会它们。相反,在任何时刻,我们只能把注意力放在软件系统的一个或几个结构上。为了有意义的传达构架信息,必须说明此刻正在讨论哪个或哪些结构--即采用的是构架的哪个视图。
在讨论构架表示时,我们将使用相关术语结构和视图。视图是构架元素的内聚集的表示,由系统涉众编写和阅读。它由一个元素集的表示和元素之间的关系组成。结构是元素本身的集合,它们存在于软件或硬件中。例如,模块结构是系统中的模块和其组织的集合,模块视图是该结构的表示,由某些系统涉纵编档和使用。这些俗语通常可互换使用,但在此我们区别使用这些定义。
大体上可将构架分为3组,这取决于它们所展示的元素的主要特性。
- 模块结构。此处的元素是模块,它们是实现单元。模块表示一种考虑系统的基于代码的方法。模块被分配功能责任区域。这不怎么强调所开发出来的软件如何在运行时表现自己。模块结构能够使我们回答诸如此类的问题:分配给每个模块的主要功能责任是什么?允许模块使用的其他软件元素是什么?它实际使用的其他软件是什么?什么模块通过泛化或特化关系与其他模块相关?
- 组件-连接器结构。此处的元素为运行时组件(它们是计算的主要单元)和连接器(它们是组件间通信的工具)。组件-连接件结构能够使我们回答诸如此类的问题:什么是主要的执行组件,它们如何交互?什么是主要的共享数据存储?复制系统的哪些部分?数据在系统中经过了哪些地方?系统的哪些部分可以并行运行?在系统执行时,其结构可能会发生怎样的变化?
- 分配结构。分配结构展示了软件元素和创建并执行软件的一个或多个外部环境中的元素之间的关系。它们回答了诸如此类的问题:每个软件元素在什么处理器上执行?在开发、测试和系统构建期间,每个元素都存储在什么文件中?分配给开发小组的软件元素是什么?
这3种结构与构架设计所涉及的3大类决策一致:
- 系统如何被组织为一个代码单元集合的?
- 系统如何被组织为一个具有运行时行为(组件)和交互(连接器)的元素集合的?
- 系统如何与其环境中的非软件结构相关(也就是CPU、文件系统、网络和开发小组等)?
-
软件结构 图2.3展示了一些最常见和最有用的软件结构。
表2.1对软件结构进行了总结,该表列出了每个结构中的元素及其关系的含义,并说明了每种结构可能会用于什么情况。
选择哪些结构
我们已经简要地描述了许多有用的构架结构,还有很多其他的构架结构。设计师应该使用哪些结构?设计师应该把哪些结构编成文的?当然,肯定不是使用所有的结构并把所有的结构编成文档。