软件架构的思想和特征

主要思想:

  • 软件架构是一个软件系统的设计图,并不仅限于软件系统的总体结构,还包含一些质量属性以及功能与结构之间的映射关系,即设计决策。
  • 软件架构的两个主要焦点集中于系统的总体结构以及需求和实现之间的对应。
  • 软件架构的主要思想是将注意力集中在系统
    总体结构的组织上
  • 软件架构思想的实现:运用抽象方法屏蔽错综复杂的模块间连接,使人们的认知提升并保持在整体结构的部件“交互”层次;进一步将交互从计算中分离出来,建立“组件+连接件+配置”的软件系统高层结构组织方式。

特征:
| 特征 | 实现方式 | 作用 |
| :—-: | :—-: | :—-: |
|注重可用性|组件及架构及重用|提高软件质量|
|利益相关者较多|满足各利益相关者需求|简化复杂性|
|关注者较多|分而治之、模块化|简化复杂性|
|质量驱动|使用软件架构来处理质量属性需求、控制复杂性|由功能、数据流驱动向质量驱动转变|
|概念完整性|强调设计决策是一个持续的过程|每个决策都要在前面设计决策的基础上进行|
|循环风格|架构风格、架构模式|用标准方法来处理反复出现的情况|

软件架构定义

组成派定义:

  • 关注软件本身,将软件架构看作组件交互的集合
  • 软件架构主要反映系统由哪些部分组成,以及这些部分是如何组成的,强调软件系统的整体结构和配置
  • MaryShaw定义软件架构包括组件、连接件、约束三大要素。组件可以是一组代码,也可以是独立的程序;连接件可以是过程调用、管道和消息等,用于表示组件之间的相互关系;约束一般为组件连接时的条件。
    决策派定义:
  • 关注于软件架构中的实体(人),将软件架构视为一系列重要决策的集合
  • 软件设计实际上是开发人员意志和决策在软件开发过程中的体现,软件架构更是高层领导和架构师意志和决策的体现,强调设计决策,更加注重架构风格和模式的选择
  • 组件:具有某种功能的可重用的软件模块单元
  • 连接件:组件之间的交互,eg:管道、过程调用、事件广播、客户-服务器通信协议、数据库和应用之间的SQL连接
  • 配置:表示了组件和连接件的拓扑逻辑的约束
  • 端口:组件的接口由一组端口组成,每个端口表示了组件和外部环境的交汇点。组件作为封装实体,只能通过端口与外部交互。通过不同的端口类型,一个组件可以提高多重接口。端口eg:过程调用、通信协议

组成派和决策派定义的区别:

  • 关注点不同:软件系统的静态结构和动态交互vs架构师在设计过程中做出的关键决策 ; 系统的结构和组成方式,强调客观描述vs架构的设计过程和权衡,强调主管判断
  • 视角不同:从软件客体,描述系统是什么vs从架构师主体,描述如何设计系统
  • 涵盖范围不同:聚焦技术结构v涵盖技术决策、非功能需求、业务目标
  • 应用场景不同:用于架构描述,理解系统结构VS适用于架构设计过程,理解为什么选择某种风格

软件架构模型

软件架构建模是对架构设计决策的具体化和文档化。
软件架构建模的意义在于它能够将团建架构某些关键或关注的方面剥离出来,使用同一的图形、文档和数据进行描述,达到直观、便捷地理解、分析和交流。

软件架构模型的五类方法(优缺点):

  • 基于非规范图形表示的建模方法:将软件架构按照图形的方式进行表达,正式/非正式两类
  • 基于UML的方法:
    UML定义了一组丰富的模型元素以及建模组件、接口、关系和约束。可视化建模语言。用例图:帮助理解系统功能需求,显示若干角色以及这些角色与系统提供的用例之间的连接关系。代表了系统的外部视图。
    类图:系统中的类和类与类之间的关系,是对系统静态架构的描述。
    对象图:某个时间点系统中对象的快照。实例图。
    状态图:描述类的对象所有可能的状态以及事件发生时状态的转移条件。通常,状态图是对类图的补充。擅长描述对象在多个用例中的行为。
    协作图:交互图,强调发送和接收消息的对象之间的结构组织
    顺序图:按照交互发生顺序,显示对象之间的这些交互,反映若干对象间的动态协作关系。
    活动图:满足用例要求所要进行的活动以及活动间的约束关系
    包图:系统中的每个元素都只能为一个包所有,一个包可嵌套在另一个包中。使用包图可以将相关元素归入一个系统。
    组件图:描述代码构件的物理结构以及各构件之间的以来关系。将系统划分为组件并希望通过接口或组件细分为较低级别的结构来显示其相互关系。
    部署图:软件与硬件组件之间的物理关系以及处理节点的组件分布情况。可以显示运行时系统的结构,传达应用程序的配件和软件元素的配置和部署方式。
    复合结构:
    交互概述图:活动图和序列图的结合
    时序图:交互图的另一种形式。重点在于时序约束。显示不同对象的状态变换之间的时序约束。
    |架构元素|UML模型元素|
    |:—-:|:—-:|
    |组件|分类器(如类、组件、用例等)|
    |接口|接口|
    |关系(连接器)|关系(泛化、依赖、关联等)|
    |约束(规则)|规则|
    利用UML对架构进行建模的三种途径:(1)将UML看作是一种软件架构描述语言直接对架构建模。简单易行,但有些UML结构无法和架构的概念直接对应 (2)通过扩展机制约束UML的元模型以支持软件架构建模的需要。不改变现有语法语义,可用标准的UML工具进行约束,然而对OCL约束进行检查的工具还不是很多 (3)对UML的元模型进行扩充。增加架构建模元素,使其直接支持软件架构的概念。优点:使UML中包含各种ADL所具有的优良特性,并且具有直接软件架构建模的能力。缺点:扩展的概念不符合UML标准,与UML工具不兼容
    优点:统一的标准便于理解和交流;多视图从不同角度刻画软件架构,用于分析、设计和实现;利用模型操作工具可缩短开发周期提升效率;统一的方法有利于维护开发元素的可处理性,避免错误
    缺点:对架构的构造性建模不强,缺乏对架构风格和显式连接件的直接支持;语义的精确性不足;多视图产生信息冗余和不一致;非形式化层次,不能保证软件开发过程的可靠性,不能充分表现软件架构的本质
  • 基于形式化的方法:利用一些已知特性的数学抽象来为目标软件系统的状态特征和行为特征构造模型。Z语言,基于一阶谓词逻辑和集合论的形式规格说明语言;Petri网,一种系统的数学和图形的建模和分析工具(组件,连接件,角色,约束);B语言,VDM,CSP
  • 基于UML形式化的方法:利用形式化与UML结合的建模方法研究成果,对UML图形赋予形式化语义
  • 其他建模方法(文本语言、MDA):文本语言建模,通过文本文件描述架构,优点:单个文档描述整体架构,方便用户与文本文档的交互;文本文档的句法分析和检查方便;许多编辑器附带额外的开发支持工具;缺点:类图形结构不易理解;难以以另外的形式组织文本;MDA,模型驱动架构,以模型为中心

4+1模型

  • 逻辑视图:支持行为要求,描述系统各部分的抽象描述。用于建模系统的组成部分以及各组成部分之间的交互方式。类图、对象图、状态图和协作图。
  • 过程视图:解决并发和分发,描述系统中的进程。活动图、顺序图
  • 开发视图:组织软件模块,库,子系统,开发单元。描述系统各部分如何被组织为模块和组件。包图和组件图。管理系统体系结构中的层。
  • 物理视图:将其他元素映射到处理和通信节点。描述前三个视图中所述的系统设计实现为一组现实世界的实体。部署图,展示抽象部分如何映射到最终部署的系统中。
  • 用例视图:将其他视图映射到重要的用例(场景)上对体系结构加以说明。用例图,描述和概述图,从外部世界的角度描述正在建模的系统的功能。需要使用此时图来描述系统应该执行的操作。所有其他视图都依靠用例视图来指导。

软件架构风格

软件架构风格是描述某一特定应用领域中系统组织方式的惯用模式,作为“可复用的组织模式和习语”,为设计人员的交流提供了公共的术语空间,促进了设计复用与代码复用。
架构风格的基本属性:

  • 设计元素的词汇表
  • 配置规则
  • 元素组合的语义解释以及使用某种风格构建的系统的相关分析

使用架构风格的优势:

  • 促进设计和代码的重用性,使系统的组织结构易被理解
  • 使用标准的架构风格支持系统内部的互操作性以及针对特定风格的分析

数据流风格

特点:数据的可用性决定着处理是否被执行;系统结构由数据在各处理之间的有序移动决定;在纯数据流系统中,处理之间除了数据交换没有任何其他的交互
基本组件:数据处理单元
组件的端口:输入端口、输出端口
组件的计算模型:从输入端口读数,经过处理,然后写到输出端口
连接件:数据流ji
接口抉择:reader和writer

  1. 批处理
    基本组件:独立的应用程序
    连接件:某种类型的介质,完整的数据
    特点:近乎线性;每个处理步骤是一个独立的程序;每一步在前一步结束后才开始;数据必须是完整的,以整体的方式传播
    实例:基于eclipse的代码重复检测工具
  2. 管道过滤器
    应用场景:数据源源不断产生,系统需要对这些数据进行若干处理
    基本组件:过滤器(功能模块)
    连接件:管道(数据流)

过滤器作用:将源数据变换为目标数据
过滤器特性:独立性,完成自身功能,相互之间无需状态交互;过滤器自身无状态;对上下游过滤器“无知”
管道:将数据从一个过滤器的输出口转移到另一个过滤器的输入口;单向流动;可以有缓冲区
特点:结果的正确性不依赖于各个过滤器允许的先后次序
优点:每个组件行为不受其他组件的影响,整个系统的行为易于理解,软件组件具有良好的隐蔽性和高内聚低耦合;支持功能模块的复用;具有较强的可维护性和可扩展性;支持一些特定的分析,如吞吐量计算和死锁检测等;具有并发性
缺点:往往导致系统处理过程的成批操作;需进行加密/解析/泛解析,增加了过滤器具体实现的复杂性,系统性能不高;交互式处理能力弱
实例:Unix/Dos中的管道命令;传统的编译器
|批处理|管道过滤器|
|:—-:|:—-:|
|整体传递数据|增量|
|构件粒度较大|构件粒度较小|
|延迟高、实时性差|实时性好|
|无并发|可并发|
数据流应用:编译器;Unix管道;图像处理;声音与图像处理

主程序/子程序风格

从功能的观点设计系统,逐层分解和逐步细化得到系统架构,将大系统分解为若干模块,主程序调用这些模块实现完整的系统功能
组件:主程序、子程序
连接件:调用- 返回机制
约束:单线程
拓扑结构:层次化结构
应用场景:适用于可通过过程定义层次结构恰当描述计算逻辑的应用场景
优点:结构化程序设计,逻辑清晰易理解;模块化
缺点:对数据存储格式的变化将会几乎影响所有模块;规模变大时难理解、难测试、难维护;难以支持有效的复用

面向对象风格

特点:对象负责维护其表示的完整性;对象的表示对其他对象而言是隐蔽的
适用场景:核心问题设计识别和保护相关信息体
组件:管理器(如服务器、对象、抽象数据类型)
连接件:过程调用
约束:去中心化;通常为单线程

优点:可以在不影响其他对象的情况下改变对象的实现,简单、方便,安全可靠;设计者可将一些数据存取操作的问题分解成一些交互的代理程序的集合
缺点:管理大量对象;管理复杂交互;行为职责分散;捕获相关设计族

层次结构

系统被组织成若干个层次,每个层次由一系列组件组成;层次之间存在接口,通过接口形策调用返回的关系——下层组件向上层组件提供服务,上层组件被看作是下层组件的客户端
大多数分层架构由四个标准层组成:表现层、业务层、持久层、数据库层
应用场景:涉及可分层组织的不同服务类别的应用场景
组件:组合体,多为过程集合
连接件:取决于组件集合,通常为受限可见性下的过程调用
约束:单线程
特点:每层只能见到与自己邻接的层;大问题分解为若干小问题,隐藏了复杂度;修改一层,最多影响两层,而通常只影响上层,接口稳固则谁都不影响;上层必须知道下层的身份,不能调整层次之间的顺序
优点:支持基于可增加抽象层的涉及;支持扩展;支持重用
缺点:不是所有系统都容易用这种模式构建;定义一个合适的抽象层次可能会非常困难;层层相调,影响性能
应用实例:http分层通信协议

客户机/服务器风格(C/S风格)

客户机:业务逻辑、与服务器通讯的接口
服务器:与客户机通讯的接口、业务逻辑、数据管理
客户机为完成特定的工作向服务器发出请求;服务器处理客户机的请求并返回结果;
客户机程序和服务器程序配置在同一台计算机上时,采用消息,共享存储区和信号量等方法实现通信连接;配置在分布式环节中时,通过远程调用RPC协议来进行通信

两层C/S架构
多用户-内网/外网-数据库服务器
优点:客户机组件和服务器组件分别运行在不同的计算机上,有利于分布式数据的组织和处理;组件之间的位置是相互透明的;客户机程序和服务器程序可运行在不同的操作系统上,便于实现异构环境和多种不同开发技术的统合;软件环境和配件环境的配置具有极大的灵活性,易于系统功能的扩展;将大规模的业务逻辑分不到多个通过网络连接的低成本的计算机上,降低了系统的整体开销
缺点:开发成本高;客户机程序的设计复杂度大;客户负荷重;信息内容和形式单一;C/S架构升级需要开发人员到现场更新客户机程序,对运行环境进行重新配置,增加了维护费用;两层C/S结构采用了单一的服务器,同时以局域网为中心,难以扩展到internet;数据安全性不高,客户端程序可以直接访问数据库服务器

三层C/S架构
多用户-外网/内网-应用服务器-数据库服务器
优点:逻辑结构更清晰,提高可维护性和可扩展性;更有效地选择运行的平台和硬件环境,从而使每一层都具有清晰的逻辑结构、良好的符合处理能力和较好的开放性;可以分别选择合适的编程语言并行开发;系统具有较高的安全性

注意:
如果各层之间的通信效率不高,即使每一层的硬件配置都很高,系统的整体性能也不会太高;必须慎重考虑三层之间的通信方法、通信频率和传输数据量

浏览器/服务器风格(B/S风格)

是三层C/S风格的一种实现方式,主要包括浏览器,Web服务器和数据库服务器
多客户端浏览器-外网/内网-Web服务器-数据库服务器
在客户机上采用了WWW浏览器,将Web服务器作为应用服务器
核心是Web服务器,数据请求、网页生成、数据库访问和应用程序执行全都有Web服务器来完成;系统安装、修改和维护全在服务器端解决,客户端无任何业务逻辑
优点:客户端只需要安装浏览器,操作简单能够发布动态信息和静态信息;运用HTTP标准统一协议和统一客户端软件,能够实现跨平台通信;开发成本比较低,只需要维护Web服务器程序和中心数据库。客户端升级可以通过升级浏览器实现
缺点:个性化程度比较低;客户端数据处理能力比较差,加重了Web服务器的工作负担,影响系统整体性能;数据提交一般以页面为单位,动态交互性不强,不利于在线处理事务;可扩展性比较差,系统安全性难以保障;B/S架构的应用系统查询中心数据库,其速度要远低于C/S架构
目前B/S开发常用的一个技术框架

  • 前端开发框架:Vue.js
  • 后端开发框架:Spring Boot
  • 数据区:MySQL
  • 缓存:Redis

仓库风格

仓库是存储和维护数据的中心场所
组件:中心数据结构组件,表示当前数据的状态;相对独立的组件集合,各个功能模块
连接件:数据仓库与独立组件之间的交互。如果由输入流中事务触发系统相应的进程执行,这种知识库是传统的数据库型知识库;如果由中心数据结构的当前状态触发系统相应的进程执行,这种知识库称为黑板知识库
应用场景:应用于核心问题是建立、扩充和维护一个复杂的中央信息体的情况
典型应用:数据处理,主要需要用传统的数据库来搭建业务决策系统;软件开发环境,主要表示和操作相关的程序和设计
优点:便于模块间的数据共享;方便模块的添加、更新和删除;避免了知识源的不必要的重复存储等;
缺点:对于各个模块,需要一定的同步/加锁机制保证数据结构的完整性和一致性
应用实例:现代编译器;基于仓库风格的软件研发环境eclipse;版本控制系统git

黑板风格

一个大问题被分解为若干个子问题;每个子问题的解决需要不同的问题表达方式和求解模型,分别涉及求解程序;每个求解程序具有某一特定领域知识;这些程序是相互独立的;根据求解过程中的状态来动态决定各个专门程序之间的操作顺序,它们之间通过协同工作共同完成整个问题的求解;专门的控制程序负责根据问题求解的状态来调用最恰当的求解程序,从而形成一种随机性的执行次序
黑板系统是传统上被用于信号处理方面进行复杂解释的应用程序,以及松散耦合的组件访问共享数据的应用程序。
黑板架构实现的基本出发点是已经存在一个对公共数据结构进行协同操作的独立程序集合。
例如,自然语言处理、语音处理、模式识别、图像处理
组成部分:知识源、黑板数据结构、控制器
控制器监视黑板状态激活对应的知识源,知识源读取更新知识,对黑板进行修改,逐渐找到问题的解
个知识源之间的通讯和交互只通过黑板进行
全局数据库用来存储数据、传递信息,包含解域的全部状态;解决问题过程中的状态数据,以层次形式组织起来

知识源:是描述某个独立领域问题的知识及其处理方法的知识库;知识源分别存放且相互独立;通过黑板进行通信,合作求出问题的解;具有“条件-动作”的形式。当条件满足时,知识源被触发,其动作部分增加或修改黑板上的内容
控制器:时刻监视黑板状态变化;对黑板上信息的当前状态进行判断和评价;当黑板的状态满足了知识源的执行条件时,该知识源被控制器触发并进行计算,然后将结果更新到黑板上;这种更新又导致其他知识源参与计算并更新黑板,知道找到问题解为止

优点:便于多客户共享大量数据;便于添加新的作为知识源代理的应用程序,也便于扩展共享的黑板数据结构;知识源可重用;支持容错性俄健壮性
缺点:不同知识源代理对于共享数据结构要达成一致,而且,这也造成对黑板数据结构的修改较为困难——要考虑到各个代理的调用;需要一定的同步/加锁机制保证数据结构的完整性和一致性,增大了系统复杂度。
应用实例:语音识别系统

解释器风格

解释器是一个用来执行其他程序的程序,它针对不同硬件平台实现了一个虚拟机,将高抽象层次的程序翻译为低抽象层次所能理解的指令,以弥合程序语义所期望的与硬件提供的计算引擎之间的差距,
源代码->解释器->宿主系统
优点:有利于实现程序的可移植性和语言的跨平台能力;可以对未来的硬件进行模拟和仿真,降低测试的复杂性和昂贵花费
缺点:额外的间接层次导致了系统性能的下降
应用实例:JVM

解释器对比编译器
编译器不会执行输入的源码,而是将其翻译为另一种语言,通常是可执行的机器码或目标码,并输出到文件中以便随后链接为可执行文件并加以执行。编译-链接-执行
在解释器中,程序源代码被解释器直接加以执行。解释执行
解释器的三种策略:

  1. 传统解释器:纯粹的解释执行,直接读取源代码并加以执行
  2. 基于字节码的解释器:编译-解释执行,源码首先被编译为字节码,再被解释器加以解释。字节码并不是真正的机器目标代码,与硬件平台无关。源码-编译器-字节码-解释器-宿主系统
  3. JIT解释器:编译||解释执行。字节码在运行时被编译为本机的目标代码,当字节码被执行时,运行环境下的编译器将其翻译为本地机器码。源码-编译器-字节码-解释器||编译器目标码-宿主系统

基于规则的系统风格

把业务逻辑抽取出来形成独立的规则库。系统运行时,读取规则库,依据当前运行状态,从规则库中选择与之匹配的规则,对规则进行解释,根据结果控制系统运行的流程。
业务逻辑=固定业务逻辑+可变业务逻辑(规则)+规则引擎
基于规则的系统:一个适用模式匹配搜素来寻找规则并在正确的时候应用正确的逻辑知识的虚拟机。将知识表示为“条件+行为”的规则,当满足条件时触发相应的行为。
基本思想:将业务逻辑中可能频繁发生变化的代码从源码中分离出来
基本过程:使用规则定义语言(如XML)将这些变化部分定义为规则; 在程序运行时,规则引擎根据程序执行的当前状态,判断需要调用并执行哪些规则,进而通过“解释器”的方式来解释执行这些规则。◦ 其它直接写在源代码中的程序,仍然通过传统的“编译”或“解释”的办法加以执行。
规则的表达形式:两个部分,IF部分(规则的前提或条件)THEN部分(规则的结论或触发的行为),一个规则可以有多个条件,使用AND或OR连接
应用实例:基于规则的专家系统

优点:降低了修改业务逻辑的成本;缩短了开发时间;将规则外部化,可在多个应用之间共享;对规则的改变将非常迅速并且具有较低的风险。
|基于规则的系统|解释器|
|:—|:—|
|知识库(规则库)|带解释的程序|
|规则解释器|解释器引擎|
|规则与数据元素选择|解释器引擎内部的控制状态|
|工作内存|程序当前的运行状态|

基于规则的系统 解释器风格的系统
相同点 都是通过“解释器”(规则引擎),在两个不同的抽象层次之间建立一种虚拟的环境
不同点 在自然语言/XML的规则和高级语言的程序源代码之间建立虚拟机环境 在高级语言程序源代码和OS/硬件平台之间建立虚拟机环境

事件驱动风格

组件通过发布/订阅事件隐式交互,发送者不依赖接收者的存在或响应
消息:具有特定含义的数据,对象通过发送的方式请求另一对象为其服务
事件:能够激活对象功能的动作。当发生这种动作后将给所涉及对象发送一个消息,对象便可执行相应的功能。可以被系统识别的、发生在界面上的用户动作或状态变化
基本思想:组件不直接调用一个过程,而是发布或广播一个或多个事件;系统中的其他组件通过注册与一个事件关联起来的过程,来表示对某一关事件感兴趣,当这个事件发生时,系统本身会调用所有注册了这个事件的过程。
|功能|描述|
|:—|:—|
|分离的交互|事件发布者并不会意识到订阅者的存在|
|多对多通信|采用发布/订阅消息传递,一个特定事件可以影响多个订阅者|
|基于事件的触发器|控制流由接收者确定(基于发布的事件)|
|异步|通过事件消息传递支持异步操作|

特点:事件的触发者并不知道哪些构件会被事件影响,相互保持独立。
事件调度策略:
事件分派模块的功能:复杂接收到来的事件并派遣它们到其他模块
两种策略:广播式,派遣模块将事件广播到所有的模块,但只有感兴趣的模块才会取事件并触发自身的行为;选择式广播,派遣模块将事件送到那些已经注册了的模块中。

点对点的选择广播式(消息队列):系统安装并配置一个队列管理器,并定义一个命名的消息队列;某个应用向消息队列注册,以监听并处理被放置在队列里的事件;其他的应用连接到该队列并向其中发布事件;队列管理器存储这些消息,知道接收端的应用连接到队列,取回这些消息并加以处理;信息只能够被唯一的消费者所消费,消费之后立即从队列中删除

发布-订阅的选择广播式:事件发布者向“主题”发布事件,订阅者向主题订阅事件,一个事件可以被多个订阅者消费;事件在发送给订阅者之后,并不会马上从主题中删除,主题会在事件过期之后自动将其删除

应用实例:Field、Win32 GUI程序

优点:组件低耦合。一个组件出错不会影响其他组件;提高软件复用能力,只要在系统事件中注册组件的过程,就可以将该组件集成到系统中;系统便于升级
缺点:组件放弃了对计算的控制器,完全由系统来决定;存在数据交换问题;正确性验证存在问题

C2风格

层次体系架构风格 基于组件和消息的架构风格,适用于GUI软件开发,构件灵活和可扩展的应用系统
通过连接件绑定在一起的按照一组规则运作的并行组件网络。
该规则规定了所有组件之间的交互必须通过异步消息机制来实现
系统组织规则:
组件之间不能直接连接
组件和连接件都有一个顶部一个底部,组件的顶部连接到某连接件的底部,组件的底部连接到某连接件的顶部
一个连接件可以和任意数目的其他组件和连接件连接
当两个连接件进行直接连接时,必须由其中一个的底部到另一个的顶部

连接件的主要职责:消息的路由和广播;消息的过滤

优点:可使用任何编程语言开发组件,组件重用和替换易实现;组件之间相对独立,依赖较小,具有一定扩展能力;组件不需要共享地址空间;可实现多用户和多个系统之间的交互;可使用多个工具及和多种媒体类型,动态更新系统框架结构
缺点:不太适合大规模流式风格系统,以及对数据库使用比较频繁的系统
实例:电能质量报警系统,KLAX游戏

平台/插件风格

插件(plug-in)是一种遵循统一的预定义接口规约编写出来的程序,应用程序在运行时通过接口规约对插件进行调用,以扩展应用程序的功能。本质在于不修改程序主题的情况下对软件功能进行扩展与加强

平台:程序的主题或主框架,完成一个软件系统的核心和基础,分为内核功能:整个软件的重要功能,和插件处理功能:用于扩展平台和管理插件,为插件操纵平台和与插件通信提供标准平台扩展接口。
插件:功能扩展或补充模块。
插件受到的约束是:插件必须能在运行过程中动态地插入平台和从平台中注销,且不影响系统的运行;当在系统中插入插件后,系统的功能得到扩展或升级;多个插件之间、插件和平台之间不会发生冲突

需要定义两个标准接口:
平台扩展接口:完全由平台实现,插件只是调用和使用。实现插件向平台方向的单向通信,插件通过平台扩展接口可获取主框架的各种资源和数据,可包括各种系统句柄,程序内部数据以及内存分配等
插件接口:完全由插件实现,平台只是调用和使用。为平台向插件方向的单向通信,平台通过插件接口调用插件所实现的功能,读取插件处理数据

优点:降低系统各模块之间的互依赖性;系统模块独立开发、部署、维护;根据需求动态的组装、分离系统
缺点:插件是别人开发的可以用到某主程序中的,只服务于该主程序,可重用性差
应用实例:eclipse开发平台

面向Agent风格

用Agent智能体的思维去考虑问题
核心思想:将复杂任务分解为多个自治、协作的智能体,通过交互与协调实现整体目标
Agent组件:能自主运行、具有某种程度的智能以适应环境变化、可以与其他Agent进行交互和通信,具备一定的目标追求能力;自主性、智能性、交互性;
可以是物理实体(机器人)或软件实体(在计算机网络上执行特定任务的程序),通过感知周围环境,采取行动来影响该环境,并基于自身的目标和知识做出决策。
Agent连接件:对复合型组件的连接,该连接能够提供通信、协调、转化、接通等服务。多Agent系统中的连接件并非显示地将两个不同的组件联系起来,不同Agent之间的联系是根据运行时的状态来决定的
常见的Agent连接件:
消息传递系统:Agent通过发送和接收消息来交换信息,可异步可同步
黑板系统:Agent可以通过访问一个共享的黑板来读取信息或向其写入信息
代理服务器或中介者:负责转发消息或者帮助Agent发现彼此
发布/订阅模型:允许Agent订阅它们感兴趣的主题,并从其他Agent哪里接收关于这些主题的信息更新
服务接口:Agent可以通过良好的服务接口与环境或其他Agent进行交互

优点:解决复杂问题,特别是对于分布开放异构的软件环境
缺点:通信开销大,多Agent频繁交互可能导致延迟;Agent的设计比较复杂
适用场景:需要处理高度动态和不确定性环境的应用场景,如自动化、电子商务、信息管理、分布式控制系统等

面向方面软件架构风格AOP

AOP增加方面组件,封装系统的横切关注点
系统的方面需求特性或关注点:系统的有些特性和需求是横切与系统的每一个层面中,并融于系统的每一个组件中,如系统中的时间要求、业务逻辑、性能、安全性和错误检测等
应用AOP的主要目的:尽量分离技术问题实现和业务问题实现
允许开发者能够对横切关注点进行模块化设计;能够实现关注分散,将通用需求功能从不相干类之中分离出来;能够实现代码重用
方面:方面是横切关注点的模块化单元。一个方面可以包含与特定行为相关的建议、连接点以及切入点。
建议:指的是方面应该执行的具体动作。可以是在特定事件发生之前、之后或异常抛出时执行的动作
连接点:程序执行过程中的某些点,如方法调用、异常抛出等,在这些点上可以插入调用
切入点:一组连接点的集合,定义了在哪些建议应该被执行的连接点上应用
织入:将方面代码整合到主程序逻辑的过程。织入可以在编译器、加载器或运行时完成。

优点:增强功能独立性;减少代码重复;提高可维护性;简化设计
缺点:有一定学习成本;建议可以改变程序流而不需要之间修改源代码,可能会增加调试难度;存在潜在的性能开销,特别是在运行时织入方面时

面向服务架构风格SOA

SOA时一个组件模型,它将应用程序的不同功能单元(服务)通过这些服务之间定义两阿红的接口和契约联系起来
服务是一个粗粒度的、可发现的软件实体
接口是采用中立的方式进行定义的,应独立于实现服务的硬件平台、操作系统和编程语言,便于不同系统中的服务以一种统一和通用的方式进行交互。
服务请求者:服务或者第三方的用户,通过查询服务提供者在服务注册中心发布的服务接口的描述,通过服务接口描述来通过RPC或SOAP进行绑定调用服务提供者所提供的业务或服务
服务提供者:作为服务管理者和创建者,必须将服务米哦啊书的接口发布到服务注册中心才能被潜在的服务请求发现,能够为合适的服务请求者提供服务。
服务注册中心:服务接口的管理中心,服务请求者能够通过查询服务注册中心的数据库来找到需要的服务调用方式和接口描述信息

发布:服务提供者将对服务接口的描述信息发布到服务注册中心上
发现:服务请求者通过查询服务注册中心的数据库找到需要的服务
绑定和调用:服务请求者在查询到所需要服务描述信息,根据这些信息服务请求者能够调用服务。

优点:灵活性,根据需求变化,重新编排服务;对IT资产的复用;使企业的信息化建设真正以业务为核心。业务任意根据需求编排服务,而不必考虑技术细节
缺点:服务的划分很困难;服务编排是否得当;如果选择的接口标准有问题会给系统带来额外开销和不稳定性;对IT硬件资产还谈不上复用;主流实现方式接口很多,很难统一;主流实现方式只局限于不带界面的服务的共享

微服务架构

将单个应用程序开发为一组小型、独立部署的服务的方法。这些服务围绕特定业务功能构建,独立开发,可通过全自动部署机制独立部署,独立扩展。每个小型服务都在自己的进程中允许,并以轻量级机制(HTTP/REST,消息队列等)进行通信
特点:
服务自治,围绕具体业务能力组织系统,高度内聚;每个服务独立开发、部署、扩展,技术栈可异构;各服务拥有专属数据存储
轻量级通信机制:同步通信,HTTP/REST、gRPC;异步通信,消息队列(如Kafka、RabbitMQ)
去中心化治理:服务独立演进,允许团队自治;基础设施通过统一平台管理
容错和弹性设计:通过熔断、重试、降级等机制保障系统可用性和稳定性

优点:加速开发周期;技术多样性;弹性扩展;容错、易维护
缺点:分布式系统的复杂性,需处理网络延迟、分区容错、数据一致性等问题;运维成本高,需要更多的监控和管理工具来跟踪多个服务的状态和性能;团队协作需要严格规范接口定义
适用场景:大型复杂系统(长期演进和多团队协作)、高并发需求(独立扩展关键业务)、需快速创新业务(频繁试错快速交付)

SOA 微服务
服务粒度 更粗粒度 小,单一业务功能
通信机制 依赖企业服务总线ESB 轻量级协议,消息队列
数据管理 偏共享数据资源 数据库私有化
部署扩展 较难实现独立部署和扩展 独立部署、独立扩展
技术多样 理论支持 实际支持

基于层次消息总线的架构风格(JB/HMB风格)

JB/HMB基于层次消息总线、支持组件的分布和并发,组件之间通过消息总线进行通讯
消息总线是系统的连接件,负责消息的分派、传递和过滤以及处理结果的返回
各个组件挂接在消息总线上,向总线登记感兴趣的消息类型。
不要求各个构件具有相同的地址空间或局限在同台机器上,可较好地描述分布式并发系统

优点:模块化与可维护性;灵活、可扩展;支持异步通信,提高系统响应能力和吞吐量;松耦合和异步通信,增强系统的容错能力
缺点:消息总线本身比较复杂,在高并发场景下可能成为系统的瓶颈;调试和定位问题更加复杂;消息传递和总线管理会引入一定性能开销;消息传递的一致性和可靠性如何保证

正交架构风格

由组织层和线索的组件构成
层是一组具有相同抽象级别的组件构成
线索是子系统的特例,它是由完成不同层次功能的组件组成,每一条线索完成整个系统中相对独立的一部分功能
如果线索是相互独立的,即不同线索中的组件之间没有相互调用,那么这个结构就是完全正交的。
正交软件架构是一种以垂直线索组件族为基础的层次化结构。
基本思想:把系统应用的结构按功能的正交相关性,垂直分割为若干个线索,线索又分为几个层次,每个线索由多个具有不同层次功能和不同抽象级别的组件构成。
特点:由完成不同功能的n个线索组成;系统具有m个不同抽象级别的层;线索之间是相互独立的;系统有一个公共驱动层(最高层)和公共数据结构(最低层)

优点:结构清晰、易于理解;易修改、可维护性强;可移植性强、重用粒度大
缺点:并不是所有软件系统都能完全正交化或成本太高。必须权衡正交化的开销与得到的性能之间的关系

异构风格

异构风格是几种风格的组合,组合方式可能有如下几种:

  1. 使用层次架构。一个系统组件被组织成某种架构风格,但它的内部结构可能是另一种完全不同的风格。
  2. 允许单一组件使用复合的连接件

优点:可以实现遗留代码的重用;在某一单位中,规定了共享软件包和某些标准,但仍会存在解释和表示习惯上的不同。选择异构架构风格,可以解决这一问题。
缺点:不同风格之间的兼容问题有时很难解决

实例:

  1. B/S结构和C/S结构组合——“内外有别”模型
    对外用B/S(浏览器访问,方便广域网用户)
    对内用C/S(客户端软件,保障性能和安全性)
    典型场景:企业ERP系统
    外部供应商:通过网页浏览器(B/S)提交订单、查询物流
    优点:无需安装,手机电脑都能用
    内部员工:用安装的客户端软件(C/S)处理财务、库存
    优点:响应快,支持复杂操作(如批量导入Excel)
  2. B/S结构和C/S结构组合——“查改有别”模型
    查询类操作用B/S(轻量级访问)
    修改类操作用C/S(需要高安全性和稳定性)
    典型场景:医院信息系统
    患者/家属:通过网页(B/S)查报告、预约挂号
    优点:随时随地访问
    医生/护士:用桌面客户端(C/S)开处方、修改病历
    优点:防误操作,支持指纹/CA证书认证

模型-视图-控制器风格MVC

MVC结构主要包括模型、视图和控制器三部分。
(1)模型(Model, M):模型是应用程序的核心,它封装了问题的核心数据、逻辑关系和计算功能,提供了处理问题的操作过程。
(2)视图(View, V):视图是模型的表示,提供了交互界面,为用户显示模型信息。
(3)控制器(Controller, C):控制器负责处理用户与系统之间的交互,为用户提供操
作接口。

优点:多个视图与一个模型相对应。变化——传播机制确保了所有相关视图都能够及时地获
取模型变化信息,从而使所有视图和控制器同步,便于维护;具有良好的移植性;系统被分割为三个独立的部分,当功能发生变化时,改变其中的一个部分就能满足要求
缺点:增加了系统设计和运行复杂性;视图与控制器连接过于紧密,妨碍了二者的独立重用;视图访问模型的效率比较低;频繁访问未变化的数据,也将降低系
统的性能

敏捷开发的基本理念

个体和互动优于过程和工具
可运行的软件胜过详尽的文档
客户合作胜过合同谈判
响应变化胜过遵循计划

敏捷开发在实践中表现为一种迭代、增量和持续集成的开发方法

敏捷开发与架构设计的关系

  • 软件架构与敏捷开发的出发点是一致的,都是一个权衡的过程,目的都是为了提高软件开发效率、提高软件质量、降低软件成本,将开发团队的价值最大化。
  • 敏捷开发也需要重视软件架构
  • 敏捷开发改变了软件架构的设计方式。敏捷思想中将传统的架构设计分成:种子架构设计+详细架构设计。架构设计分散在敏捷软件开发过程中,提高效率、减少风险。

敏捷开发中如何改变了软件架构的设计方式

敏捷开发非常重视软件的架构设计,但是轻架构的详细设计
敏捷思想中将传统的架构设计分成:种子架构设计+详细架构设计
分离后,敏捷软件种子架构的内容包括:软件的架构层次,重要模块、重要类的说明
敏捷开发把传统软件开发前期的详细架构设计,分散到了整个敏捷开发软件过程中,以达到提高效率、减少风险的目的。
需求分析:
敏捷开发中的需求分析引入了架构设计的理念,分为初始阶段需求分析和迭代阶段需求分析。初始阶段的需求分析中摒弃了具体的细节,仅仅抓住软件最高层的概念。迭代阶段需求分析是随着项目的进展逐步完善的,具有高适应性。
初始设计:
初始阶段的目标是在所有涉众之间达成关于项目的生命周期目标的协议,在项目进行之前确定重要的业务和需求风险初始设计需要对软件系统的设计进行全局抽象层次上的考虑
包括系统的基本处理流程、系统的组织结构、模块划分、功能分配等
迭代过程
针对需求的不可预见性,在敏捷开发中使用了迭代过程。
长期的计划通常是不稳定的,单次迭代的短期计划是稳定的。
迭代开发都是基于上次迭代的结果,每次迭代都有一个坚实的基础。

敏捷的思想在软件架构设计中最主要的体现就是团队设计和简单设计这两种设计理念
团队设计
团队设计的理论依据是群体决策,这样可以避免理论上完美,但程序员无法实现的架构
设计。
方式:
全体人员参与架构设计
组织优秀的开发人员组成设计组
这样设计出来的架构称为原始架构,在后续的迭代过程中不断地反馈和改进
优点:其结论要比个人决策更加完整,避免个人遗漏,相对稳定、周密。
缺点:需要额外付出沟通成本、决策效率低、责任不明确等

简单设计
敏捷的思想要求软件架构设计必须是简单设计。
这里的简单体现在两个方面:表达方式的简单化和现实抽象的简单化。
表达方式的简单化:指的是敏捷开发中对详细架构描述文档等中间产物的弱化,只满足有效沟通即可。
现实抽象的简单化:指的是仅针对当前需求建模分析,不做“多余的”工作。
简单设计可以降低开发成本、提升沟通效率、增强适应性和稳定性。

两类常见敏捷软件架构设计方法

规划式设计和演进式设计,具体体现为初始阶段设计和迭代过程中的设计

初始阶段输出了一个软件系统的原始架构,然后通过迭代过程进行完善。
迭代将致力于重用、修改、增强目前的架构,以使架构越来越强壮。

架构设计人员 架构表现方式 架构设计人员 架构表现方式 迭代设计周期
极限编程XP 全体开发人员 系统隐喻 全体开发人员(以结对编程的2人为单位) 用户故事(隐喻) 1-3周
Scrum Scrum Master 产品backlog Scrum Master和全体开发人员 Spring backlog 2-4周
特征驱动软件开发 主设计师 特征表 主程序员 设计包 2周

成功的软件架构应具有的品质

  • 良好的模块化
  • 适应功能需求的变化,适应技术的变化
  • 对系统的动态运行有良好的规划
  • 对数据良好的规划
  • 明确、灵活的部署规划

基于体系结构的软件设计方法ABSD

基于体系结构的软件设计方法为软件系统的概念体系结构提供构造方法,概念体系结构描述了系统的主要设计元素及其关系
概念体系结构代表了在开发过程中作出的第一个选择,它是达到系统质量和业务目标的关键,为达到预定功能提供了基础
三个基础
功能分解:ABSD使用已有的基于模块的内聚和耦合技术
通过选择体系结构风格来实现质量和业务需求
软件模板的使用:利用一些软件系统的结构
目的
组织最早的设计策略,不包括形成实际的软件构件和类,但要作出有关功能划分和达到不同质量属性机制的决策。
ABSD是一个递归细化的方法,软件系统的体系结构通过该方法得到细化,知道能产生构件和类
步骤
架构需求-架构设计-架构文档化-架构复审-架构实现-架构演化

需求与架构的协同演化

软件需求和软件架构两者式相辅相成的关系,一方面软件需求影响软件架构设计,另一方面软件架构帮助需求分析的明确和细化。
需求与架构的互相影响可以看成一个螺旋的过程,也是一个双峰的过程。
双峰模型强调软件需求和软件架构的平等性,它是简化版的螺旋模型,在发展需求和架构规约同时,继续从解决方案的结构和规约中分离问题的结构和规约,在一个反复的过程中,产生更详细的需求规约和设计规约,最终把交织在软件开发过程中的设计规约和需求规约分离开来。

将软件架构映射到详细设计经常遇到什么问题?如何解决?

从设计阶段的软件架构模型向代码的转换过程,是将设计阶段的软件架构模型逐步精化的过程。
经常出现的问题:

  • 缺失重要架构视图,片面强调功能需求
  • 不够深入,架构设计方案过于笼统,基本还停留在概念性架构的层面,没有提供明确的技术蓝图
  • 名不副实的分层架构,缺失层次之间的交互接口和交互机制,只进行职责划分
  • 在某些方面过度设计

可能的解决方法

  • 针对一楼的架构视图进行设计
  • 将设计决策细化到技术相关的层面
  • 明确各层之间的交互接口和交互机制
  • 切忌过度设计

MDA的基本思想、过程,应用MDA的好处

MDA基于模型驱动软件架构的映射方法
区分了三类模型:
计算无关模型CIM:也称业务模型,描述系统的外部行为和运行环境
平台无关模型PIM:具有高抽象层次、无关于任何实现技术的模型
平台特定模型PSM;为某种特定实现技术量身定做
开发步骤:

  1. 用计算无关模型CIM捕获需求
  2. 创建平台无关模型PIM
  3. 将PIM转化成为一个或多个平台特定模型PSM,并加入平台特定的规则和代码
  4. 将PSM转化为代码

基本思想:将软件系统分成模型和实现两部分,模型是对系统的描述,实现是利用特定技术在特定平台或环境中对模型的解释。模型仅仅负责对系统的描述,与实现技术无关。

好处:将模型与实现分开后,能够很好的适应技术易变性。由于实现往往高度依赖特定技术和特定平台,当技术发生迁移时,只需针对这种技术作相应的实现,编写相应的运行平台或变换工具。所以,能够比较好的应对实现技术发展带来的挑战

架构设计原则

有一般设计原则和关键设计原则两类,
一般原则:包含商业原则、数据原则、应用程序原则、技术原则等;
关键设计原则:关注点分离、单一职责原则、最少知识原则等

商业原则:
企业利益最大化
信息管理,人人有责
事务持续性
使用通用软件
守法
IT责任
知识产权保护

数据原则:
◦数据资产
◦数据共享
◦数据访问
◦数据托管
◦使用常用词汇、有数据定义
◦数据安全

应用程序原则:
◦ 技术无关性
◦ 易用性
 技术原则:
◦需求变化
◦响应变更管理
◦控制技术多样性
◦互操作性

关注点分离
将程序分解为相对无关的、功能重叠部分尽可能少的一个个模块,达到高内聚和低耦合的目的。
单一职责原则
每个组件或模块应负责一个特定特征或功能,或者内聚功能的集合。
最少知识原则(迪米特法则,LoD)
一个组件或对象应该对其他组件或对象的内部细节尽可能少的了解。
不重复自身原则(DRY):
只须在一个地方指定意图,例如,对于程序设计,特定功能只能在一个组件内实现,且该功能不能复制到任何其他组件内。
尽量减小前期设计
只做必要的设计。

软件架构设计面临的主要威胁及其对策

几个面临威胁的方面

  • 被忽略的重要非功能需求
  • 频繁变换的需求
  • 考虑不全面的架构设计
  • 不及时的架构验证
  • 较高的创造性架构比重
  • 架构的低可执行性

被忽略的重要非功能需求及其对策:
非功能需求大致分为质量属性与约束两大类。
质量属性是软件系统的整体质量品质。如易用性、性能、可伸缩性、持续可用性、健壮性、安全性、可扩展性、可重用性、可移植性、易理解性和易测试性等
约束限制,要么是架构设计中必须遵循的限制,要么转化为质量属性需求或功能需求。
对策:全面认识需求。

频繁变化的需求及其对策:
任何需求变更都可能意味着时间和金钱的消耗,并且大量需求变更之后程序可能变得混乱,势必引起Bug增多,影响产品质量。
对策:关键需求决定架构

考虑不全面的架构设计:
对策:多视图探寻架构

不及时的架构验证及其对策:
对策:尽早验证架构。应真正对早期架构进行编码实现,而不仅仅是评审。要对原型进行测试,重点要确保早期架构考虑的质量属性是否能达到预期。

较高的创造性的架构比重及其对策:
对策:合理分配经验架构与创新架构比重。调查显示,80%经验架构加20%创新架构是比较合理的分配比重。

架构的低可执行性:
要充分考虑经济型、技术复杂性、发展趋势和团队水平等多方面的因素,制定出合适的架构决策。若一味追求架构的完善性、准确性,而忽视其可执行性,将为软件开发过程带来风险
对策:验证架构的可执行性

软件架构评估的必要性

软件架构评估的方式分类

  • 基于问卷调查或检查表的软件架构评估技术
    优点:比较灵活,可评估多种质量属性,也可以在软件体系结构设计的多个阶段进行
    缺点:评估的结果很大程度来自评估人员的主观推断,因此不同的评估人员可能会产生不同甚至截然相反的结果,而且评估人员对领域的熟悉程度、是否具有丰富的相关经验也成为评估结果是否正确的重要因素。

  • 基于场景的软件架构评估技术
    一般采用激励、环境和响应三方面对场景进行描述

  • 基于度量的软件架构评估技术
    要建立质量属性和度量之间的映射原则,即确定如何从度量结果推出系统具有何种质量属性;
    从软件架构文档中获取度量信息;
    根据映射原则分析推导出系统的某些质量属性

基于问卷调查或检查表的软件架构评估技术 基于场景的软件架构评估技术 基于度量的软件架构评估技术
通用性 通用或特定领域 特定领域 通用或特定领域
评估者对待评估架构的掌握程度要求 简单了解 比较熟悉 精确掌握
客观性 主观 比较主观 比较客观
评估时间 早期,中期 中期 后期

质量属性、(质量)场景

软件架构的质量有内部质量、外部质量之分;
一般认为开发态软件架构是软件的静态架构,其质量是内部质量,包含软件架构模型、数据、描述文档和视图的质量等
处于运行和维护演化过程的软件架构,其质量是外部质量,包含基于该软件架构开发的系统的性能、可靠性、安全性等。

讨论软件架构质量问题的意义:
最终软件产品质量问题是当前软件开发发展过程的重要核心关注点之一
问题发现的越早,解决问题的代价越小
软件架构自身存在着很高的质量需求

软件架构典型的内部质量指标有(文档、数据、图表、模型)的可维护性、可重用性、可移植性、可集成性和可测试性等。
可维护性:指软件系统或组件在纠正错误,提升性能或其他属性,以及适应变化的环境的修改容易程度
可重用性:指合理地设计系统使得系统结构或其某些组件能够在未来的应用开发中可以重复使用的能力
可移植性:系统能够在不同计算环境(或平台下)运行的能力
可集成性:使其他独立开发的系统组件能够与待开发系统协同运行的能力
可测试性:指通过测试使软件表露出缺陷的容易程度

软件架构的外部质量是指在软件系统运维过程中,软件系统体现出来的与软件架构有关的质量属性
性能:系统的响应能力,即要经过多少时间才能对某个刺激做出响应,或者在某个时间段内所能处理的事件的个数。性能主要关注:客户端响应时间增加、吞吐量降低以及服务器资源过载使用;内存消耗增加、以及过多的缓存未命中;数据库服务器处理增加;网络带宽消耗增加
可用性:指系统正常运行的时间比例。系统的可用性经常会收到系统错误、基础结构问题、恶意攻击、系统负载等因素的影响。关注如下问题:物理层发生故障或无响应;如果系统不能及时处理由于网路配置或网络阻塞引起的大规模负载,采用拒绝服务、组织授权用户访问系统等中断系统操作;不恰当的资源使用会降低可用性;应用程序中的错误或故障会导致系统范围内的失败;频繁的升级会降低系统的可用性;网络故障或导致应用程序的不可用。需要考虑如果处理不稳定的网络连接;在应用程序中考虑信任边界并保证子系
统采用了一定程度的访问控制或防火墙技术,同时也要考虑外延数据的有效性,来提高系统
的弹性和可用性
可靠性:系统能够保持正常运行的能力。分为两方面:容错,在错误发生时确保系统正确的行为,并进行内部修复;健壮性,保护应用程序不受错误使用和错误输入的影响,在遇到意外错误事件时确保应用系统处于已经定义好的状态
可靠性主要关注如下的问题:系统崩溃或变得没有回应时,探测失效根源并自动启动失效备援,或者将负载转送到备份系统;输出不一致时,通过执行插桩探测性能缺陷根源,并通过系统输出相关信息;由于外部因素(例如网络不可用)导致系统失效时,寻找合适的方式处理不可靠的外部系统、失效的交互以及失效的事务等。
安全性:衡量系统在向合法用户正常提供服务的情况下,阻止企图非授权使用,或者港剧拒绝服务攻击,并阻止系统信息泄露和丢失的能力
安全性主要关注的问题有:
◦ (1)欺骗用户身份
◦ (2)由恶意输入引起的危害
◦ (3)数据篡改
◦ (4)拒绝用户行为
◦ (5)信息泄露及敏感数据丢失
◦ (6)由于DoS攻击导致的服务中断

易用性(Usability)
◦ 易用性包含如下几个方面的意思:
 (1)可学习性
 (2)效率
 (3)可记忆性
 (4)错误避免
 (5)错误处理
 (6)满意度
易用性主要考虑如下的问题:
◦ (1)完成一项任务需要太多的交互(大量的点
击),保证对屏幕输入流程及交互模式的设计最
大限度地提高易用性。

◦ (2)在多步骤的接口中存在不正确的流程步骤,
考虑结合工作流来简化多步骤操作。
◦ (3)数据元素和控制没有很好进行分类,选择合
适的控制类型并采用公认的UI设计模式对控制符
及内容进行设计。
◦ (4)给用户的反馈非常薄弱,特别是在应用程序
发生错误,异常或没有响应的情况下,考虑采用
相关技术最大限度地提高用户交互性。

ATAM评估方法 架构权衡分析方法

基于场景
分析软件体系结构对场景也就是对系统的使用或修改活动的支持程度,从而判断该体系结构对这一场景所代表的质量需求的满足程度
优点:考虑到了所有与系统相关人员对质量的要求;
缺点:不同的应用系统对同一质量属性的理解可能不同,基于场景的评估方式是特定于领域的;这一评估方式的实施者一方面需要有丰富的领域知识以对某以质量需求设计出合理的场景,另一方面,必须对待评估的软件体系结构有一定的了解以准确判断它是否支持场景描述的一系列活动。

目标:理解SA关于软件系统的质量属性需求决策的结果
特点:揭示SA对特定质量目标的满足情况,描述诸多质量目标之间的相互作用和权衡;结构化的评估方法,可重复
基本概念:

  • 敏感点:是一个或多个构件的特征。可以是设计师搞清楚实现质量目标时应该注意什么
  • 权衡点:是影响多个质量属性的特征;是多个质量属性的敏感点;需要进行权衡
  • 敏感点影响一个质量属性,权衡点影响多个质量属性
  • 场景:从风险承担者的角度对与系统的交互的简短描述。一般采用刺激、环境和响应三方面对场景进行描述
  • 刺激是场景中解释或描述风险承担者怎样引发与系统的交互部分。例如,用户可能会激发某个功能,维护人员可能会做某个更改,测试人员可能会执行某种测试等,这些都属于对场景的刺激
  • 环境描述的是刺激发生时的情况。例如,当前系统处于什么状态?有什么特殊的约束条件?系统的负载是否很大?某个网络通道是否出现了阻塞等。
  • 响应是指系统如何通过体系结构对刺激作出反应的。例如,用户所要求的功能是否得到满足?维护人员的修改是否成功?测试人员的测试是否成功等

过程:通常花费三个整天,每天都要进行三个过程,场景提出、架构提出和将场景映射到架构上,并进行分析评估

步骤:

  1. 陈述,包括通过它进行的信息交流。ATAM方法陈述、商业动机的陈述、SA的陈述
  2. 调查与分析,包括对照体系结构方法评估关键质量需求。确定体系结构方法;生成质量属性效用树,说明构成系统效用的质量属性,具体到场景层次,标注刺激/反应,并区分不同的优先级;分析体系结构方法,体系结构风险、非风险、敏感点和权衡点被识别
  3. 测试,包括对照所有相关人员的需求检验最新结果。集体讨论并确定场景优先级;分析体系结构方法
  4. 形成报告,包括陈述ATAM的结果。结果的表述

质量属性效用树
效用(代表系统的整体质量)-二级节点构成质量属性-刺激-响应
效用树为我们提供了一种直接而有效地将系统的业务驱动因素转换为具体的质量属性场景的机制,该步骤的输出结果是对具体质量属性需求(以场景形式实现)的优先级的确定
•构建效用树将质量属性细化为场景
•确定最重要的质量属性目标,并设置优先级
•效用树设置优先级标准
•每个场景对系统成功与否的重要性
•体系结构设计人员所估计的实现这种场景的难度

SAAM评估方法

主要分析体系结构的可修改性;也可以对系统属性及系统功能进行分析
评估方法:描述场景、划分优先级、分析体系结构问题
输入:一组场景
输出:将代表了未来可能做的更改的场景与体系结构对应起来,显示出体系结构中未来可能具有较高复杂度的地方,估计预期工作量;理解系统功能,比较多个体系结构支持的功能数量

优点

  1. 简单易用,适合早期评估
  2. 关注实际业务需求
  3. 支持多利益相关方参与
  4. 可扩展性强
    缺点
  5. 依赖主观判断,缺乏量化指标
  6. 仅适用于特定质量属性
  7. 场景选择影响评估结果
  8. 不适合超大规模系统

SAAM考查的是SA的单独的质量属性,而ATAM提供从多个竞争的质量属性方面来理解SA,使用户能认识到在多个质量属性目标间权衡的必要性。

为什么要进行软件架构度量

软件架构作为软件开发过程中早期阶段的设计模型
如果通过软件架构度量能够预测待开发的软件产品质量,并能够即时地发现早期设计缺陷,这对于减少开发风险和提高最终软件产品质量是非常重要的

  • 从架构出发可以更有效地把握整个软件系统的设计结构和版本更新问题
  • 基于架构的度量可以在设计早期发现架构的不合理之处
  • 基于架构的度量可以对架构的演化程度进行评估和预测
  • 架构度量是一种静态的度量方法,不需要执行软件或者进行仿真,具有成本低、容易实现且不依赖于程序特定的运行环境的优点

架构度量和架构演化的关系

软件架构为什么会发生演化

软件架构演化就是为了维持软件架构自身的有用性
我们在理解软件架构演化的时候,需要考虑具体的软件架构定义
软件架构包括组件(components)、连接件(connectors)和约束(constraints)三大要素,这类软件架构演化主要关注的就是组件、连接件和约束的添加、修改与删除等

软件架构演化的方式

软件架构静态演化:发生在软件架构的设计、实现和维护过程中,软件系统还未运行或者处在运行停止状态;
静态演化需求
(1)设计时演化需求:在架构开发和实现过程中对原有架构进行调整,保证软件实现与架构的一致性以及软件开发过程的顺利进行;
(2)运行前演化需求:软件发布之后由于运行环境的变化,需要对软件进行修改升级,在此期间软件的架构同样要进行演化。
一般过程:
原系统-软件理解-需求变更分析-演化计划-系统重构-系统测试-更新后系统-原系统

软件架构动态演化:发生在软件系统运行过程中
动态演化的需求
(1)软件内部执行所导致的体系结构改变。例如,许多服务器端软件会在客户请求到达时
创建新的组件来响应用户需求
(2)是软件系统外部的请求对软件进行的重配置。例如,操作系统在升级时无须重新启动,在运行过程中就完成对体系结构的修改

内容:
属性改名:对非功能指标进行重新定义,如服务响应时间等
行为变化:在运行过程中,用户需求变化或系统自身服务质量的调节,都将引发软件行为的变化。如:为了提高安全级别而更换加密算法;将http协议改为https协议。
拓扑结构改变:如增、删组件,增、删连接件,改变组件与连接件之间的关联关系等。
风格变化:一般不变,如果非要改变软件的架构风格,也只能将架构风格变为其“衍生”风格

动态演化的技术:

  • 采用动态软件架构
    动态软件架构是一种能够在系统运行时根
    据需求、环境变化或用户行为动态调整其
    结构和行为的架构设计模式。
    ◦ 动态软件架构强调在系统运行过程中,通
    过动态加载、卸载或重新配置组件,实现
    功能扩展、性能优化或故障恢复。
    其核心特性包括:
     (1)运行时适应性:支持在不停机的情况下
    调整组件或服务,如动态扩展服务器节点以应
    对流量高峰。
     (2)状态感知与决策:基于实时数据(如负
    载、用户请求类型)动态决策,例如负载均衡
    系统根据流量分配资源。
     (3)多端协同、动态更新
    ◦ 应用场景包括
     微服务架构中动态服务发现,自适应系统(如
    自动驾驶决策),物联网(动态集成新设备)

  • 进行动态重配置
    动态重配置指在软件系统运行时修改其配
    置或结构,而无需停止或重启系统。
    ◦ 这使系统能够适应需求变化(如负载波动、
    功能更新或故障恢复),同时保持服务的
    连续性
    核心特征:
     (1)实时性:调整发生在运行时,无需停机。
     (2)灵活性:支持参数调整、组件替换、资
    源扩展等。
     (3)透明性:对用户或外部系统无感知,服
    务不中断。
    ◦ 应用场景:
     云计算中计算资源的弹性伸缩,在线服务升级,
    故障节点替换等

什么是软件重构?为什么要进行软件重构?

软件重构是改进已经写好的软件设计、提高软件的某些质量属性,是进行软件优化和提高软件质量的重要手段之一。

在不改变软件的功能和外部可见性的情况下,为了改善软件的结构,提高软件的可读性、
可扩展性、可重用性、可维护性等质量属性的情况下而对其进行的改造。

软件重构背景:(重构的动机)
与用户有关的某些非功能需求变化 直接影响 软件内部质量
用户功能需求的变更 间接影响 软件内部质量

软件架构的类别:软件架构重构、结构调整、代码重构

重构类别 重构需求 重构目的
架构重构 软件架构级坏味道、设计技术债 通过软件产品整体结构或者组织方式的重构来消除坏味道和技术债,提高软件架构的质量
代码重构 代码坏味道、代码技术债 通过代码重构来消除坏味道和代码方面的技术债,提高代码质量等

架构腐蚀的含义

软件架构腐蚀指预期软件架构或概念软件架构与实际软件架构之间的偏离。这种偏离更多的是源自日常的软件修改,而非人为的恶意。

架构腐蚀的预防控制方法:腐蚀最小化;腐蚀预防;腐蚀修补

腐蚀最小化:可以通过面向过程的架构一致性策略等方法,统一而严格地编写软件架构设计文档,进行架构评估,进行软件架构依从性监控使得实现忠于架构设计,进行架构依赖性分析揭示特定系统中违背软件架构规则的情况
腐蚀预防:通过一些具体的预防措施(如联动架构策略、自适应策略)进行架构腐蚀预防
腐蚀修补:架构修补包括识别腐蚀、从源代码中恢复实现的架构、修复恢复的架构使之符合预期架构、协调实现与预期架构

架构恢复的含义与意义

架构恢复与架构腐蚀的关系

软件技术债

技术债的含义
技术债是指开发人员为了加速软件开发,或是由于自身经验的缺乏,有意或无意地在应该采用最佳方案时进行了妥协,使用了短期内能加速软件开发的方案,从而在未来给自己带来额外的开发负担
技术债的分类

  • 代码债:开发时没有守代码规范导致的债务,来源包括静态分析工具的违规行为和不一致的编码风格
  • 设计债:在设计时未采用最优解决方案导致的债务,来源包括设计臭味和违背设计规则的行为。架构技术债也是设计债的一种
  • 测试债:测试环节产生的债务,一般由测试的缺乏、测试覆盖面不充分以及不恰当的测试设计导致
  • 文档债:由技术文档问题产生的债务,包括缺少重要技术文档、较差的文档和未及时修改更新的文档

技术债的成因

  • 进度压力:
  • 软件设计师缺乏足够的经验和技巧
  • 不注重设计原则的应用
  • 缺乏对设计坏味和重构的意识
  • 开发中有意采用非最优的选择

技术债的识别方法
对于代码技术债,在软件开发、管理和运行中往往会出现一些信号,通过这些信号可以及时找出技术债
对于非代码类型的技术债,更多地是通过提高开发、测试人员的基本技能素养和开发测试规范性来即使发现问题,每个环节都做到精确、清晰、完整、可追溯,从而可以及时发现技术债并进行定位

技术债的偿还
技术债的偿还工作是由发现和管理作为基础的,当开发者发现一个技术债时,他并不一定立刻偿还,而是根据技术债的具体情况决定偿还方式
处理方法分为以下四步:

  1. 发现项目中包含的技术债
  2. 将技术债加入到产品列表中
  3. 根据债务的影响和场外成本进行优先级排序
  4. 在合适的开发洲际对不同的技术债进行修改偿还

软件坏味道

代码坏味

如果程序中的某一段代码是不稳定或者有一些潜在问题的,那么该段代码往往会包含一些明显不太好的痕迹。我们称这些痕迹为代码坏味
代码的坏味道是用来帮助开发者在开发的过程中识别出具体什么地方需要进行重构的工具
应用级坏味道

  1. 重复代码:在一个以上的地方出现了重复的代码片段。例如一个父类有两个子类,这两个子类中存在相同的表达式
  2. 人为复杂性:在进行简单设计就充分的情况下,过度设计
  3. 散弹式修改:如果每遇到某种变化,你都必须在许多不同的类中做出许多小修改。
    类级坏味道
  4. 过大的类
  5. 依恋情结的类:一个类的方法过多地使用了另一个类的方法。
  6. 过度亲密类:一个类存在与另一个类的实现细节依赖
  7. 拒绝的馈赠:子类仅仅使用父类中的部分方法和属性,其他来自父类的馈赠成为了累赘。 违反了里氏替换原则
  8. 冗赘类:一个做的事情太少的类
  9. 数据泥团:当一群变量一起在程序的不同部分传播时会发生数据泥团现象。即:常常可以在很多地方看到相同的若干项数据。
  10. 不完美的程序库类:尽管许多编程技术都建立在library classes的基础上,但是Library classes构筑者没有未卜先知的能力,不可能考虑所有可能的情况
  11. 纯数据类:某个类拥有一些字段以及用于访问这些字段的方法,除此之外一无长处。这样的classes只是一种“不会说话的数据容器”,它们几乎一定被其它classes过份细琐地操控着
    方法级坏味道
  12. 过长方法:一个方法(函数、过程)含有太多行代码
  13. 参数太多
  14. 超长标识符
  15. 数据过量返回
  16. 超长代码行

    架构坏味

    架构坏味道在系统粒度下出现的层次要高于代码坏味道
    架构坏味道是一种通常使用的、可以对系统生命周期特性产生消极影响的架构设计。它可能是由于在不适当的环境下应用了一个不合适的解决方案;或者在错误的粒度层次下应用了某个设计抽象等产生的,会对系统的可理解性、可测试性、可扩展性以及可重用性等产生负面影响。
    架构的坏味道是用来告诉开发者什么时间、是什么地方对架构进行适当的重构工作。

连接件嫉妒
广泛地将连接件的功能与组件的功能相连接导致的连接件嫉妒会降低组件的可重用性、可测试性和可理解性。但性能较好
如果该系统对于性能的要求远大于可维护性,那么系统中出现连接件嫉妒是可以容忍的。
虽然对于某些系统来说,出于某些考虑可能做出上面的权衡来保留连接件嫉妒现象,但是
这种不考虑该味道对系统生命周期可维护性,可能会产生毁灭性的影响。

软件脆弱性的含义

脆弱性是自然、动植物、动植物群体、社会、国家、制度等等众多属性中部分属性的集合,是表示事物应对波动性、随机性、压力等等的变化趋势

软件架构设计存在一些明显的或者隐含的缺陷,攻击者可以利用这些缺陷攻击系统,或者当受到某个或某些外部刺激时,系统发生性能下降、稳定性下降、可靠性下降等。
如果软件架构具备这些缺陷,我们认为该软件架构是脆弱的,也就是软件架构脆弱性。

软件脆弱性的成因

通常情况下,我们认为软件脆弱性是导致破坏系统安全策略的系统安全规范、系统设计、实现和内部控制等方面的弱点
软件架构脆弱性通常与软件架构的风格和模式有关,不同风格和模式的软件架构,脆弱性体系和特点有很大不同。

软件脆弱性特点:
(1)脆弱性是软件系统中隐藏的一个弱点,本身不会引起危害,但被利用后会产生严重的
安全后果;
(2)在软件开发过程中,自觉或不自觉引入的逻辑错误是大多数脆弱性的根本来源;
(3)与具体的系统环境密切相关,系统环境的任何差异都有可能导致不同的脆弱性问题;
(4)旧的脆弱性得到修补或纠正的同时可能会引入新的脆弱性
因此,脆弱性问题会长期存在。

软件架构脆弱性属于软件设计脆弱性或软件结构脆弱性的一种。
软件架构脆弱性是更高层次的软件结构脆弱性,也是更加重要的软件脆弱性问题

软件脆弱性的例子

  1. 分层架构
    一旦某个底层发生错误,那么整个程序将会无法正常运行,产生安全性问题,也可能会得出错误的结果;
    将系统隔离为多个相对独立的层,要求在层与层之间引入通信机制。在使用面向对象方法设计的系统中,通常会存在大量细粒度的对象,以及它们之间的大量的消息交互——对象成员方法的调用。本来直来直去的操作,现在要层层传递,势必造成性能的下降

  2. C/S架构
    客户端需要安装专用的客户端软件,系统软件升级时,每一台客户机需要重新安装,其维护和升级成本非常高。
    高昂的维护成本且投资大
    传统的C/S结构的软件需要针对不同的操作系统系统开发不同版本的软件,由于产品的更新换代十分快,代价高和低效率已经不适应工作需要

  3. B/S架构
    相对客户端来说,页面通用化,不突出个性。
    而且页面需要不断地动态刷新,尤其是当用户增多,网速慢等情况,服务器的压力将会增大,加载时间会变长
    由于不需要安装客户端,客户端易扩展,B/S将面对大量的不可知用户。
    相对服务器来说,当用户增多时,服务器响应速度慢。
    功能虽然多样化,但是不能专门化,不能实现复杂的功能。
    服务器承担着重要的责任,数据负荷较重。一旦发生服务器“崩溃”等问题,后果不堪设想

  4. 事件驱动架构
    组件削弱了自身对系统的控制能力。一个组件触及事件时,并不能确定响应该事件的其他组件及各组件的执行顺序
    不能很好地解决数据交换问题
    使系统中各组件的逻辑关系变得更加复杂
    事件驱动容易进入死循环
    虽然有机会实现有效利用cpu,但也存在高并发事件处理的可能造成系统响应问题,且易导致系统数据不正确、丢失数据现象
    因为可响应的流程基本都是固定的,如果操作不当,容易引发安全问题

  5. MVC模式
    由于没有明确的定义,完全理解MVC并不是很容易
    MVC由于将应用分为三层,意味着代码文件增多。
    不适合小型,中等规模的应用程序
    增加系统结构和实现的复杂性
    视图对模型数据的低效率访问
    一般高级的界面工具或者构造器不支持模式。改造这些工具以适应MVC需要和建立分离的部分的代价很高

  6. 微内核架构
    微内核架构难以进行良好的整体优化
    微内核的进程间通信开销也较单一内核系统要大的多
    通信损失率高

  7. 管道过滤器架构
    每个过滤器的输入输出是独立的,一个过滤器的输出做为另外一个过滤器的输入,耦合度低
    若攻击者知道了某个过滤器的输入输出,有可能得出过滤器的功能,从而对系统的安全性造成威胁
    由于一个过滤器的输出作为另外一个过滤器的输入,若一个过滤器发生错误,使得整个错误在系统中放大,从而威胁系统的稳定性。

  8. 黑板模式
    不能确保期望结果,求解整个问题是通过多个知识源来进行的,而知识源的选择是通过控制机构中调度程序来选择的,如果知识源选择的不够恰当,可能会导致错误或者有误差的结果;
    复杂,效率低下;
    不支持并行:首先控制机构中需要将知识源放入调度队列中排队,其次多个知识源共享黑板需要同步,因为它们是通过黑板进行通讯的,每个状态的改变可能会影响下一个状态的改变

9.微服务架构
开发人员需要处理分布式系统的复杂性;开发人员要设计服务之间的通信机制,通过写代码来处理消息传递中速度过慢或者不可用等局部失效问题;
服务管理的复杂性,在生产环境中要管理多个不同的服务实例,这意味着开发团队需要全局统筹;
需要把握好应用微服务架构的时机