典籍翻译:架构风格与网络程序架构设计

最近周末帮外甥女"小雪"补习英语,遴选了Fielding博士的毕业论文作文课外阅读资料,也借这个机会来重新梳理一下软件架构设计的相关理论。

译者序

本文拟对Fielding的博士论文进行翻译,按照"信、达、雅"的原则,在翻译过程中,力求尊重原文原意,同时兼顾语言的简洁通顺。

这是笔者第一次尝试去翻译国外经典论文典籍,作为力学专业、但从事CAx软件开发的技术工作者,笔者深感前辈们呕心沥血的成果来之不易,对文中每句话都反复研究良久,力求不会误解前辈们的谆谆教导。但限于个人水平与从业经历,难免有不当之处,欢迎批评指正。

引言

正如Perry与Wolf所述,架构设计是上世纪90年代研究的焦点。现在的软件系统化更加注重系统组件化:将系统分成独立的组件,通过组件协作来满足系统需求。软件架构主要研究如何划分系统组件、组件间如何通信、信息如何传输、系统单元如何独立演进、如何表述概念等问题。

优秀的架构并不是凭空产生的。所有的设计决策均为满足系统需求为目标的,这条原则在传统建筑行业与软件行业都是一样的。“功能决定形式”的原则来源于建筑行业数百年的经验教训,但软件从业人员却经常忽略这一原则。在短句"Monty Python"中有一段搞笑段子,说是有的建筑师会按照屠宰场结构来设计公寓,这或许能够将建造最好屠宰场,但是对于以后居住在这里的租户来说,他们定会感觉不适。

这看起来有点滑稽,但事实上,很多软件项目会盲目使用很多流行的架构,到最好才发现可能并不需要这种架构。造成这种现象的原因是由于对架构涉及的约束并不了解,实际上就是采用这些架构的设计者并不清楚优秀架构的原理。

本论文研究计算机科学的两个前沿问题:软件和网络。长期以来,软件研究主要关注设计方法的分类、设计方法的演化等问题,但很少讨论设计决策对系统的影响。相反,网络研究主要关注通信的性能,却没有意识到交互方式的改变可能会更重要。本文使用架构约束来探究网络应用程序的架构设计,用以实现期望的架构属性。可以一组自洽的约束集合称之为架构风格。

前三章介绍了使用软件风格来研究软件架构的框架,揭示了架构风格是如何指导网络应用程序架构设计的。对常见的架构风格进行调研,依据架构风格对网络超媒体系统的作用,将这些架构风格进行了分类。分类的目的是为了找出那些可用于WWW软件架构设计的约束。

需要理解Web应用的需求,才能更好的为这类应用程序设计架构。Web应用实际上是一种Internet级别的超媒体系统。Internet将各种信息服务连接在一起,信息服务必须能够弹性伸缩、独立部署等特点。分布式超媒体通过页面内的控件来实现访问信息。Web架构设计需要考虑如何在高延迟的网络撒花姑娘传输大块数据。

针对分布式超媒体系统,第五章引入了一套由许多约束构成的REST架构。REST架构注重组件交互的伸缩性、接口的通用性、组件独立部署、使用中间件来降低延迟等。给出了REST架构的原则及约束,并与其他架构风格进行了比较。

在第六章中,将会说明REST架构在过去的六年时间里已被用于现代Web应用的设计与开发。其中,HTTP与URI则定义了Web应用中组件通信的接口。

在实现过程中,通常并不会完全遵循架构设计里面的约束。REST架构也可以用于识别实现过程中那些违背REST约束的问题,在第六章中,也会对实现过程中的问题进行总结。

简单说,本文主要做了以下工作:

  • 使用架构模式来研究软件架构的方法,同时给出了软件架构的定义。
  • 依据架构模式对分布式超媒体系统的作用,对网络应用程序的架构模式进行了分类。
  • 针对分布式超媒体系统,提出了REST架构
  • 验证REST架构可用于现代Web应用设计与开发。

第一章

软件架构没有公认的定义。这也导致了,许多研究会忽略架构设计的某些方面。本章依据文献研究与对网络应用程序的理解,给出了一种软件架构定义。

1.1 Run-time Abstraction

software architecture is an abstraction of the run-time elements of a software system during some phase of its operation. A system may be composed of many levels of abstraction and many phases of operation, each with its own software architecture.

软件架构的核心是抽象,隐藏实现细节,同时向外暴露接口。一些复杂的系统通常会有多层抽象,每一层可以有一套架构。每层架构对应该层的抽象,向外暴露接口以供本层的其他元素使用;在每个元素内部,子元素也可使用其他架构来实现父元素的接口,直到最基本的元素。

除了架构的层次性,软件系统通常包含启动、初始化、业务处理、重新初始化及关闭等阶段,每个阶段也可以由不同的架构。比如说,配置文件用于系统启动,因而系统启动架构需要将其作为一个构成元素,但是对于业务处理阶段来说,由于配置信息已经分发给系统,此时不会再把配置文件作为业务处理架构的元素。一个完整的架构不仅需要能够描述系统各个阶段的行为,还需要更够涉及不同阶段的转换。

Perry and Wolf将processing elements理解成数据转换器;Shaw将components定义为计算与状态单元;Shaw 与Clements将组件components为系统运行期间处理数据的单元,包括程序、对象、进程及过滤器。这里需要区分一下软件架构(software architecture)与软件结构(software structure):软件架构是系统运行时的描述,软件结构指的是软件代码的描述。软件架构与软件结构不必保持一致,架构设计与代码组织虽然相互密切相关,但是却不是一回事,很多软件架构描述却不能够认识到这种差异。

1.2 Elements

A software architecture is defined by a configuration of architectural elements--components, connectors, and data--constrained in their relationships in order to achieve a desired set of architectural properties.

Perry与Wolf对软件架构进行了深入的研究,他们认为软件架构是一组架构元素构成的集合,这些架构元素具有外观形式与设计原理,将架构元素可以分为processing、data、connecting等。架构元素的外观形式是指架构元素对外具有一定外观属性,同时可以与其他架构元素发生关系,而这些可定义为作用于架构元素上的约束。架构元素的设计原理实际上描述了架构设计过程中的一系列(非)技术决策。

关于软件架构的定义,本文中对Perry与Wolf的见解略有不同。本文认为软件架构不应当包含架构元素的设计原理,尽管架构元素的设计原理是架构研究与设计的一个重要方面,但在架构定义中包含架构元素的原理,意味着设计文档也是系统运行时的一部分。架构元素的设计原理影响架构的演进,但是一经确定,软件架构是独立于架构元素设计原理的。比如,使用反射机制,可以将一个底层架构替换成另一个底层架构,而这过程中并未引入新的架构元素设计原理。

打个比方,如果建筑的设计图纸被焚毁,因为墙体依旧可以支撑屋顶,建筑并不会坍塌。软件架构具有一些属性,忽略这些属性将会毁坏软件的架构。就像在建筑中,使用玻璃来代替承重墙,将会影响建筑的稳定性。因此,软件架构定义中应当包含架构元素的属性,而非架构元素的设计原理,架构元素设计原理是架构元素属性的因,即使没有架构元素设计原理会导致架构发生蜕变,但架构元素设计原理也不应当作为软件架构定义的一部分。

Perry与Wolf的定义中,将架构元素进行了分类,Processing elements 执行数据的变换,data elements是信息数据,connecting elements用于关联不同的元素。本文中分别使用components与connectors 来替换Processing elements、connecting elements。

Garlan与Shaw认为软件架构是由components与connectors构成,Shaw等也对软件架构定义做了补充与扩展。

令人比较诧异的的是,Shaw认为软件架构的描述才是软件软件架构,按照他的定义,软件架构就是软件架构描述文档中的框、线,而且data elements并没有被认为是软件架构元素。这是显然不适合网络应用程序的,因为data elements往往是网络程序中最为重要的。

1.2.1 Components

component is an abstract unit of software instructions and internal state that provides a transformation of data via its interface.

相对来说,比较容易圈定出哪些架构元素是components的。Perry与Wolf认为components用于处理data elements。Garlan与Shaw认为Components用于执行计算。本文中强调components与Connectors的区别。

components提供了一组接口用于处理数据。数据处理包括从二次存储中加载数据到内存、执行计算、转换数据格式、封装数据等。架构中不同组件具有不同的特性。也就是说,每个组件通过接口而非内部实现来向其他组件提供服务。按照Parnas法人说法,这实际上是该组件对其他组件的约定。

1.2.2 Connectors

connector is an abstract mechanism that mediates communication, coordination, or cooperation among components.

Perry与Wolf认为connectors是架构元素的粘合剂。Shaw与Clements则认为connector提供了一种机制用于组件间的通信、互操作等。比如,shared representations、RPC、message-passing protocols以及data streams。

可以将connectors与components做下对比。connectors将数据从一个components传递到另一个components,但不会改变数据内容。当然,connectors内部实现在传输数据之前,可能会修改数据格式,最后会将数据还原成数据的原有格式,这样便于数据传输。从外观行为上来看,不需要关注connectors这种内部实现细节。与之不同,components大多数情况下会修改数据。

1.2.3 Data

datum is an element of information that is transferred from a component, or received by a component, via a connector.

与Perry、Wolf的架构模型相比,不少研究均认为软件架构应当包含data elements。Boasson认为现在软件架构过于注重组件结构与开发工具,建议要重视以数据为中心的架构模型。

data element用于表示一段数据信息,connector会将data element从一个component传递到另一个component。常见的data element包括byte-sequences、messages、marshalled parameters等,但那些永久存在于组件内的数据通常不被看做是data element。像是传感器等component也可以产生数据。

1.3 Configurations

configuration is the structure of architectural relationships among components, connectors, and data during a period of system run-time.

Abowd认为架构由components、connectors、configurations等组成。components负责计算;connectors负责连接不同的components;configurations用于配置components与connectors。可以用不同的符号来表示它们,进而描述软件架构。

或许可以把configurations看作是对components的一组约束。比如,Perry与Wolf在他们的架构模型中引入了topology,用以更加方便地区分 active configuration与其他约束。Medvidovic 与Taylor也对架构中的configurations进行了研究。

1.4 Properties

软件架构的属性是通过编排components、connectors与data来获得的。这些属性可分为功能性属性与非功能性属性。非功能性属性也被乘坐质量属性,包括可维护性、易用性、性能、动态扩展性等。

constraints是按照软件工程的原则来编排architectural elements(包括components、connectors与data等),因此架构属性实际上就是由constraints确定的。比如,uniform pipe-and-filter通过组件接口的通用性来实现可用性与可配置性,也就是说,使用通用性原则获得了可用性与可配置性。

架构设计的目标就是要设计一套架构属性能够满足系统需求的架构。至于说,哪些架构属性更加重要,这个由所研究的问题决定。在本文2.3节,针对网络应用程序,将会讨论哪些较为重要的架构属性。

1.5 Styles

An architectural style is a coordinated set of architectural constraints that restricts the roles/features of architectural elements and the allowed relationships among those elements within any architecture that conforms to that style.

软件架构包括功能性属性与非功能性属性。对不同类型的系统,很难比较它们所使用的软件架构;不同环境下的同一类型系统,也不易比较它们所使用的的架构。架构风格(架构模式)是一种对软件架构进行分类的方法,架构风格关注架构中主要方面,而忽略具体应用相关的细节。

Perry与Wolf认为架构模式是对各种architectural elements的抽象,着重分析架构的重要部分。架构模式封装了架构设计过程中关键性的决策,关注组件约束、组件间的关联等。

Garlan与Shaw等认为软件架构风格是组件间关系的一种模式。具体来说,他们认为软件架构模式给出了一些components、connectors,同时定义了一组约束用于限制这些components、connectors。架构风格来自软件架构,试想若用线、框图来表示软件架构,架构模式则是对其的抽象。Abowd认为软件架构风格可用于去理解一组软件架构的。

新兴的软件架构可能仅是某种已有架构风格的一种,架构风格描述了软件架构的不同方面,一套架构可以包含多种架构风格,一种架构风格也可由多种架构风格混合而成

有些软件架构风格被称为"银弹",能够应对各种场景。但是,一个合格的软件架构师应当明白,应当根据待研究的问题选择合适的软件架构风格。为网络应用程序选择合适的架构风格,需要理解网络应用程序的需求,了解各种相关架构风格及它们能够解决的问题,预见各种架构风格是否适合网络应用程序。

架构风格中的"风格"表示一组自洽的约束集合,这与"风格"一词的原意是不同的。Loerke认为软件架构风格是对过去架构的评价。Loerke认为风格来自建筑设计过程中的约束。把一组约束冠以一种风格,有利于交流。

1.6 Patterns and Pattern Languages

伴随着架构风格的发展,设计模式与模式语言也被应用到面向对象软件开发。设计模式是重复出现的系统结构;模式语言是由模式组成的规则系统。这两个概念源自Alexander编写的建筑结构的著作。

模式的设计空间是面向对象编程中的一些实现技巧,包括继承、组合等。有时候,架构风格描述会被改造为架构模式。但是,模式主要通过抽象来描述对象间通信接口,实际上是对具体实现施加了约束。模式可以用于处理对象间的相互作用。模式定义了解决问题的一种方法。

架构风格与软件模式虽然源自建筑领域的架构,但是它们已与建筑架构分道扬镳。Alexande所提出的模式关注于重复出现的人类活动,而非架构元素的编排,Alexande的设计原则关注于人们生活与文化。

Alexander所提出的模式与软件架构风格由许多相同之处。架构风格包含一组约束,用于满足最终的系统属性。

1.7 Views

系统可以包含多种架构及架构风格,可以从其他角度来分析系统架构。Perry与Wolf提出了三种研究研究软件架构的视角:processing、data及connection。processing着重于组件间的数据流;data着重于处理流程;connection着重于组件间的关系。

可以使用多种视角来研究架构。4+1 View Model使用了五种视角,每种视角关注于一个特定的问题。

1.8 Related Work

此处仅介绍了软件架构的定义及架构模式的描述。软件架构研究还包括架构分析技术、架构恢复和重构、架构设计的工具与环境、架构优化、软件架构案例等。在第三章中将会讨论架构风格分类、分布式处理范式、中间件等相关内容。

1.8.1 Design Methodologies

软件架构的早期研究主要关注于设计方法。比如,面向对象设计提倡基于对象组织系统。在早期的设计方法中,JSD(Jackson System Development)强调架构级设计。JSD使用了pipe-and-filter及process control等约束,但这种设计方法往往仅产生一种架构风格。

早期有一些架构分析及演化的研究。Kazman使用SAAM与ATAM对架构设计进行了研究;Shaw比较了各种汽车巡航控制系统的架构设计。

1.8.2 Handbooks for Design, Design Patterns, and Pattern Languages

Shaw提倡架构设计手册应当与传统工程学科保持同步;这“四人帮”的书、Coplien的文献较早对设计模式进行了分类。

相较于架构风格,软件设计模式更加关注待解决的问题。Shaw基于架构风格给出了8种架构模式;Buschmann深入研究了面向对象开发中的架构风格。但这些文献很少研究架构模式间的不同。

Tepfenhart与Cusick使用二维图比较了domain taxonomies, domain models, architectural styles, frameworks, kits, design patterns及applications。设计模式用于构筑软件架构;架构模式是一类架构的特征;但他们却没有给出架构的定义。

1.8.3 Reference Models and Domain-specific Software Architectures (DSSA)

Reference model给出了描述软件架构及组件间关系的概念框架;OMG提出了一种称为Object Management Architecture (OMA)的Reference model,这个模型定义了如何创建对象、如何共享对象等,OMA抢到对象的管理而非应用。

Hayes-Roth提出了domain-specific software architecture (DSSA) 。这种模型包括:a)特定应用领域的参考框架;b)可重用的组件库;c)应用配置。

DSSA在ADAGE、AIS等某些领域取得了成功。DSSA强调组件重用,而非为某一系统选择架构风格。

1.8.4 Architecture Description Languages (ADL)

近几年,软件架构方面的文献主要是研究architecture description languages (ADL)。Medvidovic与Taylor认为ADL是对系统概念架构模型及描述的语言,至少包括:components, component interfaces, connectors及architectural configurations。

Darwin是一种通用的描述系统结构的语言。Darwin可以对分布式架构及组件架构进行描述。

UniCon可由component、connector来构建架构。Wright提出了一个描述组件间相互作用的原则。

与设计方法一样,ADL也会引入一些假定,这些假定可能会影响其描述架构风格的能力,这些假定也可能与中间件中的假定有冲突。有时,ADL只能用于描述某一种架构风格。比如,C2SADEL是一种仅能描述C2架构的ADL;与之相反,ACME是一种较为通用的ADL,但却不适合用于架构风格分析、构建实际应用。

1.8.5 Formal Architectural Models

Abowd认为可以按照架构语义到架构描述的映射来表述架构风格。但是,这实际上是假定了架构是可描述的,而非运行时的抽象。

Inverardi与Wolf认为可以把架构元素类比成化学制品,这个模型描述了组件间如何变换数据、但对于那些不进行数据流变换的系统来说,如何使用这种模型就不太清楚。

Rapide是一种基于事件的定义、描述架构的语言。Le Métayer则提出了一种基于图的架构定义方式。

1.9 Related Work

本章介绍了本文的研究背景。为了避免理解上的混淆,引入了一些软件架构定义相关的术语。特别是,在软件架构定义中,将data作为一个架构元素,同时总结了其他人在架构、架构风格方向的研究。

接下来的两章,就网络应用程序,将介绍架构风格相关的背景,如何使用架构风格来进行架构设计;然后介绍一些常见的架构模式。

你可能感兴趣的:(CAx,架构)