软件体系结构

  • 格式:pdf
  • 大小:820.93 KB
  • 文档页数:15

软件体系结构

软件体系结构

质量属性:

开发期质量:可扩展性,可复⽤性,可维护性等;

运⾏期质量:正确性,健壮性,性能,可靠性,容错性,易⽤性,安全性,可移植性,兼容性。

设计原则:1. ⾯向接⼝编程(Program to interfaces, not to implementations)2. 多⽤组合,少⽤继承(Favor composition over inheritance)3. Principle of Least Knowledge(Law of Demeter)4. 单⼀职责原则(Single Responsibility Principle):就⼀个类⽽⾔,应该仅有⼀个引起它变化的原因。5. 开闭原则(Open-Closed Principle):软件实体对扩展是开放的,但对修改是关闭的,即在不修改⼀个软件实体的基础上去扩展其功能。抽象化是开闭原则的关键6. ⾥⽒代换原则(Liskov Substitution Principle):在软件系统中,⼀个可以接受基类对象的地⽅必然可以接受⼀个⼦类对象。⾥⽒代换原则是实现开闭原则的重要⽅法之⼀。7. 依赖倒置原则(Dependency Inversion Principle):要针对抽象层编程,⽽不要针对具体类编程。实现开闭原则的关键是抽象化,并且从抽象导出具体化实现,如果说开闭原则是⾯向对象设计的⽬标的话,那么依赖倒置原则就是⾯向对象设计的主要⼿段。依赖注⼊:构造注⼊,设置注⼊,接⼝注⼊8. 接⼝隔离原则(Interface Segregation Principle):使⽤多个专门的接⼝来取代⼀个统⼀的接⼝。9. 分离关注点(Principle of Separation of Concerns):"Organize software into separate components(pieces) that are as independent as possible."

软件风格:

Model-View-Controller(pattern)

MVC模式(Model-view-controller)是软件⼯程中的⼀种软件架构模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)MCV模式的⽬的是实现⼀种动态的程序设计,使后续对程序的修改和扩展简化,并且使程序某⼀部分的重复利⽤成为可能。

控制器(Controller):负责转发请求,对请求进⾏处理。

试图(View):界⾯设计⼈员进⾏图形界⾯设计。

模型(Model):程序员编写程序应有的功能(实现算法等等)、数据专家进⾏数据管理和数据库设计(可以实现具体的功能)

将应⽤程序划分为三种组件,模型-试图-控制器(MVC)设计定义它们之间的相互作⽤。

模型(Model):⽤于封装与应⽤程序的业务逻辑相关的数据以及数据的处理⽅法。"Model"有对数据直接访问的权利,例如对数据库的访问。"Model"不依赖"View"和"Controller",也就是说,Model不关⼼它会被如何显⽰或是如何被操作。但是Model中数据的变化⼀般会通过⼀种刷新机制被公布。为了实现这种机制,那些勇于监视此Model的View必须事前在此Model上注册,从⽽,View可以了解在数据Model上发⽣的改变。

视图(View)能够实现数据有⽬的的显⽰(理论上,这不是必需的)。在View中⼀般没有程序上的逻辑。为了实现View上的刷新功能,View需要访问它监视的数据模型(Model),因此应该事前在被它监视的数据那⾥注册。

控制器(Controller)起到了额不同层⾯间的组织作⽤,⽤于控制应⽤程序的流程。它处理事件并作出响应。"事件"包括⽤户的⾏为和数据Model上的改变。

实例Java平台上实现的MVC模型

视图(View)

在J2EE应⽤程序中,视图(View)可能由Java Server Page(JSP)担任。⽣成View的代码则可能是⼀个servlet的⼀部分,特别是在客户端服务端交换的时候。

控制器(Controller)J2EE应⽤中,Controller可能是⼀个servlet。除了可直接以J2EE来撰写外,亦可⽤其他框架来撰写,常见的有Struts2,Spring Framework…等等。

模型(Model)Model则是由⼀个实体Bean来实现。

C/S(Client-Server)

C/S软件是基于资源不对等,且为实现共享⽽提出来的。C/S体系结构主要有三个主要组成部分:数据库、服务器、客户应⽤程序和⽹络。优点:具有强⼤的数据操作和事务处理能⼒;对于软件和硬件的变化显⽰出强⼤的适应性和灵活性;将⼤的应⽤处理任务分到许多通过⽹络连接的低成本计算机上。缺点:开发成本⾼;客户端程序设计复杂;软件维护和升级困难。

管道过滤器风格(Pipe-and-Filter)

每⼀个组件都有⼀组输⼊和输出,组件读输⼊的数据流,经过内部处理,然后产⽣输出的数据流。过滤器风格的连接件就像是数据流传输的管道,将⼀个过滤器的输出传到另⼀个过滤器的输⼊。

分层系统(Layered/Tiered Architecture)

组织成⼀个层次结构,每⼀层都为上⼀层提供了相应的服务,并且接受下⼀层的服务。在分层系统的⼀些层次中构件实现了虚拟机的功能。实例:分层的操作系统

端到端(Peer-to-Peer)

⿊板系统/仓库系统(Blackboard/Repository)

组件:中⼼数据结构(仓库)和⼀些独⽴构件的集合。

仓库和在系统中很重要的外部组件之间的相互作⽤实例:需要使⽤⼀些复杂表征的信号处理系统

基于事件的隐式调⽤(Event-Based Architecture(PubSub))

组件不直接调⽤⼀个过程,⽽是触发或⼴播⼀个或多个事件。系统中的其他组件中的过程在⼀个或多个事件中祖册,当⼀个事件被触发,系统⾃动调动这个事件中注册的所有过程。这种风格的组件是⼀个模块,这些模块可以是⼀些过程,⼜可以是⼀些事件的集合。不变量:事件的触发者并不知道哪些组件会被这些事件影响(观察者模式-Observer)实例:数据库管理系统,⽤户界⾯。

SOA(Service-Oriented Architecture)

⾯向服务的体系结构是⼀个组件模型,它将应⽤的不同功能单元(称为服务)通过这些服务之间定义良好的接⼝和契约联系起来。阿⾥的dubbox是国内现在应⽤最多的⽤来实现SOA的框架。它将服务注册到企业服务总线上,当某个系统需要调⽤其他系统中数据的时候直接从企业服务总线上获取,⽽不是端到端的获取,从⽽减少了系统的复杂度。

RESTF(representational state transfer)表述性状态转移

Rest是web服务的⼀种架构风格;使⽤HTTP,URI,XML,JSON,HTML等⼴泛流⾏的标准和协议;轻量级,跨平台,跨语⾔的架构设计。它是⼀种设计风格,不是⼀种标准,是⼀种思想。Rest架构的主要原则:

1. ⽹络上的所有事情都被抽象为资源2. 每个资源都有⼀个唯⼀的资源标识符3. 同⼀个资源具有多种表现形式(xml,json等)4. 对资源的各种操作不会改变资源标识符5. 所有的操作都是⽆状态的6. 符合REST原则的框架⽅式即可成为RESTful什么是Restful:

对应的中⽂是rest式的;Restful web service是⼀种常见的rest的应⽤,是遵守了rest风格的web服务;rest式的web服务是⼀种ROA(TheResource-Oriented Architecture)(⾯向资源的架构)为什么会出现Restful

在Restful之前的操作:http://127.0.0.1/user/query/1 GET 根据⽤户id查询⽤户数据http://127.0.0.1/user/save POST 新增⽤户http://127.0.0.1/user/update POST 修改⽤户信息http://127.0.0.1/user/delete GET/POST 删除⽤户信息

RESTful⽤法:http://127.0.0.1/user/1 GET 根据⽤户id查询⽤户数据http://127.0.0.1/user POST 新增⽤户http://127.0.0.1/user PUT 修改⽤户信息http://127.0.0.1/user DELETE 删除⽤户信息

之前的操作是没有问题的,⼤神认为是有问题的,有什么问题呢?你每次请求的接⼝或者地址,都在做描述,例如查询的时候⽤了query,新增的时候⽤了save,其实完全没有这个必要,我使⽤了get请求,就是查询,使⽤post请求,就是新增的请求,我的意图很明显,完全没有必要做描述,这就是为什么有了restful如何使⽤

总结:restful就是旧技术,新风格。

⼤泥球风格(big ball of mud):⼤泥球风格就是没有任何清楚的结构,杂乱⽆章、错综复杂,邋遢不堪、随意拼贴的⼤堆代码。

控制反转与依赖注⼊

什么是控制?如下图所⽰,我们看到了软件系统中对象的⾼耦合现象。全体齿轮的转动由⼀个对象来控制,如类B

什么是控制反转?是⽤来对对象进⾏解耦。借助第三⽅实现具有依赖关系的对象之间的解耦。这个第三⽅就是ioc容器。引⼊了ioc容器后,对象A、B、C、D之间没有了依赖关系,全体齿轮转动的控制权交给容器。这时候齿轮转动控制权不属于任何对象,⽽属于ioc容器,所以控制权反转了,从某个对象转到了ioc容器。

什么是依赖注⼊?

什么是依赖?依赖是指⼀种关系,如果在类A中创建了类B的实例,我们说类A依赖类B。下⾯有⼀个例⼦:

出现的问题(problems):

问题1:如果现在要改变类B⽣成⽅式,如需要new B(string name)初始化 B,需要修改类A中的源代码;

问题2:如果想测试不同B对象对A的影响很困难,因为B的初始化被写死在了A的构造函数中;

问题3:如果要对类B的实例进⾏调试时,就必须在类A中对类B的实例进⾏测试,增加了测试的难度和复杂度;因为当出现问题时,不知道是类A的问题还是类B的问题。解决⽅法:

依赖注⼊定义:将B对象实例作为类A的构造器参数进⾏传⼊,在调⽤类A构造器之前,类B实例已经别初始化好了。像这种⾮⾃⼰主动初始化依赖,⽽通过外部传⼊依赖对象的⽅式,我们就称为依赖注⼊。

依赖反转

根据依赖注⼊的定义:被依赖者对象并不是依赖⾃⼰主动初始化,⽽是通过外部传⼊被依赖者的⽅式,那么背依赖者对象类型可以是其本⾝,也可以使其实现类或继承⼦类;

所以,经过分析,被依赖者的对象类型,并不是依赖者⾃⾝可以决定的,(当然传统的程序设计⽅式是依赖者决定的),⽽是由外部创建者决定的,所以被依赖者类型的决定权反转了。对于spring来说,就是由spring容器决定的;

依赖反转定义:被依赖者的对象类型并不是由依赖者⾃⾝可以决定的,⽽是由外部创建者决定的,外部传⼊什么类型的对象就是什么类型的对象,依赖者对其⼀⽆所知;

框架与库有⼀个基本的特征是框架⼀般指的是会调⽤你的代码,控制权从你写的程序⼿中转移到框架中,⽽库⼀般是⽤来被你调⽤。