软件体系结构概念
构件
构件是具有某种功能的可复用的软件结构单元,表示系统中主要的计算元素和数据存储。
构件是一个封装的实体,只能通过接口来进行交互。构件的功能以服务的形式体现出来,并通过接口对外发布,进而与其他构件产生关联。
连接
连接是构件间建立和维护行为关联与信息传递的途径。
连接件
连接件表示构件之间的交互并实现构件之间的连接。
- 管道(pipe)
- 过程调用( procedure call )
- 事件广播( event broadcast )
- 客户机-服务器( client-server )
- 数据库连接( SQL )
软件体系结构的目标
- 可重用性:复用已实现证明的体系结构,或提供可重用资产。
- 可扩展性:易于增加新的需求。
- 可改变性:易于适应需求变更。
- 简单性:复杂问题简单化。
- 有效性:展现系统满足需求的能力。
软件体系结构的发展
风格、模式和框架
- 体系结构风格:用于描述某一 特定应用领域中系统组织的惯用模式,反映了领域中众多系统所共有的结构和语义特性。
eg: MVC就是一种体系结构风格。
- 设计模式:描述了软件系统设计过程中常见问题的一-些解决方案,通常是从大量的成功实践中总结出来的且被广泛公认的实践和知识。
观察者模式是一种常见的设计模式,主要用于解决事件处理的问题。
- 软件框架:软件框架是由开发人员定制的应用系统的骨架,是整个或部分系统的可重用设计,由一组抽象构件和构件实例间的交互方式组成。
eg: Django就是一个开放源代码的外部应用框架。
框架与体系结构的关系?
体系结构的呈现形式是一个设计规约,而框架则是“半成品”的软件;
体系结构的目的是指导软件系统的开发,而框架的目的是设计复用。
框架与设计模式的关系
框架给出的是整个应用的体系结构;而设计模式则给出了单一设计问题的解决方案,且可以在不同的应用程序或者框架中进行应用。
举例:一个网络游戏可以基于网易的Pomelo框架开发,这是一个基于Node.js的高性能、分布式游戏服务器框架;在实现某个动画功能时,可能会使用观察者模式实现自动化的通知更新。
设计模式的目标是改善代码结构,提高程序的结构质量;框架强调的是设计的重用性和系统的可扩展性,以缩短开发周期,提高开发质量。
软件设计原则
-
抽象
抽象是关注事物中与问题相关部分而忽略其他无关部分的一种思考方法。
>如果系统中的SQL Server换成MySQL,SQLServerConnection需要全部换为MySQLConnection 。
符合抽象原则的系统设计,应用系统发生更改的时候,只会影响接口的具体实现。
封装
封装和信息隐藏是指每个软件单元对其他所有单元都隐藏自己的设计决策,各个单元的特性通过其外部可见的接口来描述。模块化
模块化是在逻辑和物理上将整个系统分解成多个更小的部分,其实质是“分而治之” ,即将一 个复杂问题分解成若干个简单问题,然后逐个解决。
系统分解原则
系统分解的目标:高内聚、低耦合。
内聚性是一个模块或子 系统内部的依赖程度。
- 如果一个模块或子系统含有许多彼此相关的元素,并且它们执行类似任务,那么其内聚性比较高;如果一个模块或子系统含有许多彼此不相关的元素,其内聚性就比较低。
耦合性是两个模块或子系统之间依赖关系的强度。- 如果两个模块或子系统是松散耦合的,二者相互独立,那么当其中一个发生变化时对另一个产生的影响就很小;如果两个模块或子系统是紧密耦合的,其中一个发生变化就可能对另一个产生较大影响。
-
层次化
分层( Layering )
每一层可以访问下层,不能访问上层。
封闭式结构:每一层只能访问与其相邻的下一层
开放式结构:每- -层还可以访问下面更低的层次
层次数目不应超过7+2层
划分( Partitioning )
系统被分解成相互对等的若干模块单元。
每个模块之间依赖较少,可以独立运行。
注意:模块单元增加了处理开销,过度分层或划分会增加复杂性。
eg: 安卓操作系统层次结构
-
复用
复用( Reuse)是利用某些已开发的、对建立新系统有用的软件元素来生成新的软件系统,其好处在于提高生产效率,提高软件质量。 - 源代码复用:对构件库中的源代码构件进行复用
- 软件体系结构复用:对已有的软件体系结构进行复用
- 框架复用:对特定领域中存在的一个公共体系结构及其构件进行复用
- 设计模式:通过为对象协作提供思想和范例来强调方法的复用
软件体系结构风格
软件体系结构风格( Architectural Styles )是描述特定系统组织方式的惯用范例,强调了软件系统中通用的组织结构。常见体系结构风格
-
主程序-子程序
主程序-子程,序风格是结构化程序设计的一种典型风格,从功能的观点设计系统,通过逐步分解和细化,形成整个系统的体系结构。
-
面向对象风格
- 系统被看作是对象的集合,每个对象都有一个它自己的功能集合;
- 数据及作用在数据上的操作被封装成抽象数据类型;
-
只通过接口与外界交互,内部的设计决策则被封装起来。
-
管道-过滤器风格
管道过滤器风格把系统任务分成若干连续的处理步骤,这些步骤由通过系统的数据流连接, 一个步骤的输出是下一个步骤的输入。 -
以数据为中心的风格
仓库体系结构( Repository Architecture )是一-种以数据为中心的体系结构,适合于数据由一个模块产生而由其他模块使用的情形。
问题:每个功能模块与仓库之间的耦合非常高。
举例:剪贴板是一个用来进行短时间的数据存储, 并在文档/应用之间进行数据传递和交换的软件程序。
-
客户机/服务器结构
客户机/服务器体系结构( Client/Server )是一种分布式系统模型,作为服务器的子系统为其他客户机的子系统提供服务, 作为客户机的子系统负责与用户的交互。
两层C/S结构- 服务器只负责数据的管理
-
客户机实现应用逻辑和用户的交互
胖客户端:客户端执行大部分的数据处理操作。
瘦客户端:客户端具有很少或没有业务逻辑。
三层C/S结构
表示层:包括所有与客户机交互的边界对象,如窗口、表单、网页等。
功能层(业务逻辑层):包括所有的控制和实体对象,实现应用程序的处理逻辑和规则。
数据层:实现对数据库的存储、查询和更新。
B/S结构
游览器/服务器结构式三层C/S风格的一种实现方式。
集群结构
如果功能层或者数据层分布在多台服务器上,就形成了集群式的系统结构。
MVC结构
影响Web系统模块化的一些因素
模型-视图-控制器(MVC)结构将应用程序的数据模型、业务逻辑和用户界面分别放在独立构件中,这样对用户界面的修改不会对数据模型/业务逻辑造成太大影响。
由控制器来决定视图与模型之间的依赖关系。
- 每次请求必须经过"控制器-> 模型->视图”过程,才能看到最终展现的界面。
- 视图是依赖于模型的。
- 渲染视图在服务端完成,呈现给浏览器的是带有模型的视图页面,性能难优化。
MVC改进方案
首先从游览器发出AJAX请求,服务端接收请求,返回JSON数据给游览器,游览器进行渲染。
RESTful API
由于前端的发展,已经很有必要把前端模板从后端服务器上剥离出来。这样,后端可以专注于业务逻辑。
充分利用GET、PUT、POST、DELETE四种HTTP请求。
对与web而言,我们必须让前后端通过同一域名的同一端口访问到,否则就会出现跨域的问题。跨域就是说我们不能用ajax在一个域名上获取另一个域名或另一个端口提供的数据。解决:nginx
异步任务
假如在用户要求执行某种任务之后,需要执行1min才能执行结束,而游览器的超时限制为30s,这时就需要用到异步任务,任务管理器返回任务的id再启动任务,用户拿到id后可以随时查看任务的运行情况。
异步任务的实现方式
- 事件风格
eg:调试器
事件管理器:IDE(集成开发环境)
事件源:调试器
事件处理器:编辑器与变量监视器
事件系统是将应用看成是一 个构件集合, 每个构件直至发生对它有影响的事件时才有所动作。
事件风格的实现策略
- 选择广播式
二者是一种松耦合的关系。
- 观察者模式
观察者被注入到被观察者中进行监听,随时对被观察者的变化做出反应。
基于经验的选择原则
- 层次化的思想在任何系统中都可能得到应用
- 如果问题可分解为连续的几个阶段,那么考虑使用顺序批处理风格或管道-过滤器风格
- 如果核心问题是应用程序中数据的理解、管理与表示,那么考虑使用仓库或者抽象数据类型( ADT ) /OO风格
- 如果数据格式的表示可能发生变化, ADT/OO可限制这种变化所影响的范围
- 如果数据是持久存在的,则使用仓库结构
- 如果任务之间的控制流可预先设定、无须配置,那么考虑使用主程序子过程风格、OO风格
- 如果任务需要高度的灵活性与可配置性、松散耦合性或者任务是被动性的,那么考虑使用事件系统或C/S风格
- 如果设计了某种计算,但没有机器可以支持它运行,那么考虑使用虚拟机/解释器体系结构
- 如果要实现一些经常发生变化的业务逻辑,考虑使用基于规则的系统
软件设计过程
软件总体设计
系统总体设计是在需求分析的基础上定义系统的设计目标,将整个系统划分成若干子系统或模块,建立整个系统的体系结构,并选择合适的系统设计策略。
权衡设计目标
-
空间与速度
如果响应时间或吞吐量不满足需求,就有可能使用更多的存储空间来进行加速。如果软件不满足存储空间的限制,就可能牺牲速度对数据进行压缩处理。 -
交付时间与功能
如果开发进度发生落后,可以考虑减少一定的功能来保证按时交付,也可以考虑推迟交付时间。
合同软件通常更强调功能性,成品软件更侧重于交付时间。 -
交付时间与质量
如果测试落后于进度,可以先发布一个有少量缺陷的系统,随后再进行升级和修复。 -
交付时间与人员
如果开发进度发生落后,加班是一个可行的方法。在项目后期,增加人手是不可取的。
确定子系统或模块
选择系统部署方案
系统部署方案是描述系统运行期间构件和硬件节点之间的关系,在系统设计阶段处理软件/硬件的映射问题,可能会增加新的子系统或模块的定义。
定义设计策略
对于微信抢票应用来说,我们可以采用单线程、事件驱动和异步任务处理来实现整个控制流。