Chapter 1 什么是软件架构

目录

什么是软件架构?什么不是软件架构?

架构是一组软件结构

架构是一种抽象

每个软件系统都有一个软件架构

架构包含行为

不是所有的架构都是好架构

架构和视图

结构和视图

三种结构

结构提供洞察力

一些有用的模块结构

一些有用的组件和连接器结构

一些有用的分配结构

将结构相互关联

少即是多

应该选择哪些结构?

架构模式

什么构成“好”的架构?

总结

推荐阅读

讨论问题


阅读一本提取了许多人关于软件架构经验的书,书中预设到:

1. 一个软件架构对一个软件系统的成功发展来说是重要的,而且

2. 有充分的、充分推广的关于软件架构的知识体去填满一本书

这本书的目的是说服你,这些假设都是真的。一旦你被说服了,给你一个基础知识,这样你就可以自己应用了。

构建软件系统是为了满足组织的业务目标。架构是那些(抽象的)业务目标和(具体的)最终结果体系的桥梁。虽然从抽象目标到具体系统之路可能很复杂,但好消息是软件架构可以通过使用已知的支持这些业务和任务目标完成的技术来进行设计、分析、文档和实现。复杂性可以被控制,变得易于处理。

那么,这些就是本书的主题:架构的设计、分析、文档和实现。

在这章,我们将严格地从软件工程的角度来关注架构。就是说,我们将研究软件架构给一个发展项目带来的价值。(以后的章节将从商业组织的角度出发)

什么是软件架构?什么不是软件架构?

软件架构有许多定义,通过网络搜索很容易发现,但是我们喜欢这个定义:

系统的软件架构是对系统进行推理所需要的一组结构。它包含软件元素,软件元素之间的关系,以及二者的属性。

这个定义与讨论系统“早期”或“主要”设计决策的其他定义形成对比。虽然很多架构决策都是在早期做出的,但不是所有——尤其是在敏捷和螺旋开发项目中。同样,很多早期做出的决策与架构无关。此外,我们很难辨别一个决策是否重要。有时只有时间能证明一切。因为写架构是架构师最重要的责任,我们需要知道一个架构包含哪些决策。

另一方面,结构在软件中非常容易识别,它们针对系统设计形成一个强有力的工具。

让我们看看我们定义的一些含义:

架构是一组软件结构

这是我们定义中第一个也是最明显的含义。结构只是被关系组合在一起的一组元素。软件系统由许多结构组成,没有任何一个结构声明为架构。体系结构有三大类,在架构的设计、文档、分析中发挥了巨大的作用:

1. 第一,一些结构将系统划分为执行单元,在这本书中我们叫做模块。模块被分配了特定的计算义务,是编程团队工作分配的基础(A队负责数据库,B队负责业务规则,C队负责用户接口,等等)在大型项目中,这些模块被细分,以分配给子团队。例如,大型企业资源规划的数据库的实现可能非常复杂,以至于它的实现被分成许多部分。捕获这种分解的结构是一种模块结构,实际上是一种模块分解结构。另一种模块结构作为面向对象分析和设计——“类图”来出现,如果你将模块聚合到层中,你将创造另一种(非常有用的)模块结构。模块结构是静态的结构,因为他们专注于系统功能分解并分配给实现团队的方式。

2. 其他结构是动态的,意味着它们关注元素在运作时相交互以执行系统功能的方式。假设要给系统建一组服务。这个服务、与之交互的基础设置、它们间的同步和交互关系形成了通常被用来描述一个系统的另一种结构(新结构)。这些服务编译自我们刚刚描述的各种执行单元中的程序。这本书中我们将运行时结构叫做“组件和连接器”(C&C)结构。在软件工程中,术语组件是超载的。在我们的使用中,一个组件就是一个运行实体。

3. 第三种结构描述了从软件结构到系统的组织、开发、安装与执行环境的映射。例如,模块被分配给团队进行开发,并将其分配给文件系统中的位置以进行实现、集成和测试。为了执行,组件被部署到了硬件上。这些映射叫做分配结构。

尽管软件包含无穷无尽的结构,但并非所有的结构都是架构。例如,按照由短到长的顺序给包含字母Z的源代码行集排序。它是一个软件结构,但它不是很有趣,也不是软件架构。如果一个结构支持系统和系统属性的推理,那么它就是架构。推理应该是关于对某些利益相关者非常重要的系统属性。这些包括了系统实现的功能,在面对故障时系统的可用性,给系统进行特定修改的难度,系统对用户请求的响应能力,和许多其它的。我们将在本书中花费大量时间讨论架构和像这些质量属性之间的关系。

因此,架构集不是固定的或有限的。架构是在你的系统上下文中有用的东西。

架构是一种抽象

因为架构由结构组成,而结构由元素和关系组成,所以一个架构由软件元素和元素之间的相互关系组成。这意味着架构特别省略了对系统推理无用的元素的某些信息——尤其是,它省略了在单个元素之外没有分支的信息。因此,一个架构首先是一个系统的抽象,它选择了某些细节而忽略了其他细节。在所有的现代化系统中,元素通过接口的方式交互,接口将元素的细节分割为public部分和private部分。架构关注的是public这边的划分;元素的private细节——只与内部实现有关的细节——不是架构的。然而,除了接口之外,架构抽象让我们从元素的角度看系统,他们是如何被安排、交互、组成的,他们支持我们系统推理的属性是什么,等等。这种抽象对驯服系统的复杂性是很重要的——我们只是不能,也确实不想在全部时间处理所有复杂性。

(在这本书中我们使用术语“元素”来指代一个模块或一个组件,且不想加以区分)

每个软件系统都有一个软件架构

每个系统都可以显示为元素和他们之间的关系,以支持某种类型的推理。在最微不足道的情况下,一个系统自己就是一个单独元素——一个无趣的、可能无用的架构,尽管如此它是一个架构。

即使每个系统有一个架构,却并不意味着任何人都要知道此架构。可能所有设计系统的人都走了,文档灭绝(或者从未产生),源代码丢失(或从未交付),我们全部拥有的只是可执行的二进制代码。这揭露了系统架构和架构存在之间的区别。因为一个架构可以独立于它的描述或规范而存在,这提高了架构文档的重要性,它在18章中讲到;还有架构重构,在20中章讲到。

架构包含行为

每个元素的行为都是架构的一部分,因为行为可以被用来推理系统。行为具象化了元素之间的交互,这种交互明显是我们架构定义的一部分。这告诉我们架构的框架图实际上根本不是架构。当看到框名时(数据库、图形用户界面、执行等等),一个读者可能会将对应元素的功能和行为很好滴想象出来。这个精神想象接近于一个结构,但它从观察者的想象力中诞生,且依赖于没有出现的信息。这不意味着每个元素的确切行为和性能必须在所有情况被记录下来——某些行为的方面是细粒度的,而且低于架构师关注的层级。但是如果到了元素行为影响拎一个元素或影响整个系统接受性的程度,这个行为必须作为系统架构的一部分来考虑并记录下来。

不是所有的架构都是好架构

对于一个系统的架构是好是坏,这个定义是无关紧要的。一个架构可能会允许或阻止一个系统行为、质量属性和生命周期需求的完成。假设我们不接受试错法作为选择系统架构的最佳方法——也就是说,随机地选择一个架构,以此为基础建立一个系统,不断优化——这提高了架构设计的重要性,在17章中讨论,21章处理架构评估

架构和视图

结构和视图

我们将使用相关术语结构和视图来讨论架构的表示。

· 一个视图是一组连贯的架构元素的表示,由系统利益相关者编写和阅读。它由一组元素表示和它们之间的关系组成

· 结构是一组元素本身,因为它们存在于软件或硬件中

总之,视图是结构的表示。例如,模块structure是系统模块和它们组织的集合。模块view是该结构的表示,依据选定符号的模版被文档化,被一些系统利益相关者所使用。

所以:架构师设计结构。他们记录那些结构的视图

三种结构

正如我们在前一节中看到的,架构可以被分为三大类,这依赖于它们所展示的普遍性质。这对应于架构设计包含的三大决策:

1. Module structures将决策具象化,这个决策是如何将系统组织为必须搭建或获得的一组代码或数据单元。在任何模块结构中,元素都是某种模块(可能是类、层,或仅仅是功能的划分,所有这些都是实现单元)。模块代表了考虑系统额度一种静态方法。模块被分配功能职责区;在这些结构中,对作为结果的软件在运行时如何呈现自己的重要性较少。模块结构允许我们回答下面的问题:

· 什么是分配被每个模块的主要功能职责?

· 模块还允许使用哪些其他软件元素?

· 它实际使用和依赖的其他软件是什么?

· 哪些模块通过泛化或专门化(即继承)关系与其他模块相关?

模块结构直接传达这些信息,但是当分配给每个模块的职责发生变化时,它们也可被用来扩展地询问对系统的影响。换句话说,检查系统的模块结构,即查看其模块视图,是推断系统可修改性的极好方法。

2. C&C structures则更侧重于系统的运行时行为,解决如何将系统结构化为一组具有运行时行为的元素(组件)和互动(连接器)。

· 通过这种结构,可以理解系统中的主要执行组件以及它们在运行时的交互方式。

· 它可以帮助识别和理解系统中用于存储共享数据的关键部分。

· 该结构还可以揭示系统的哪些部分被复制以提高可用性或性能。

· 它可以帮助你理解数据在系统中的流动和处理方式。

· 这可以提供关于系统哪些部分可以并行执行以提高性能的洞察。

· 组件和连接器视图还可以帮助回答系统的结构是否可以在运行时更改,以及如何更改的问题。

延伸来说,组件和连接器视图对于提问系统的运行时属性(如性能、安全性、可用性等)至关重要。

3. Allocation structures体现了系统将如何与其环境中的非软件结构(如CPU、文件系统、网络、开发团队等)相关联的决策。这些结构显示了软件元素与一个或多个外部环境中的元素之间的关系,这些外部环境是软件被创建和执行的地方。分配视图可以帮助我们回答以下问题:

  • 每个软件元素在哪个处理器上执行?
  • 在开发、测试和系统构建期间,每个元素存储在哪些目录或文件中?
  • 每个软件元素如何分配给开发团队?

这种视图侧重于软件和其运行环境之间的映射和关系,这包括物理环境和组织环境。它可以帮助团队理解和答复有关系统如何与其它元素交互,以及如何进行资源分配的问题,从而确保系统的顺利运行和高效开发。

结构提供洞察力

结构在我们理解软件架构的角度上起着非常重要的作用,这是因为它们具有分析和工程能力。每种结构都提供了一个用于推理某些相关质量属性的视角。例如:

  • "uses" structure 是模块结构的一种,它体现了哪些模块使用了其他模块,与系统可以轻松扩展或缩减的程度有很强的联系。
  • concurrency structure 体现了系统内的并行性,与系统能够轻松地避免死锁和性能瓶颈有很强的联系。
  • deployment structure 与实现性能、可用性和安全目标的成功度有很强的联系。

等等。每种结构都为架构师提供了对设计的不同洞察力(即,每种结构都可以分析其实现一个质量属性的能力)。但也许更重要的是,每种结构都为架构师提供了一个工程杠杆点:通过适当地设计结构,可以实现所需的质量属性。

在第4章中描述的场景对于测试给定结构及其与其他结构的连接很有用。例如,一个想要更改系统并发结构的软件工程师需要查阅并发和部署视图,因为受影响的机制通常涉及进程和线程,而物理分布可能涉及与在单机上协同定位的进程使用不同的控制机制。如果需要更改控制机制,则需要查阅模块分解来确定更改的范围。

一些有用的模块结构

以下是一些有用的模块结构:

  • 分解结构 Decomposition structure:该结构中的单位是模块,这些模块通过“是子模块的关系”相互关联,显示了模块是如何递归分解为更小的模块,直到模块足够小而容易理解。此结构中的模块代表设计的常见起点,因为架构师列举了软件的单位将要做什么,并将每一项分配给一个模块进行后续(更详细的)设计和最终实现。模块通常与产品(如界面规范、代码、测试计划等)相关联。分解结构在很大程度上决定了系统的可修改性,因为它确保了可能的变化是局部的。也就是说,变化最多只涉及少数(最好是小型)模块。这种结构通常用作开发项目组织的基础,包括文档的结构和项目的集成和测试计划。该结构中的单位往往具有特定于组织的名称,如“段”或“子系统”。

  • 使用结构 Uses structure:在这个重要但被忽视的结构中,单位也是模块,可能是类。单位之间通过使用关系(一种专门的依赖关系)相关联。一个软件单位如果使用另一个单位,则第一个单位的正确性需要第二个单位正确运行的版本(而不是存根)。使用结构用于构建可以扩展以添加功能的系统,或可以从中提取有用的功能子集的系统。轻松创建系统的子集允许进行增量开发。

  • 层结构 Layer structure:该结构中的模块称为层。层是一个抽象的“虚拟机器”,通过一个受管理的接口提供一组连贯的服务。层只允许以严格受控的方式使用其他层;在严格分层的系统中,一个层只允许使用其下面的层。该结构用于赋予系统可移植性,即更改底层计算平台的能力。

  • 类(或泛化)结构 Class (or generalization) structure:该结构中的模块单位称为类。关系是继承自或是实例化自。该视图支持关于集合的推理,这些集合具有相似的行为或能力(例如,其他类继承自的类)和参数化的差异。类结构允许人们推理关于重用和功能的增量添加。如果一个项目已经遵循了面向对象的分析和设计过程,并且存在任何文档,那么它通常是这种结构。

  • 数据模型 Data model:数据模型描述了静态信息结构,用数据实体和它们的关系来表示。例如,在一个银行系统中,实体通常会包括账户、客户和贷款。账户具有几个属性,如账户号码、类型(储蓄或支票)、状态和当前余额。关系可能规定一个客户可以有一个或多个账户,一个账户可以与一个或两个客户关联。

这种结构提供了一个明确的方式来组织和理解系统中的数据和它们之间的关系,对于理解系统的行为和实现特定的质量属性非常重要。

一些有用的组件和连接器结构

组件和连接器结构展示了系统的运行时视图。在这些结构中,上述描述的模块都已编译成可执行的形式。所有组件和连接器结构因此与基于模块的结构是正交的,处理一个运行系统的动态方面。所有组件和连接器结构中的关系是附着关系,展示了组件和连接器是如何连接在一起的(连接器本身可以是熟悉的结构,比如“调用”)。有用的C&C结构包括以下几种:

  • 服务结构 Service structure:这里的单位是通过诸如SOAP(见第6章)之类的服务协调机制相互操作的服务。服务结构是一个帮助工程师设计由可能独立开发的组件组成的系统的重要结构。

  • 并发结构 Concurrency structure:这种组件和连接器结构允许架构师确定并行的机会和资源竞争可能发生的位置。单位是组件和它们的通信机制的连接器。组件被排列成逻辑线程;一个逻辑线程是一系列可以在设计过程后期分配给单独的物理线程的计算。并发结构在设计过程的早期阶段被用来识别管理与并行执行相关的问题的要求

一些有用的分配结构

分配结构定义了C&C或模块结构中的元素如何映射到非软件事物:通常是硬件、团队和文件系统。有用的分配结构包括以下几种:

  • 部署结构 Deployment structure:部署结构展示了如何将软件分配给硬件处理和通信元素。元素是软件元素(通常是来自C&C视图的进程)、硬件实体(处理器)和通信路径。关系是“分配给”,显示软件元素驻留在哪些物理单位上,并且如果分配是动态的,则为“迁移至”。这种结构可以用来推理关于性能、数据完整性、安全性和可用性的问题。它在分布式和并行系统中特别感兴趣。
  • 实现结构 Implementation structure:这种结构展示了软件元素(通常是模块)如何映射到系统的开发、集成或配置控制环境中的文件结构。这对于开发活动和构建过程的管理至关重要。(实际上,您的开发环境工具的屏幕截图,该工具管理实现环境,通常可以形成一个非常有用和足够的实现视图图表。)
  • 工作分配结构 Work assignment structure:这种结构将实现和整合模块的责任分配给将执行它的团队。将工作分配结构作为架构的一部分使得清楚地知道谁做这项工作既有架构意义又有管理意义。架构师将知道每个团队所需的专业知识。此外,在大型多源分布式开发项目中,工作分配结构是用来指明功能共性的单位并将其分配给一个团队的手段,而不是让每个需要它们的人来实现它们。这种结构还将确定团队之间的主要通信路径:定期的电话会议、维基、电子邮件列表等。

这些结构提供了一种明确和组织的方式来定义和理解软件元素如何与其环境中的非软件元素相关联,这对于保证系统的各种质量属性和理解系统如何开发和维护至关重要。

将结构相互关联

每种结构都为系统提供了不同的视角和设计手柄,每种结构本身都是有效且有用的。尽管这些结构提供了不同的系统视角,但它们并非独立的。一个结构的元素将与其他结构的元素相关联,我们需要推理这些关系。例如,在分解结构中的一个模块可能表现为一个组件和连接器结构中的一个,一个的一部分,或几个组件,反映其运行时的另一面。通常来说,结构之间的映射是多对多的。

图1.2展示了两个结构如何相互关联的一个非常简单的例子。左图显示了一个微型客户端-服务器系统的模块分解视图。在这个系统中,必须实现两个模块:客户端软件和服务器软件。右图显示了同一系统的组件和连接器视图。在运行时,有十个客户端正在运行并访问服务器。因此,这个小系统有两个模块和十一个组件(和十个连接器)。

虽然分解结构中的元素与客户端-服务器结构中的元素之间的对应关系是显而易见的,但这两个视图用于非常不同的事物。例如,右侧的视图可以用于性能分析,瓶颈预测和网络流量管理,这些使用左侧的视图来做是极其困难或不可能的。

(在第13章中,我们将学习map-reduce模式,其中简单的,相同的功能被分布在数百或数千个处理节点上,整个系统有一个模块,但每个节点有一个组件。)

个别项目有时会认为一个结构是主导结构,并尽可能地用主导结构的术语来表述其他结构。通常主导结构是模块分解结构。这有一个很好的理由:它倾向于产生项目结构,因为它反映了开发的团队结构。在其他项目中,主导结构可能是一个显示系统的功能和/或关键质量属性是如何实现的C&C结构。

少即是多

并不是所有的系统都需要考虑多种架构结构。系统越大,这些结构之间的差异往往就越明显;但对于小系统来说,我们常常可以用更少的结构来应对。与其使用几种组件和连接器(component-and-connector, C&C)结构,通常一个就足够了。如果只有一个进程,那么进程结构就崩溃到一个单一的节点,不需要在设计中明确表示。如果不进行分布式部署(也就是说,如果系统是在一个单一的处理器上实现的),那么部署结构就变得微不足道,不需要进一步考虑。

总的来说,只有当设计和记录一个结构能够带来正面的投资回报时才进行,通常是通过减少开发维护成本来实现的。

应该选择哪些结构?

我们简要描述了许多有用的架构结构,还有更多其他的结构。架构师应该选择哪些来进行工作?应该选择哪些来进行记录?肯定不是全部。第18章将更深入地讨论这个话题,但目前一个好的答案是,你应该思考各种可用的结构如何为你提供洞察和对系统的最重要的质量属性的影响,然后选择那些在实现这些属性方面发挥最佳作用的结构

架构模式

在某些情况下,架构元素以解决特定问题的方式组合在一起。这些组合经过时间的检验,在许多不同的领域都被证明是有用的,因此它们被记录和传播了下来。这些架构元素的组合称为“architectural patterns”,它们为解决系统面临的一些问题提供了打包策略。

一个架构模式明确了用于解决问题的元素类型及其交互方式。可以根据模式使用的架构元素类型来描述模式。例如,一个常见的模块类型模式是:

  • 分层模式 Layered pattern:当软件元素之间的“使用”关系是严格单向的时,会出现一个层次结构系统。一层是一组相关功能的有序集合。在一个严格的分层结构中,一个层只能使用它下面那一层的服务。这种模式在实践中有很多变种,以减少结构上的限制。层通常被设计为抽象(虚拟机),它隐藏了下层的实现细节,从而产生可移植性。

常见的组件和连接器类型模式包括:

  • 共享数据(或仓库)模式 Shared-data (or repository) pattern:该模式包括创建、存储和访问持久数据的组件和连接器。仓库通常采用(商业)数据库的形式。连接器是管理数据的协议,例如SQL。
  • 客户端-服务器模式 Client-server pattern:组件是客户端和服务器,连接器是它们之间共享的协议和消息,用于执行系统的工作。

常见的分配模式包括:

  • 多层模式 Multi-tier pattern:描述如何将系统的组件分布和分配到由某些通信媒介连接的不同的硬件和软件子集中。此模式专门描述了通用的部署(软件到硬件分配)结构。
  • 能力中心和平台 Competence center and platform:这些是专门描述软件系统工作分配结构的模式。在能力中心中,工作是根据一个站点的技术或领域专长来分配的。例如,用户界面设计是在一个具有可用性工程专家的站点完成的。在平台中,一个站点负责开发软件产品线(见第25章)的可重用核心资产,而其他站点则开发使用核心资产的应用程序。

我们将在第13章进一步探讨架构模式。

什么构成“好”的架构?

没有绝对好或坏的架构。架构更多的是针对某些目的而言是更适合或者不适合。例如,一个三层服务导向架构可能正是一个大企业基于网络的B2B系统所需要的,但对于航空电子应用程序来说就完全不适合。一个为了实现高可修改性而精心打造的架构对于一个一次性的原型来说并不合适(反之亦然!)。本书的一个重点是,实际上可以评估架构——这是关注它们的巨大好处之一——但只能在特定明确目标的上下文中进行。

尽管如此,在设计大多数架构时仍应遵循一些经验法则。如果不遵循这些规则,不一定意味着架构会有致命的缺陷,但至少应作为一个警告标志进行调查。

我们将我们的观察分为两类:流程推荐和产品(或结构)推荐。我们的流程推荐如下:

1. 架构应该是一个单一的架构师或一个有明确技术领导的小型架构师团队的产物。这种方法赋予了架构其概念完整性技术一致性。这个建议同样适用于敏捷和开源项目以及“传统”项目。应该有一个强大的连接将架构师和开发团队联系起来,以避免出现不切实际的象牙塔设计。
2. 架构师(或架构团队)应该持续地根据一份优先排序的、明确规定的质量属性要求来构建架构。这将影响总是会发生的权衡。功能性没那么重要。
3. 架构应该使用视图来记录。这些视图应该根据项目时间线来解决最重要的利益相关者的关切。这可能意味着首先进行最小的文档记录,然后再详细阐述。关切通常与系统的构建、分析和维护以及新利益相关者的系统教育有关。
4. 应该评估架构实现系统重要质量属性的能力。这应该在生命周期的早期进行,当它带来最大的好处时,并在适当的时候重复,以确保对架构(或其预期的环境)的变化没有使设计变得过时。
5. 架构应该便于分步实现,以避免一次性集成所有内容(这几乎永远不会奏效),同时也可以及早发现问题。实现这一点的一个方法是创建一个“骨架”系统,其中通信路径被执行,但最初功能很少。可以使用这个骨架系统来逐步“增长”系统,根据需要进行重构。

我们的结构性经验法则如下:

1. 架构应该具有功能责任基于信息隐藏关注点分离原则分配的明确定义的模块。信息隐藏模块应该封装可能会改变的事物,从而将软件隔离于这些变化的影响。每个模块都应该有一个明确定义的接口,将可变的方面从使用其设施的其他软件中“隐藏”或“封装”起来。这些接口应该允许它们各自的开发团队大体独立地工作。

2. 除非你面临前所未有的需求(可能但不太可能),你应该使用众所周知的架构模式和策略(在第13章中描述)来实现你的质量属性,每个属性都有特定的模式和策略。

3. 架构永远不应依赖于特定版本的商业产品或工具。如果必须这样做,那么它应该被构造成可以简便和经济地更换到不同版本。

4. 生成数据的模块应该与消耗数据的模块分开。这有助于提高可修改性,因为更改通常限制于数据的生成或消耗方面。如果添加了新数据,两边都将需要更改,但这种分离允许分阶段(增量)升级。

5. 不要期望模块和组件之间存在一一对应的关系。例如,在具有并发性的系统中,可能有多个实例的组件并行运行,每个组件都是由相同的模块构建的。对于具有多线程并发的系统,每个线程可能使用来自几个组件的服务,每个组件都是由不同的模块构建的。

6. 每个进程都应编写成可以轻松更改其分配给特定处理器的方式,甚至可以在运行时更改。

7. 架构应该提供少量的组件交互方式。也就是说,系统应该以相同的方式做相同的事情。这将有助于提高可理解性,减少开发时间,提高可靠性,并增强可修改性。

8. 架构应包含一个特定的(且小的)资源争用区域集合,其解决方案应明确指定并维护。例如,如果网络利用是一个关注点,那么架构师应该为每个开发团队产生(并执行)指南,以实现最少的网络流量。如果性能是一个关注点,架构师应该产生(并执行)主要线程的时间预算。

总结

系统的软件架构是用于理解系统所需的一组结构,其中包括软件元素,它们之间的关系以及它们的属性。

结构是一组元素及其之间关系的集合。

视图是由系统利益相关者编写和阅读的一组协调的架构元素的表示。视图是一个或多个结构的表现。

结构有三个类别:
- 模块结构显示系统如何被构造为一组需要构建或获取的代码或数据单位。
- 组件和连接器结构显示系统将如何被构造为一组具有运行时行为(组件)和交互(连接器)的元素。
- 分配结构显示系统将如何与其环境中的非软件结构(如CPU,文件系统,网络,开发团队等)相关联。

结构代表了架构的主要工程杠杆点。每个结构都带来了操控一个或多个质量属性的能力。它们代表了创建架构的强大方法(后来用于分析它并向其利益相关者解释它)。正如我们将在第18章中看到的,架构师选择作为工程杠杆点的结构也是选择作为架构文档基础的主要候选结构。

每个系统都有一个软件架构,但这个架构可能已被记录和传播,也可能没有。

没有所谓的固有好或坏的架构。架构只是更适合或不太适合某些目的。

推荐阅读

大卫·帕纳斯(David Parnas)的早期工作奠定了软件架构研究的概念基础。一个典型的帕纳斯读者应该包括他关于信息隐藏的基本文章[Parnas 72],以及他关于程序系列的作品[Parnas 76]、软件系统中固有的结构[Parnas 74]和使用用途结构来构建系统的子集和超集的介绍[Parnas 79]。所有这些论文都可以在他的重要论文合集中更容易找到[Hoffman 00]。

佩里和沃尔夫的一篇早期论文[Perry 92]将软件架构视图和结构与房屋中找到的结构(如管道、电气等)进行了类比。

软件架构模式已在“面向模式的软件架构”系列中进行了大量的分类记录[Buschmann 96]等。本书的第13章也讨论了架构模式。

关于工业开发项目中使用的架构视图的早期论文是[Soni 95]和[Kruchten 95]。前者发展成一本书[Hofmeister 00],全面展示了在开发和分析中使用视图的情况。后者则发展成了Rational Unified Process,关于这个过程有很多参考资料,包括纸质和在线资料。一个好的参考是[Kruchten 03]。

克里斯蒂娜·加切克(Cristina Gacek)和她的同事在[Gacek 95]中讨论了围绕软件架构的流程问题。

Garlan和Shaw在软件架构的开创性工作中[Garlan 93]提供了许多出色的架构风格示例(一个与模式类似的概念)。

在[Clements 10a]中,你可以找到关于架构模式和架构风格之间区别的扩展讨论。(它认为模式是一个上下文-问题-解决方案的三元组;风格仅仅是一个更侧重于解决方案部分的浓缩形式。)

请参阅[Taylor 09]以获取基于决策而非结构的软件架构定义。

讨论问题

1. 软件架构常常被拿来和建筑的架构做概念类比。这种类比有什么优点?在建筑中对应软件架构结构和视图的是什么?对应模式的是什么?这种类比有什么弱点?它何时会失效?

2. 你接触过的架构是否记录了像本章所描述的不同结构和关系?如果是,是哪些?如果不是,为什么不是?

3. 你是否熟悉软件架构的另一种定义?如果是的话,将其与本章给出的定义进行比较和对比。许多定义都包含像“理由”(陈述架构为何是现在这样的原因)或是架构如何随时间演变的考虑。你是否同意或不同意这些考虑应该是软件架构定义的一部分?

4. 讨论架构如何作为分析的基础。决策呢?架构授权进行什么样的决策?

5. 架构在降低项目风险中的作用是什么?

6. 找到一个关于系统架构的公认定义,并讨论它与软件架构有什么共同之处。对企业架构也做同样的事情。

7. 找到一个已发布的架构示例。展示了哪种或哪些结构?鉴于其目的,应该展示哪种或哪些结构?架构支持什么样的分析?批判它:你有哪些问题是该表述没有回答的?

8. 帆船有架构,这意味着它们有“结构”来推理船的性能和其他质量属性。查找barque, brig, cutter, frigate, ketch, schooner和sloop的技术定义。提出一套有用的“结构”来区分和推理船舶的架构。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值