项目计划和进度 风险知识库
小组经验
风险政策和指南
捕获风险学习
风险分类记录学习的两个关键方面:新风险;成功的缓解策略
管理从风险中学习
在特定的风险分类领域必须有专人负责
风险分类应平衡两个方面的需求:风险覆盖的全面性和复杂性及可用性
需要建立一个风险知识来维护风险分类,定义,诊断,平分系统,以及捕获使用他们的小组经验反馈
需要很好的管理风险审核过程,确保捕获所有的学习经验,
上下文相关的风险分类
对于特殊的,一再重复的项目上下文,要通过开发风险分类来求精风险标识
风险知识库
在管理风险知识中提高成熟度
最低层,没有知识库,在实施风险管理时从零开始
第二级,将采用非形式的知识库
第一级为风险表识提供了一个更加结构化的方法
如何描述和评估软件架构质量
软件的质量建模
评估软件架构质量的价值
怎样改变软件架构的质量
如何评价软件的架构
评估软件架构师的能力
1软件的质量建模
技术架构
管理架构
支撑架构
业务架构
软件架构质量模型隐喻 1
软件架构的重要性是不然而喻的,但是当所有人都意识到他的重要性的时候,却很少有人能够清晰的描述出如何能够提高软件质量
软件质量况架的目的就在于提出一个评价的原型,帮助我们分析一种方法和技术是否能够提高软件质量
什么才是一个高质量的软件
满足用户的需求。这是最重要的一点,一个软件如果不能够满足用户的需要,设计的在好,采用的技术在先进,也没有如何的意义,所以这点非常的朴实,但却是软件质量的第一个评判标准
合理进度,成本,功能关系,软件开发中的所有的管理都是围绕着这几个要素在做文章的,如何在特定的时间内,以特定的成本,开发出特定功能 的软件,三者之间存在一种微妙的平衡,在Planning
一个高质量的软件的开发过程中,项目成员一定能够客观的对待这三个因素,并通过有效的计划,管理,控制,使得三者之间达成一种平衡
保证产出的最大化
具备扩展性和灵活性,能够适应一定程度的需求变化,当今的社会已经变成一种变化速度极快的设计了。变化就会对软件产生冲击,所以一个质量优秀的软件,应该能够在一定程度上适应这种变化,并保持软件的稳定
能够有效的处理例外的情况,写过软件的人都知道,实现主题功能的工作量其实不大,真正的工作量都在处理各种例外,所以,一个软件如果能够足够的建壮,足够的鲁棒,能够承受各种非法情况的冲击,这个软件就是高质量的
保持成本和性能的平衡。性能往往来源于客户的非功能需求,是软件质量的一个重要评价因素,但是性能问题在任何地方都存在,所以需要客观的看待她,例如一段性能不错的代码可能可读性很差,这就需要进行平衡,如果这段代码的性能是整个软件的关键,那么取高性能而舍弃可读性,反之则取可读性而舍弃高性能,一个优秀的软件能够保持成本和性能之间的平衡
能够可持续的发展,很少有软件组织只开发一个软件的,所以,一个优秀的软件在开发完成后,可以形成知识沉淀,为软件组织的长期发展贡献力量,这是一个优秀软件应该要能够作到的
软件的质量框架的 组成
第一部分是前提,说明了软件框架的适用范围,以及适合的环境,和方法学一样,没有泛之四海皆准的方法学,所以软件质量框架也需要一个上下文环境
第二部分是价值观,价值观说明了软件质量框架中强调的价值,在软件的框架的结构和实践中,都将充分的表现出一开始我们定义的价值
第三部分是结构,结构定义了软件质量框架的组成部分
以及软件质量框架和开发过程的关系,第四部分是文章着墨最多的部分,及优秀实践
优秀实践通过具体,实际的分析,举例,深入阐述了软件质量框架的价值观和结构
软件架构的前提
平台前提:由于软件质量框架的实践将会涉及具体的技术和代码,所以我们首先为软件质量框架定义了平台,软件质量框架将会运行在 J2EE 平台上,使用对象分析技术
组织前提:执行软件质量框架需要投入,需要付出,软件质量框架最难的地方不是学习,而是执行,在一个组织中,需要评估应用软件质量框架需要多少多少投入,对目前的开发过程有多大的助益,一般来说,组织的规模越大,其开发过程和产品越复杂,就越适合采用软件质量框架
方法学前提:在敏捷方法学中,对规则和秩序有两中不同的观点,一种是强调规则和秩序,以XP为代表,他对代码都有要求,另一种则不那么强调,以自适应的软件开发为代表,他不要求程序员的具体行为,软件质量框架采用第一种观点,要求组织中存在严谨的规则和秩序
软件质量框架的价值观
明确具体:对软件的管理必须是明确具体的,软件开发是工程,也是艺术,需要紧密的协作和沟通,任何一个含糊的指令都可能导致软件开发中出现错误,所以,在软件开发中,任何一个指令都应该是明确具体的,为什么说是相对呢?是和成本相对,指令越明确,成本就越高,例如,你可以把需求文档写的非常的具体,但是你需要付出制作和维护的代价,所以我们的明确性是一个考虑成本前提下的特性
明确具体要从综合上考量,怎么理解呢? 例如 XP中的用户故事是非常不精确的,按道理说它是不明确,也是不具体的,但是在整个开发周期中,将会有跌代,测试,现场用户等多种手段使用户故事明确具体起来,所以从整体上看,它并不违反我们的价值观,产品质量是一个系统工程,决不仅仅是在QA部门工作,这个道理适用于制造业,也适用于软件业
容错:软件开发是人的工作,人是无法避免错误的,所以软件质量框架中容易犯错。因为不犯错误是天方夜潭,你就算做了这方面的强制规定也无法避免他的出现,反而会引发其他的问题,例如隐瞒错误,或为了隐瞒错误而导致的额外成本。所以正确的态度是允许发生错误,并建立一套监测,管理,反馈,修改错误的体制
规范:在前提中,我们已经提到了,规范是软件质量框架的基本态度,所以,软件质量框架中强调规范,并使用规范来推动框架的运作
测试:软件的质量框架非常强调测试,测试是保证质量的必由之路,测试要尽可能快的反馈,这是软件质量框架对测试的基本态度,测试是综合的,软件开发过程中的所有工件,都需要伴随着相应的测试工件,这是基于一个简单的观念,如果你不能够成为你的工作制定一个完成的标准,你又该如何开展你的工作呢?
软件质量框架的结构
处于结构核心的是技术架构和管理架构,软件质量框架既不是方法学,也不是一个软件,更象两者的结合体,技术架构和管理架构的融合体现了这一特性,软件质量框架并不关心单个开发人员的效率,他关注的是开发团队整体的效率
因此,管理架构在框架中的意义在于他定义了一套软件管理的方法,能够对开发人员极其他们的工作进行管理,从这一点来看,他的作用和软件工程方法学一样的,但是在现实中我们很难发现软件组织在迈向软件过程的涂中往往因为现实的困难而止步不前,其中一个主要的原因是在引入的方法学的过程中生产效率降低了,而引起组织成员对变革的怀疑和不满
软件质量框架还提供了一个技术框架,其中的是目的明确的定义如何应用组织中涉及的软件技术,以及管理软件技术的方法,技术架构是具体的代码,相比起方法学来说,他更加的具体,更容易为开发人员是进行技术积累,另一方面也是为管理架构服务
技术架构和管理架构的下一层是支撑框架支撑框架包括代码,组件,文档,目的是为技术架构和管理架构提供底层的支持
处于结构最顶层的是业务架构,这个部分对于任何一个软件组织来说都是不同的因为不同的软件组织的业务不同。业务架构的目的是对业务进行建模和抽象,提取出可重用的部分,以提高软件组织的生产率
软件架构的优秀实践
一个开发团队要提高效率,就需要思考目前的管理活动中有那些要素是可以改进的;如何把一些事务性的操作变得自动化,从而节约人力,如何找到更好的方法,让开发过程更为合理,更注重软件的质量;如何在团队中传播优秀的思想,让团队成员不断的学习和进取,自发的改进过程,这些美好的愿望几乎是所有方法论和各种认证的共同心声,但是要完全做到可就太难了
优秀的实践是来源与软件开发界的一些新思路和新理念论,他们能够为以上愿望的达成起到正面的作用。在组织中引入用这些实践决不是一个容易的过程,但他们确实非常的有效,不论是在成本控制上,还是在质量的改进上
日创建:一个组织应当拥有一个有效的工作流程,这个工作流程能够指导软件开发的进行,这个流程应该是具体的,可操作的,随意的计划和从来不遵循的进度决不是一个有效的工作流程,日创建实践提出了一种对开发过程进行精细管理的方法,他是量化软件的基础,有了日创建,你会发现计划的制定和进度的监控是非常容易的一件事情
测试驱动开发:软件质量的根源来源于测试,测试作好了,软件的质量就好,这是毫无疑问的,问题的关键在于怎么做测试,才能保证测试的投入能够带来软件质量的有效提升。测试驱动开发正是为了解决这个问题而出现的,他不是一个完整的方法论,可以和任何一种开发流程进行融合,测试驱动开发不但能够改善测试效果,还能够改进软件的设计
建立核心框架:框架是一种具有高质量重用性的软件,这个特性决定了他非常适合成为软件组织积累知识的一种有效手段,传统的知识积累的方法是文档,但是文挡容易产生歧异,开发人员往往也不愿意去阅读和理解文挡,框架提供的是一种综合的手段,包括文挡,模型和代码,更容易理解,更重要的是,开发人员必须在日常的工作中使用框架,这使得他们对框架中的知识非常的熟悉,并根据工作的需要来改进框架
面向组件编程:有效的组织再于有效的分工,体力活动容易进行分工,脑力劳动则比较难,而软件开发似乎更难了,所以,长久以来我们都习惯采用以功能块开发为单位的粗粒度划分方式,并以服务作为组件之间相互依赖的契约,不但定义了组件和组件之间的关系,也规定了组件开发者,组件使用者,组件测试者的权利和义务。从而能够进行软件开发工作的分配,管理, QA 等工作
从软件结构的角度来看,日创建和测试驱动开发似乎偏向于管理架构,而建立核心框架和面向组件编程侧重于技术框架,事实上,他们既包含技术架构,也包含管理架构,彼此之间也有相关关联
例如,面向组件编程在合理划分组件之后,就需要一个有效的核心框架来集成组件,通过每个组件都需要采用测试驱动开发方法来保证质量,同时,日创建将会以组件为单位进行每日的创建,从而为进度估算提供有效数据
未来的一种可能性是UML2.0和MDA技术的普及,以上的几个实践从以代码为核心转变为以设计为核心,而另一种可能性是随着以AspectJ为代表的AOP 技术的普及和J2se1.5 中引入了的元数据机制,面向组件编程把Aspect 作为组件的一种,而测试驱动开发也会加入测试 Aspect 的相关内容,在日创建中也会增加相应的处理AOP的步骤
软件架构评估
高质量架构设计的障碍
1对软件开发过程中架构设计的重要性没有认识
2对软件架构师的角色缺乏理解
3宽泛地认为设计是技术形式的活动,而不是技术活动
4对设计的过程缺乏理解
5在开发组织中缺乏设计经验
缺少软件架构设计的方法学和相应工具
不知道如何评估设计
在“利益相关者”之间缺乏有效的沟通
架构权衡分析评估方法
1评估参与者
1)评估组独立于项目组,3-5人,中立,每个人都有能力进行架构设计
2项目决策者项目负责人,架构师,客户代表等构成
3架构利益相关者相关者开发人员,测试人员,维护人员,用户等构成12~15人
Cost Benefit Analysis Method(CBAM)
1)消耗和效益的上下文
Business Goals ->Architechture Strategies->Persormance ,security,modiliablity ,Usablity ->Benefit
|
^
Cost
步骤
评估软件架构师的能力
角色和分工
参与应用建模的人员主要分成两类角色,系统架构师和设计师
系统架构师职责
系统架构师负责领导和协调整个项目中的 技术活动
在个人综合素养方面,系统架构师应该具有领导才能,能够在压力下作出关键性的决定性的决策并善始善终
能够赢得项目经理,客户,用户群体以及管理团队的认同和尊敬,尤其要善于和项目经理紧密协作
在各个方面都能展现出目标的实干作风,在专业技能方面,与其他角色相比,系统架构师通常具有全方位的技能,其见解重在广度,而不是深度
系统架构师不仅要具备设计师的各项技能,而且应该具有问题领域和软件工程领域的实践经验,从而有能力在无法获得完整信息的情况下迅速领会问题并根据经验作出谨慎的判断
如果项目较大,系统架构师将是一个团队,上述的关键素质要求可由团队成员来分担,但其中要有一名系统架构师具有足够的权威
设计师职责
设计师的工作对象通常是系统的局部或者细节
设计师应该掌握的技能包括
理解以 Use Case 建模的技术捕获和描述的软件需求
在系统架构师的统一协调下,应用 UML进行局部的面向对象的分析和设计
了解主流的实施技术(程序设计语言和 开发环境)
设计模式与软件架构设计
面向对象软件架构设计思想
使用UML进行软件架构设计
设计模式的本质论
设计模式与架构模式
面向对象的本质论-面向对象范式
功能分解模式分析
功能分解模式如何适应需求的变化
面向对象范式
功能分解:
分析者将问题分成多个功能步骤,这些步骤组合起来就是可以解决实际的问题
把问题分解成小块来解决,比以次处理整个问题要简单
功能分解带来的问题
他不能帮助我们为未来可能发生的变化作出准备
他不能帮助我们的代码优雅的演变
变化的发生还为错误和意外结果的发生创造了机会-许多错误都来自代码的变化
模块化方式处理变化
模块化可以帮助你写出更容易理解的代码,更容易理解的代码也更容易维护;
模块话并不能帮助你写出能应付所有可能出现的变化代码
内聚和耦合
内聚度:是指程序中的操作之间联系紧密的程度,描述了一个子程序的内部成分之间相互联系的强度
耦合度:是指两个只程序之间联系强度,描述了一个子程序与其他子程序之间的联系强度
耦合度与内聚度成反比
目标:将建具有内部完整性(强内聚)的子程序,以及小的,直接的,,可见的,灵活的与其他子程序之间的联系(松耦合)
责任迁移模式处理需求变化
软件开发过程的视角
概念(conceptual)
展示了问题领域中的概念
一个概念模型可以在对实现软件有很少或毫无注意的情况下勾勒出来
规格 (Specification )
我们只看软件的接口,而不看软件的实现
实现 (Implementtation)
置身于代码当中,使常规视角
目标:
一个层次(概念层次)上通信而在另一个层次(实现层次)上执行,
请求者不知道发生了什么,只知道概念上发生了什么
面向对象范式
面向对象范的核心是“对象”的概念
所有的东西都聚焦于对象
围绕对象-而非函数-组织代码
对象从不同视角观察
概念层
一个对象是一系列责任
规格层:一个对象是一系列可以被其他对象或该对象自己调用的方法
实现层:一个对象是一些代码和数据
面向对象本质论-设计原则
面向对象的设计目标
可维护性,可复用性
可维护性:
现在存在的问题:
过于僵硬,过于脆弱,复用率低,粘度过高
可维护性
设计的目标
可扩展性(Extensionlity)
新的功能可以很容易假如到系统中
灵活性(Flexiblity)
允许代码修改平稳的发生,而不会涉及到许多其他的模块
可插入性
可以很容易地将一个类抽出去,同时将一个可以很容易地将一个类抽出去,同时将一个同样的接口的类加入进来
可复用性
重要性
较高的生产效率
较高的软件质量
恰当使用复用可以改善系统的可维护性
传统的复用
代码的剪贴使用
算法的复用
数据结构的复用
设计原则
“开闭”原则(OCP)
Open-Closed Principle
定义Software entities should be open for extension but closed for modifycation
一个软件实体对扩展开放,对修改关闭
”抽象化“是OCP的关键
对可变性的封装原则
Priciple of Encapsulation of Variation (EVP)
找一个可变的因素把他封装起来
一种可变性不应当散落到代码的很多角落里,而应当被封装到一个对象里
一种可变性不应当与另一种可变性混合在一起
里氏代换原则(LSP)
Liskov Substitution Principle
如果对某一对象类型T1的对象O1,都有类型为T2的对象o2,使得以T1定义的所有程序P在所有的对象O1 都代换成o2时,程序P的行为没有变化,那么类型T2是类型T1的子类型
依赖倒转原则(DIP)
Dependency Inversion Principle(DIP)
要依赖于抽象,不要依赖于具体
抽象层次包含的是应用系统的商务逻辑和宏观的,对整个系统来说重要的战略性的决定,是必然性的体现
具体层次则含有一些次要的,与实现相关的算法和逻辑以及战术性的体现,带有相当的偶然性
表述
Abstractions should not depend upon details,details should depend upon abstractions ,(抽象不应当依赖细节,细节应当依赖抽象)
Program to an interface ,not a implementation (要针对接口编程,而不要针对实现编程
接口隔离原则(ISP)
Interface Segregation Principle (ISP)
从一个客户角度来将,一个类对另一个类的以来性应当建立在最小的接口上
原则,角色分割
定制服务
组合/聚合复用原则(CARP)
Compsition/Aggregation Reuse Principle (CARP)
定义
在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分,新的对象通过向这些对象的委派达到复用已有功能的目的
尽量使用合成/聚合,而不是继承
类图中的关系
一般化的关系(Ceneralization )
表示类与类之间的继承关系,接口与接口之间的继承关系
类对接口的实现关系
关联关系(Association)
表示类与类之间的联接,他是一个类知道另一个类的属性和方法
关联可以是单向的,也可以是双向的
聚合(Aggregation)关系
是关联的一种,是强的关联关系,是整体与个体的关系
合成关系
是关联关系的一种,是比聚合关系强的关联,他要求普通的聚合关系中代表整体的对象负责代表个体的对象的生命周期,合成关系不能共享
依赖关系(Dependency)
是类与类之间的连接,依赖总是单向的,依赖表示一个类依赖于另一个类的定义
通常被依赖的对象以方法的参数或返回表示
迪米特法则(LoD)
Law of Demeter(LoD)又称最少知识原则
Least Knowledge Principle (LKP)
表述
only talk to your immediate friends "只与你的直接朋友通信"
Don't talk to strangers "不要与陌生人讲话"
每个软件单位对其他的单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单位
狭义的迪米特法则
如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用,如果其中一个类需要调用另一个类的某一方法的话,可以通过第三方转发这个调用
朋友的确定
当前对象本身(this)
以参量形式传入到当前对象方法的中的对象
当前对象的实例变量直接引用的对象,
当前对象的实例变量如果是一个聚集,那么聚集中的元素都是“朋友”
当前对象所创建的对象
与依赖倒转原则的互补原则
广义的迪米特法则
封装(信息隐藏)
模块将它所有的实现细节隐藏起来,彻底地将提供给外界的API 和自己的实现分割开来
模块与模块间仅通过彼此的API 相互通信,而不会理会模块内部的工件细节
控制信息过载
在类的划分上,应当创建弱耦合的类,类之间的偶合越弱,就越利于复用
在类的结构设计上,每一个类都应当尽量降低成员的访问权限(Accessibility)
在类的设计上,只要有可能,一个类应当设计成不变类
在对其他类的引用上,一个对象对其实例的引用应当降到最低
ICONIX 流程
最小建立模型技术
对于大多数问题而言,只需要使用20% 的UML ,可以完成80% 的建立模型的工作
实际中,好象总是没有足够的时间来完成建立模型分析设计工作,总是过早进入到编码阶段
足以很好地完成软件项目工作所需要的,最小的UML和建立模型的技术子集
如何从用例到代码
工作起点:
假设:
一些原型化的工作已经完成
确定了用户界面
已经开始确定系统的一些场景和用例
面向对象的系统中
代码的结构好似由类来定义的
编写代码前,必须知道所需的软件类是什么样的
类图规定了代码的结构
获得一组非常详细的,设计级别的(Design-level)类图
设计级是一种详细程度,这种级别的类图可以用做系统实际代码的模版,准确地指出如何组织代码
面向对象的软件开发中,最困难的工作之一分配行为,这需要就每个要建立的软件函数作出决策
对于每个函数必须决定将其放在那个类中
时序图将操作分配给类
时序图帮助你作出行为分配决策的理想工具
需要根据用例获得的时序图
如何跨越模糊用例与详细程度类似代码的时序图之间的鸿沟
使用健壮图他填补模糊,朦胧的用例与非常详细,精确的时序图之间的鸿沟
时序图的最上面是,特定场景涉及的一组对象
设计模式的本质论
模式是从解决具体问题抽象出俩的,这种具体问题在特定的上下文中重复出现,也就是说,每个具体形式都对一种重复的问题采用重复的解决方案
然而,模式不仅仅是解决方案,正式因为很多人认为设计模式仅仅是解决方案,所以导致设计模式的滥用和设计过度
模式不是解决方案
模式是在某种语镜中权衡各方面利弊的一种方案的选择,这种选择是这些利弊平衡的结果,获得好处的同时需要付出代价,并且结果中有利的方面,也有不利的一面
在语境中,问题出现在一种特定的上下文中,并且包含各种相互竞争的关切(Forces),目标解决方案包括对这些关切的平衡,这种关切在模式中称为作用力,这些作用力相互牵制,因此,模式不能简单看作是“特定场景的解决方案",下面的定义更符合模式的内在含义
模式是被命名的有组织的信息,他捕获了在一定语境(场景)中包含相关作用力的问题的解决方案的本质结构和内在含义,这种解决方案被证明是成功的
模式包含3个部分:相关的上下文,与上下文相关的作用系统和解决问题的方案
理解设计模式的结果而后代价
在GOf 的设计模式中充分讨论了模式的使用结果,既有好的一面,又有不好的一面,即使用模式是有代价的
1对象过多
设计模式的精髓之一是将可变的部分封装为对象,带来的饿好处是系统更加灵活,容易维护,但也增加了大量的对象,如果不恰当的使用设计模式,会使系统难于调试,下面模式比较有代表性
命令模式:将行为封装成对象,这样原来一个对象中的若干方法变成了若干命令对象,原来由一个对象完成的工作现在可能由十几个对象完成
状态模式将不同的状态封装成对象,原来可能是通过判断语句完成的工作分散到各个对象中完成,由于状态是动态决定的,因此设计测试用例时有难度
更复杂的装配关系
很多设计模式依赖对象之间的关系,因此在初始化需要执行相应的装配工作,需要装配对象的模式
生成器的模式"需要装配生成器和导航器
桥结模式:需要将代表逻辑的对象和代表实现的对象进行装配
观察者模式:需要将不同的观察者对象关联在一起
职责链模式:需要组装整条职责链
测试难度加大
这是由前面两个结果导致的饿,由于对象的增多和对象间关系的复杂,因此测试用例的设计难度加大,特别是很多逻辑上的错误可能由装配关系不当造成,并且在编译时很难发现
解决测试难度大的方法是将测试用例文挡化,即绘制测试用例的对象图,这个话题可参考相关的书籍
程序结构复杂
设计模式关注的是如何是软件更具有可维护性,因此从结构上已经与原始的需求完全不同,加上很多功能是通过对象动态组合实现的,程序的动态结构变得与静态结构同样重要
从单纯 的静态结构已经很难理解实现的方式和最终的意图了,着也是经常是使用设计模式的代价致意
设计模式不能做什么
设计模式不是法则
不能提高开发速度或者形象开发速度
不是万能的
设计模式不是法则
模式理论的精髓之一就是模式的使用一有前提和代价的模式是在某种前提下,综合各方面因素后考虑得出的结果,即在使用模式时总要是付出代价的,当然这种代价必须是可接受的,如果某个模式在所有场合中的使用都是必然的,那么他就不能叫做模式了,而是一种必须遵守的法则,例如”面向接口,而非实现编程",是法则而非模式。
不能提高开发速度或者形象开发速度
如果以一个开发周期作为考核标准,恐怕没有人会使用设计模式,设计模式并不能提高目前的开发速度,至少其关注的目标并不是开发速度,很多情况下甚至会降低开发速度,即使是正确选择了设计模式
这是因为设计模式可能回引入更多的对象和更复杂的对象装配关系,从而似的程序更多的动态状态,从局部看来边的结构复杂,难以理解并且测试困难,如果仅仅关注形象速度,或则能够百分之百地确定需求没有变化,那么设计模式并不是很好的选择
不是万能的
设计模式的使用是自然而燃的事,很多情况下不使用设计模式是因为不需要,问题很没有复杂到非用不可的程度,我们是为了设计而使用设计模式,而不是为了使用设计模式而设计
当你的项目发现有如下的问题之一时,就需要考虑重构代码,可能会有某种模式适合
代码无法进行单元测试
需求的变动总是导致代码的变动
有重复代码存在
继承层次太多了
隐藏的依赖过多
设计模式与架构模式
软件顶层架构的设计
方法
结合实际需求,选取架构模式,在进行局部调整
主要架构模式:
流程处理模式
客户/服务器模式
模型-视图-控制器的模式
分层模式
流程处理模式
流程处理系统以算法和数据结构为中心,其系统功能由一系列的处理步骤构成,相临的处理步骤用 数据流管道连接
流程处理模式适用于批处理方式的软件系统,不适合交互是交互式系统
流程处理模式
流程处理模式有三个处理步骤
步骤都使用公共的系统服务,(例如数据库访问服务,命令处理和 命令处理的进度,结果都通过用户界面
界面
前处理器 问题求解器 后处理器
系统服务
客户/服务器模式
客户端负责用户输入和处理结果的呈现,服务端负责后台业务处理
客户端 客户端
服务器
模型-视图-控制器(MVC) 模式
模型-视图-控制器模式
软件系统由模型,视图,控制器三部分组成
模型负责维护并保存具有持久性的业务数据,实现业务处理功能,并将业务数据的变化情况及时通知视图
视图负责呈现模型包含的业务数据,响应模型变化通知,更新呈现形式,向控制器传递用户的界面动作
控制器负责用户的界面动作影射为模型中的业务处理功能并实际调用之,然后根据模型返回的业务处理结果选择新的视图
分层模式
将整个软件系统分为若干层次,最顶层直接面向用户提供软件系统的操作界面,其余各层为紧邻其上的层次提供服务
分层模式可以有效降低软件系统的耦合度,应用普遍
层次划分原则
易变化的部分,如用户界面,与业务逻辑紧密相连的部件,放到高层
稳定的部分,如公共的技术服务,放到低层
每层都尽量访问紧邻的下层,避免越级访问,尤其要避免逆向访问,上层模块为下层模块提供服务
将目标软件系统的外部接口放到较低层次,系统其余部分对外部系统的访问或操作通过这些外部接口提供服务来完成
软件架构
在全面了解软件架构的前提下,对于具体的应用需求而言,影响顶层架构选取的主要因素在于分析人员的经验以及他们对每种架构样式与软件项目之间匹配程度的判断
大型软件系统的顶层架构往往需要使用多种架构样式,如,整个目标软件系统 采用分层结构,在系统的不同层次内在分别使用适宜的其他类型的架构模式
确立软件架构考虑的因素
架构中包的数量
包中软件元素过多,应对包进一步细分;如果过少,则说明架构过早陷入细节
架构中包的耦合度
包的依赖关系,连接关系应尽量简单,松散简单,,如分层结构中,通常要求某一层的软件元素只与同层次及下一层的元素存在依赖关系
软件元素的稳定性
抽取不稳定的元素的相对稳定部分,将不稳定的软件元素聚集在少数几个包中,以提高软件系统的可维护性
确立软件架构
软件元素的分类
将软件的可选功能和必须实现功能的软件元素分别放到不同包或子包中
作为软件系统运行环境的物理网络拓扑
根据软件元素在分布环境中的布局,划分顶层架构的包,是包的消息传递与物理节点的通信相协调,顶层架构定义的通信关系支持后续的分析和设计活动
确定软件架构
软件元素的安全,保密级别
根据安全访问的权限划分顶层架构中的包或者子包
开发团队的技术专长
根据开发人员在问题和技术领域的专长划分顶层架构,使得每个包的开发都能充分发挥开发和团队的技术专长
调整软件架构,支持并行开发
AOP 开发实践
AOP 概述
使用AOP实现松散耦合
使用AOP 组合两个业务逻辑
对象代理和过滤器
结论
什么是AOP
AOP 是Aspect Oriented Programming 的缩写
中文翻译为面向方面的编程,其核心内容就是所谓的“横切关注点"
OO都是纵向的结构
使用面向对象方法构建软件系统,我们可以利用 OO的特性,很好的解决纵向的问题,因为OO的核心概念,如继承等,都是纵向结构的
AOP目标
但是在软件系统中,往往有很多模块,或者很多类共享某个行为,或者说,某个行为存在于软件的各个部分中,这个行为可以看作是”横向“存在软件之中,他所关注的是软件的各个部分的一些共有的行为,而且,在很多情况下,这种行为不属于业务处理逻辑的一部分
例如,操作日志的记录,这种操作并不是业务逻辑调用的必须部分,但是,我们却往往不得在代码中显示调用,并承担由此带来的后果,(例如,当日志记录的接口发生变化时,不得不对调用代码进行修改
这种问题使用传统的OO方法是很难解决的,AOP的目标,便是要将这些”横切关注点 “与业务逻辑代码相分离,从而得到更好的软件结构以及性能,稳定性等方面的好处
关注点切割图
纵向关注点
软件模块 软件模块 软件模块 软件模块
操作日志
安全检测 横切关注点
业
务
数
据
事务处理
AOP 的自动耦合
AOP 给我们的软件设计带来了一个新的视角和架构方法,使用 AOP ,我们可以专注于业务逻辑代码的编写,而将诸如日志记录,安全检测等系统功能交由AOP 框架
在运行时刻自动耦合进来
使用AOP 技术的情景
Authentication 权限
Caching 缓存
Context passing 内容传递
Error Handling 错误处理
Lazy loading ;懒加载
Debugging 调试
Logging ,tracing ,profing and monitoring (记录追踪,优化,较准)
Performance optimization 性能优化
Persistence 持久化
Resource pooling 资源池
Synchronization 同步
Transactions 事务
AOP 概述
使用AOP 实现松散耦合
使用AOP 组合两个业务逻辑
对象代理和过滤器
结论
Websharp Aspect
我们选用这个开放源代码的Web Sharp Aspect 框架。这个框架是基于Microsoft .net 平台的,并且是使用C#语言开发的,所以,下面的示例代码使用了C#相关的语法
关于这个框架的说明以及源代码,可以从以下地址下载www.websharp.org
对于应用软件来说,权限控制是一个常见的例子,为了得到好的程序结构,通常使用OO的方法,将权限校验过程封装在一个类中,这个类包含了一个校验权限的代码
Public class Security
{
public bool CheckRight(User CurrentUser,Model accesModel, OperationType operation)
{
...//校验权限
}
}
然后,在业务逻辑过程中进行如下调用
public class BusinessClass
{
public void BusinessMethod()
{
Security s =new Security();
if (! s.CheckRight(......))
{
return;
}
...//执行业务处理逻辑
}
}
OO设计的问题
这种方法在OO 设计中,是常见的做法,但是这种做法会带来以下问题
不清晰的业务处理逻辑,在某种意义上来说,权限校验过程并不是业务逻辑执行的一部分,这个工作是属于系统的,但是,在这种情况下,我们不得不把系统的权限校验过程和业务逻辑执行过程搀杂在一起,造成代码的混乱
代码浪费,使用这种方法,我们必须所有的业务逻辑代码中用Security 类,似的同样校验的代码充斥整个软件中,显然不是很好的现象
紧耦合:使用这种方法,我们必须在业务逻辑只能显示引用Security 类,这就造成了业务逻辑代码同Security 类的紧密偶合,这意味着,当Security 发生变化时,例如 ,当系统进化时,需要对CheckRight 的方法进行改动,可能回影响到所有引用的嗲吗,下面的所有问题都是由此而来
不易扩展:在这里,我们只是在业务逻辑填加了权限校验,那一天,当我们需要填加额外的功能,例如日志记录功能的时候,我们不得不把同样在所有的业务逻辑代码中填加这个功能
不灵活,有的时候,由于某些特定的需要,我们需要暂时禁止,或者填加某项功能,采用传统的如上述的做法,我们不得不采用修改代码的方式来实现
为了解决这些问题,我们通常会采用诸如设计模式等方式,对上面的方案进行改进,这往往需要很好的技巧
利用AOP,我们可以很方便的解决上述问题
我们以Websharp Aspect 为例,看看如何来对上面的代码进行改动,以获得一个更好的系统结构
首先,Security 并不需要做任何修改
然后,我们对BusinessClass做一个小小的改动
为BusinessClass添加一个名为AspectManaged的属性,并使得BusinessClass继承AspectObject ,然后,删除代码中对Security 的调用,这样,我们的代码就变成了如下的样子
[AspectManaged(true)]
public class BusinessClass:AspectObject
{
public void BusinessMethod()
{
......//执行业务逻辑
}
}
然后,我们为系统增加一个SecurityAspect
public class SecurityAspect:IAspect
{
public void Execute (object[] paramList)
{
if (!Security.CheckRight(.......))
{
throw new SecurityException("你没有权限!");
}
}
最后,我们在系统配置文件中添加必要的信息
<Websharp.Aspects>
<Aspect type="MyAPP.SecurityAspect,MyAPP="deploy-model="signleton"
pointcut-type="Method" action-position="before" match="*,"/>
</Websharp.Aspects>
我们完成了代码重构,当BusinessClass被调用的时候
AOP框架会自动BusinessClass的BusinessMethod 方法,并调用相应的权限校验方式
采用这种方式,我们在 BusinessClass 中没有显示引用Security类及其方法,并且,在所有业务逻辑代码中,都没有必要引用Security 类
这样,借助AOP 机制,我们就实现了BusinessClass和Security 类的松散耦合,上面列出的所有问题都应刃而解,同时,这也是一种易于扩展的机制,例如,当我们需要添加相应的Aspect 类,然后在配置文件中进行配置即可,而无须对业务逻辑代码进行任何改动
使用AOP 组合两个业务逻辑
使用AOP 我们不仅可以用来分离系统功能和业务逻辑就向上面我们做的那样,也可以用来耦合不同的业务逻辑,得到更加灵活的软件结构,下面,我们通过一个具体的方案,来看看怎么通过AOP,组合两个业务逻辑过程
我们假设有如下一个场景
我们设计了一个ERP系统,其中,库存管理系统需要同财务系统相交互,例如,当某个库存商品报废的时候需要有相应的财务处理过程,因此,我们通常需要在库存商报废的业务逻辑中引用相关的财务处理逻辑,着必然会造成两个部分的耦合,当然,为了使两个部分尽量耦合程度降低,我们通常会使用Facade 等设计模式来进行解耦
由于某些原因,我们需要将库存管理系统单独出售,这就需要我们从库存商品报废的业务逻辑中将引用的相关财务处理逻辑去除,这意味着我们需要修改原有的代码
为了解决这个问题,即可以随时将财务处理逻辑添加或者从库存商品报废的业务逻辑中删除,我们可以采用一些方法,例如,设置一些开关参数,在库存商品报废的业务逻辑中,根据这些开关参数的值,来判断是否需要执行财务处理逻辑
问题是,着仍旧不是一个理想的解决方案,采用这种方式,你必须事先知道所有需要设置的开关参数,并且,在业务逻辑代码中添加相应的判断
当为系统增加一个类似的需要灵活处理的部分时,开发人员不得不添加相关的参数,并且修改相应的代码(添加相应的判断代码)
修改代码总是不好的事情,因为按照软件工程的要求,当有新的需求是,尽量不要修改原来的饿代码,而是增加相应的代码,但是,在这种情况下,你做不到
使用 AOP我们可以通过一种更加自然的方式来实现这个目标,基本方法是
首先,编写相关的库存商品报销业务逻辑,不需要添加任何其他的内容,并且,把这个逻辑的代码设置为可AOP的
其次,编写财务处理逻辑
添加一个把库存商品报废业务逻辑和财务处理逻辑组合起来的Aspect 这个Aspect 可以拦截库存商品报废业务逻辑的执行,动态的加入财务处理逻辑的过程,并且,在配置文件进行配置。
这样,我们通过一个Aspect 组合了着两个业务逻辑,并且我们随时可以通过修改配置文件的方式把财务处理从库存商品报废业务逻辑中去除,而不用修改任何代码
采用AOP的好处是,我们可以独立的编写各个业务逻辑,似的系统各个部分之间的耦合度降到最低,然后,可以在系统中根据需要随时组合两个逻辑,而不用修改原来的代码
对象代理和过滤器
应该认识到,完全AOP实现的,需要开发语言的支持,因为对于AOP 的研究,还正在进行之中,目前的开发语言,都还没有完全支持AOP 的,但是我们可以利用现有的一些语言功能,来实现AOP的部分功能
上面所举的例子,在实现上,是利用了对象代理(Proxy)机制,所谓Proxy,就是”为其他对象提供一种代理以控制对这个对象的访问"
在WebsharpAspect 中当,一个对象被标记为Aspectmanaged后,这个类的实例的创建过程,以及方法的 调用会被WebSharpAspect 控制,因此,当你调用如下语句,
BusinessClass bc=new BusinessClass();
你得到的实际不是BusinessClass类的实例,而是他的一个代理,
因此当调用这个实例的方法的时候,所有的调用都会被代理所捕获,代理会在实际的方法调用之前,透明的执行一些预定义的操作,然后在执行实际的方法,最后,在实际的方法调用之后,在执行一些预定义的操作,这样,就实现了AOP功能
注意,AOP并不仅仅等同于方法拦截,当然,着也是最常用和非常有效的AOP功能
在某些开发中,我们可能使用过滤器来完成某些AOP功能,例如,当用户访问某些资源时,我们可以对访问信息进行一些过滤处理。一个常见的场景是,在JSP的开发中,为了实现对中文的正确处理,以获得正确的文字编码,在每个Request 中进行手工进行转码肯定不是一个好的解决方案
一个比较好的例子是,是为应用程序编写一个Filter,自动进行转码处理,例如,我们可以为TOMCAT写如下一个过滤器来实现转码
public class SetCharacterEncodingFilter implements Filter
{
public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain)
{
request.setCharacterEncoding("gb2312");
chain.doFilter(request,response);
}
}
这样我们就不必在具体业务处理中进行手工的转码
,实现业务逻辑同转码这样的系统功能的分离
目前,常见的 Web服务器都提供类似的机制,例如,在IIS中,也可以使用过滤器功能,传统的开发方式是根据使用VC 开发一个ISAPI Filter ,在.net 发布后,可以使用HttpHandler和HttpModule 实现相同的功能,但是,开发难度要低得多
使用过滤器的另外的一个场景,例如,在客户请求某个Web 方面的时候,可以使用过滤器拦截这个请求,然后,判断这个用户是否具备对请求资源的访问权限 ,如果是那么,过滤器可以把这个请求放过去,什么都不做,否则,过滤器可以重定向到某个页面,告诉用户不能访问的原因,或者,直接抛出异常,又由前面的处理者处理,通过这种方式,我们可以同样的分离诸如身份验证这样的系统功能和业务逻辑,实现更好的系统结构
通过象Web服务器这样的应用程序环境提供的功能,我们还可以实现起他一些AOP的功能,构建更好的系统况架
结论
AOP给了我们一个新的视角来看待软件的架构,有的时候,即使不使用AOP技术, 只使用AOP 的某些观念和现有的技术来搭建系统架构,对我们也是非常有益的
}
面向方面的软件开发方法
需求开发的主要困难和对策
面向对象开发技术与开发规范范型变迁
横切关注点
横切关注点的建模与分离
弹性体系结构演变
AOSD 的应用
软件开发范型的变化
Code-Fix模型 -最原始的开发方式
程序越来越大,难以掌握-软件危机
结构化开发:SA,SD,SP -自顶向下,逐层分解
数据与方法分离,内聚性不够-与现实世界模型不一致
面向对象开发 :OOA,OOD,OOP-现实世界真实反映
其它:数据流理论
面向对象开发技术的核心特点
结构化理论:将应用分解为功能模块,子功能模块,功能接口,与现实问题领域的东西没有直接联系
面向对象理论:系统模型是对问题领域的直接映射,即从现实世界中直接抽象出一个模型,然后在计算机实现出来
面向对象开发技术的历史变迁
面向对象编程开启了面向对象的发展之门
而面向对象分析,设计方法才是OO思想的真正标志
面向对象开发技术的今天-核心基础
核心基础:组件技术,UML建模技术
组件技术:大型项目与系统的必由之路
需要支持平台:SOA,ESB-连接组件
拥有大量组件:重用 ,MDA-快速,廉价集成组件
响应日益复杂的业务操作:EA(连通软件与业务的鸿沟PLE(处理产品线可变性),反向工程工具(重用遗留系统)
框架:J2ee,.net 等
独立与厂商的组件描述语言-UML
面向对象开发技术的今天-最佳实践
显然仅有组件和UML是不够的,因为我们还需要知道如何捕获组件,答案就是最佳实践
->跌代开发
->体系结构为中心
->用例驱动
横切关注点
恩,一切似乎完美,是什么打破了这一宁静
横切关注点是打乱这一规则的“破坏分子"
横切关注点包括两类:
扩展:在基组件之上定义的组件,他用来表示附加的服务或功能非功能属性-AOP原先发现
对等关注点:相互独立的功能点,各组件中参与类有较大的交叠-IVar博士的补充发现弥补用例分析与实现的鸿沟
AOP就是基于对非功能属性实现中发现的"重复"
例如:留存,事务处理,安全,性能优化,错误处理,日志,调试,度量等
对等关注点
各个组件包含满足不同关注点的实现缠绕状态
某个特定的关注点分散在多个组件中-分散状态
横切关注点现行实行的不足
横切关注点1-扩展
->代码的大量重复,涉及到多个功能性类
->当横切关注点的饿需求发生变化时,会造成大量修改
->横切关注点的更新难以实现一致性
横切关注点2->对等关注点
->捕获对等功能点的用例本身就涉及多个类,容易使分析或设计的结果不能够有效的对应起来,影响了跟踪
->功能的修改,可能涉及多个类,影响系统的弹性
->原有的用例建摸在管理横切关注点存在问题
本质:合成机制,分离横切关注点的方法
->可以实现将类之外的附加行为合并到类本身
_>可以在编译是或运行时进行
->可以将不同的关注点的实现分离到不同的模块中
核心概念
->aspect:核心类元,模块化单元
->intertype:aspect 的方法,定义”原有类名.新操作名"-类扩展
->pointcut:在aspect中说明原有类中的扩展点(连接点)-操作扩展
->advice :捕获pointcut出现的特定事件
基于用例对横切关注点的建模
用例是对横切关注点的建模型的最好工具
用例描述的 关键是事件流
基于用例捕获横切关注点
应用(application)用例和基础架构(Infrastructure)用例
理解涉众关注点
->理解问题域(领域类,领域模型)
->抽取系统特性 (Feature List)
->处理功能和非功能需求(应用用例,基础结构用例)
捕获应用用例
->从特性中识别出参与者,合并为用例
->识别用例变量,并处理用例变量
->处理扩展用例
捕获基础结构用例
->抽象为<执行事务>用例对基本事务进行建模
->基础结构用例的结构化,描述基础结构用例
->处理系统范围的关注点
用例切点
用例的实现是协作
协作表识了类和类的扩展
用例切片包括:协作,(交互图,类图),特定的类,特定的扩展
基于起用例实现切片
合并特定于某用例的类
合并用例特定的类扩展
基于切片组成系统
通过用例切片(Use case slice)和非特定用例切片(non-us_specific slice)来叠加系统
用例模块
对于某个用例而然,都包括不同的模型(用例描述,分析,设计,实现,测试设计,测试实现),每个模型都可以组可以组成个切片,而将这些切片放在单独包内中,就称为用例模块
用例描述模块<------分析切片<--------设计切片<---------实现切片
测试用例切片<-------------测试实现切片
架构(Architecture)
什么是架构(体系结构)
系统元素如何组织?
系统如何实现所需功能?
系统如何满足预测性能,可靠性和其他质量特性
系统需要什么技术
系统内部组织的结构是否能够弹性响应功能,技术,平台变化
表准是否能够确保系统开发始终保持一致,采用什么设计模式
什么是好的架构
分离功能需求
从功能需求分离出非功能需求
分离平台特性
待测试从已测单元分离出来
架构基线
:最终系统的早期版本,Skinny System!
包含了最终系统所具有的子系统,组件和 接点的骨架
UP 过程中,这一任务主要是在精化阶段完成
用例驱动架构基线,寻找出关键用例子集
演练了系统的关键功能和特性
涵盖了大部分的功能性,基础结构,平台特性等方面的风险
突出了系统中的一些具有高复杂度或高风险的部分
是系统剩余部分的基础
迭代地建立架构基线
平台无关的结构(PIM)
元素结构:基于包和类的分层结构
组成部分主要是领域相关的类
通常包括“应用层”和“领域层"
应用层的元素主要实现了支持系统的主要参与者的工作流
领域层则要包括了描述重要领域概念的元素
用例结构:在元素机构的基础上添加了实际结构
叠加平台相关特性(PSM)
选择平台
系统平台特性基于架构师选定的部署结构和进层结构
我们需要将平台特性与平台无关的部分分离-最小化用例设计
可执行,并采用默认编程语言实现
是通过程序接口来激活的
分布性,内部进程的通信和平台相关消息通信与其分离
所许的信息都在内存中
使功能需求保持分离
分离功能需求的最好办法是用例 什么是独立用例的,什么是应用通用的,什么是领域通用的,什么是领域特定的
这些问题的答案用于指导:如何将类归入层,包,如果将类扩展归入到相应的切片,模型
应用用例的分析中
考虑用例规约,必要时进行更新
分析用例:识别出参与用例实现的分析类,并将行为分配给这些类
在系统元素结构中将类组织成包和层,在用例结构中将类和类扩展组织成切片
分析元素映射为设计元素,识别出接口及附加的设计元素
使功能需求在分析模型中保持独立
根据要参与实现的用例,形成合适的元素结构
将用例结构分为:针对某个特定用例行为的“用例切片”,不属于特定的某个用例的“非用例特定切片”
使功能需求保持分离
应用用例设计
识别设计元素,根据实现需要引入新的设计元素
识别组件和接口:将分析行为中的一部分演化为设计组件
完善设计元素
使类扩展保持分离
是功能需求在设计模型中保持独立
是操作扩展保持独立
总合:两个用例切片需要从相同操作得到不同的输出,并且操作的职责是提供两种输出的合并
选择:当用例切片需要从同一个操作得到不同的输出,并且要求组合结果只有一种输出
操作扩展声名包括
结构上下文:说明哪个操作是要增加的
行为上下文:说明扩展何时执行
说明附加行为
使扩展的功能需求保持分离
面向方面技术能够使我们更好地在原有系统上进行扩展
该扩展流程应该在Pointcut UpdatingRoomAvailability返回没有空房
系统建立一个针对特定房间类型的唯一带标识符返回给客户,用例结束
识别PointCut ,并将用例行为分配给类
->识别结构上下文, 确定在何处运行这些操作扩展系统调用扩展实例
识别行为上下文,定义职责中的何处需要调用
因此,得到了一个独立的用例切片的完成该扩展用例
保持非功能需求分离
分离非功能需求最有效的工具是基础结构应用
识别类
识别Pointcut
将用例行为分配给类
使基础结构保持分离
细化元素结构
在用例的切片中使基础结构保持分离
AOSD的
保持关注点分离带来的生产率提高
假设某系统有N个独立的需求,假设每个的工作量需X,则总工作量就是NX
若N个独立的需求未良好分离,就意味着每个需求的实现与其他需求的饿实现相互交迭,最坏时可能每个需求的实现与N-1个需求相关,如果交迭开发量Y着任务量就成了NX+N(N-1)Y
随着Y值的增加,未良好分离的体系结构就会带来越大的成本
从何处入手
用例建模与分析:对涉众关注点的正确性和精确性是什么重要的,用例建摸与分析适用于任何软件开发,不管是面向方面的,面向对象还是其他的,建议针对基础结构服务编写用例,建议多练习,编写出客户和开发团队都易于理解的有效用例
设计和实现:用例切片,用例结构,AOP都比较新,需要学习如何对Aspect 和用户切片建模,如何描述Pointcut,建议选择一个适用该方法解决的特定的关注点,通过用例来描述她 ,并从此驱动到编码,测试的全过程
测试,基于用例切片,可以很轻松地将测试引入的控制和工具代码轻松地除
在项目的不同阶段采用
计划阶段:很容易着手,从需求开始,从头贯穿AOSD
细化阶段前期:已经完成了一部分迭代,有一些可以工作的用例和几个基础结构服务,则可以在没有开发的部分上应用用例切片,对已开发的基础结构服务可以考虑重新设计用例切片是否有价值
细化阶段后期:如果已有一个可靠的架构,基本上不建议做修订和改变,但可靠仪考虑用参数化pointcut 来帮助你把基础结构服务和平台特性融合到系统中,还可以使用AspectJ来判断层包之间是否存在依赖注入
构建阶段:如果项目接近尾声,不必有太大的改变,可以考虑会该方法进行测试
完善阶段:可以用来对原系统更好的进行扩展。
基于 SOA的架构设计
服务的设计与原则
面向服务架构的消息模式
评估基于服务的集成技术的过程和准则
服务模式和反模式
Web 服务的体系结构
改善Web服务的协同工作能力
应用软件开发方法的演变过程
应用软件开发方法的演变过程
面向过程
面向对象
面向组件
面向服务
什么是面向服务的体系架构
一个组件模型
将应用程序的不同功能单元(服务)通过这些服务之间的定义良好的接口和契约联系起来的,接口是采用中立的方式进行定义的,他应该独立于实现服务的硬件平台,操作系统和编程语言
构建在各种这样的系统中的服务可以以一种统一和通用的方式进行交互
服务的设计与原则
Service-oriented Architecture
SOA (service-oriented Architecture:也叫面向服务,的体系结构或面向服务架构)是指为了解决Internet 环境下业务集成的需要,通过连接能完成特定任务的独立功能实体实现服务的硬件平台,操作系统和编程语言。这使得构建在各种这样的系统中的服务可以以一种统一和通用的方式进行交互
传统的Web (HTML/HTTP)技术有效的解决了人与信息系统的交互和沟通问题,极大的促进了 B2C模式的发展。
WEB服务(XML/SOAP/WSDL)技术则是要有效的解决信息系统之间的交互和沟通问题,促进B2B/EAI/CB2C的发展
SOA(面向服务的体系)则是采用面向服务的商业建模技术和Web服务技术, 实现系统之间的松耦合,实现系统之间的整合和协同,Web服务和 SOA的本质思路在于似的信息系统个体在能够沟通的基础上形成协同工作。
对于面向同步和异步应用的,基于请求/响应模式的分布式计算来说,SOA是一场革命。一个应用程序的业务逻辑(Business Logic)或某些单独的功能被模块化作为服务呈现给消费者或客户端。这些服务的关键是他们的松耦合特性
例如,服务的接口和实现和实现相独立。应用开发人员或者系统 集成者可以通过组合一个或多个服务来构建应用,而无须理解服务的低层实现,举例来说,一个服务可以用,Net或J2EE来实现,而使用该服务的应用程序可以在不同的平台之上,使用的语言也可以不同
SOA具有的特性
SOA服务具有平台独立的自我描述XML文档,Web 服务描述语言(WSDL, Web Service Description Lanuage)是用于描述服务的标准语言
SOA服务用消息进行通信,该消息通常使用XML Schema 来定义(也叫做XSD,XML Schema Definition).消费者和提供者或消费者和服务之间的通信多见于不知道提供者的环境中。服务间的通讯也可以看作企业内部处理的关键商业文档
在一个企业的内部,SOA服务通过一个扮演目录列表(Directory listing )角色登记处(Registry) 来进行维护,应用程序在登记处(Registry)寻找并调用某项服务,统一描述,定义和集成(UDDI,Universal Description ,Definition and Integration )服务登记的标准
每项SOA服务都有一个与之相关的服务品质(QOS ,quality of service).QOS 的一些关键元素有安全需求(例如认证和授权),可靠通信(译注,可靠消息是指确保消息“仅且仅仅”发送一次,从而过滤重复信息。),以及谁能调用服务的策略
SOA三大基本特征
独立的功能实体
在Internet 这样松散的使用环境中,任何访问请求可能出错,因此任何企图通过Internet 进行控制的结构都会面临严重的稳定性问题.SOA非常强调架构中提供服务的功能实体的完全的独立自主的能力,传统的 组件技术,如.net Remoting EJB,com 或者CORBA 都需要有一个宿主来存放和管理这些功能实体,当这些宿主运行结束时这些组件的寿命也结束,这样当宿主本身或者其他功能部分出现问题的时候,在该宿主上运行的其他服务就会受到影响
SOA架构中非常强调实体自我管理和恢复能力,常见的用来进行自我恢复击技术,比如事务处理,消息队列,冗余部署,和集群系统在SOA中都起到至关重要的作用
大数据量的低频率访问
对于 .net Remoting EJB或者XML-RPC这些传统的分布式计算模型而然,他们的服务 提供都是通过函数调用的方式进行的 ,一个功能的完成往往需要通过客户端和服务器来回多次函数调用完成,在intranet 的环境下,这些调用给系统的响应速度和稳定性带来的影响都可以忽略不计,但是在Internet 环境下这些因素往往是决定整个系统是否能正常工作的一个关键决定因素,因此SOA系统推荐采用大数据量的方式一次性进行信息交换
基于文本的信息传递
由于Internet 中大量异构系统的存在决定了 SOA 系统必须采用基于文本而非二进制的消息传递方式,在COM,CORBA 这些传统的组件模型中,从服务器端传往客户端的一个二进制编码的对象,在客户端通过调用这个对象的方法来完成某些功能;但是在Internet 环境下,不同语言,不同平台,对不同数据,甚至是一些基本数据类型的定义不同,给不同的服务之间传递对象带来了很大困难
由于基于文本的消息本身是不包含任何处理逻辑和数据类型的,因此服务间只传递文本,对数据的处理依赖接收端的方式可以帮忙绕过兼容性这个的大泥坑
此外,对于一个服务来说,Internet 与局域网最大的一个区别就是在internet 上的版本管理极其困难,传统软件采用的升级的方式在这种松散的分布式环境中几乎无法进行,采用基于文本的消息传递方式,数据处理可以只选择性的处理自己理解的那部分呢数据,而忽略其他的数据,从而得到非常理想的兼容性。
面向服务架构(SOA)的原则
SOA的强大和灵活性将给企业带来巨大的好处,如果某组织将其IT架构抽象出来,将其功能以粗颗粒度的服务形式表示出来,每种服务器清晰地表示 其业务价值,那么,这些服务的顾客(可以是公司内部,也可能是公司的某个业务伙伴)就可以得到这些服务,而不必考虑其后台实现具体技术,更进一步,如果顾客能够发现并绑定可用的服务,那么,在这些服务器背后的IT系统能够提供强大的灵活性,
但是,要得到种强大和灵活性,需要一种实现架构的新方法,这是一项艰巨的任务。企业架构设计师必须要变成“面向服务的架构设计师”不仅要理解SOA,还有理解SOA的实现,在架构实现和最后得到的架构结果之间的区别非常微妙,也非常关键,本文将讨论 SOA的实践,即:面向架构的设计师在构建 SOA必须考虑的事情
SOA原则,
SOA是一种企业架构,因此,他是从企业的需求开始的,但是SOA和其他企业架构方法的不同之处在于SOA提供的业务敏捷性,业务敏捷性是指对企业对变更快速和有效地进行响应,并且利用变更来得到竞争优势的能力
对架构设计师来说,创建一个业务敏捷的架构意味这创建这样一个IT架构,他可以满足当前还未知的业务需求
要满足这种业务敏捷性,SOA 的实践必须遵循以下原则:
业务驱动服务,服务驱动技术
从本质上来说,在抽象的层次上,服务位于业务和技术中间,面向服务的架构设计师一方面必须理解在业务需求和可以提供的服务之间的动态关系,另一方面,同样要理解服务与提供这些服务的低层技术之间的关系
业务敏捷是基本的业务需求
SOA考虑的是下一个抽象层次,提供响应变化需求的能力是的新的“元需求“,而不是处理一些业务上的固定不变的需求,从硬件系统而上的整个架构都必须满足业务敏捷的需求,因为,在SOA中,任何的瓶颈影响到整个IT环境的灵活性
一个成功的SOA总在变化之中
SOA的工作场景,更象是一个活的生物体,而不是象传统所说的盖一栋房子”,IT环境唯一不变的就是变化,因此面向服务架构设计师的工作永远不会结束,对于习惯盖房子的设计师来说,要转向设计一个活动的生物体要求崭新的思维方式,如下文所写的 SOA的基础还是一些类似的架构准则。
SOA基础
在IT行业有两个越来越普遍的发展方向,一个是架构方面的,一个是方法学方面的,面向服务的架构设计师可以从中有所收获,第一个就是MDA(模型驱动框架),由提出CORBA的OMG模型提出。MDA认为架构设计师首先要对待创建的系统有一个形式化的UML(也是由OMG提出)的模型,MDA首先 给出一个平台无关的模型来表示系统的功能需求和Use Cases ,根据系统搭建的平台,架构设计师可以由这个平台无关的模型得到平台相关的模型,这些平台相关的模型足够详细,以至于可以用来直接生成需要的代码。
MDA的核心就在于设计阶段系统 就已经完全描述,这样,在创建系统的时候,几乎就没有错误解释的可能,模型也就是可以直接生成代码,但MDA 有一些局限性,首先,MDA假设在创建模型之前,业务需求已经全部描述,而这一点,在当前模型的动态业务环境中几乎是不可能的,第二,MDA没有一个反馈机制,如果开发人员对模型有需要改动的地方,并没有提供给他们这么一个途径。
SOA的另一个基础是敏捷方法(AM),其中非常有名的方法是极限编程(XP),象XP这样的AM提供了在需求未知或者多变的环境中创建软件系统的过程。XP要求在开发团队中要有一个用户代表,他帮助书写测试来指导开发人员的日常工作,开发团队中所有成员都参与到设计中去,并且设计要尽量小并且非形式化, AM的目标是仅仅创建用户想要的,而不是在一些形式化模型上耗费工作量。AM的核心思想就在于其敏捷性-处理需求模型上耗费工作量
AM的核心思想就在于其敏捷性-处理需求变更的敏捷性,AM的主要弱点在其规模上的限制,例如,XP在一个小团队和中型项目中效果不错,但是当项目规模增大时,如果没有一个一致的清晰的计划,项目成员很难把握项目中的方方面面
从表面看来,MDA 和AM似乎是相对立的-MDA假定需求是固定的,而AM恰恰相反,MDA的中心是形式化的模型 ,而AM要避开他们,但是,我们还是决定把冒险把这些不同方法中的一些元素提取出来,放入到一个一致的架构实践中
在SOA中有三个抽象层次,按照SOA的第一条准则:业务驱动服务,服务驱动技术,Am将业务模型直接和实践连接起来,表现在平台相关的模型之中,MDA并没有把业务模型和平台无关模型分开来,而是把平台无关模型作为起点,SOA必须连接这些模型,或者所抽象层次,得到单一的架构方法,我们将从五个视图的架构实现方法来实现这个连接
SOA的五视图的实现方法
企业架构设计师发现他们的职业非常有竞争力并且值得骄傲,因为他们要从很多方面来通盘考虑IT系统。Kruchten (RUP的开发负责人)将这些方面提取出来,在应用到SOA时,我们称为五视图实现方法(fiveview approach)
四个方框表示对一个框架的不同审视方法,分别代表不同的涉众(stakeholder),第五个视图, use-case 视图涵盖了其他视图,在架构中扮演的是一个特殊的角色,部署试图将软件映射到低层平台和相关硬件上,是系统部署人员对架构的视图,业务分析人员则利用过程视图进行工作,他描述的是软件系统的运行时特性,最后,逻辑视图表示的是用户的功能需求,在SOA中,面向服务的架构必须能够以Use-case 视图中的用例将用户连接到服务,将服务连接到低层的技术
为了表示面向对象的架构是如何工作在这些视图的之上,让我们将他们至于SOA的模型上下文中。SOA中两个领域存在重叠,由业务模型和服务模型表示的业务领域和由服务模型及平台相关模型表示的技术领域(两个领域共享服务模型),业务用户通过逻辑视图和过程视图处理粗粒度的业务服务,根据变化的业务需求,按照需要将他们安排过程只中,另一方面,技术专家的工作是创建并维护服务和地层技术之间的抽象层。表示这些服务的中间模型,起到的是轴心的作用,业务以它为中心进行
SOA元模型从MDA中继承平台无关模型和平台相关模型,但是添加了AM和用户交互以及敏捷的反馈这两部分,后者通过椭圆之间的双向箭头来表现,类似地,元模型通过引入由中心的服务模型提供的中间层抽象解决了 AM 在伸缩性方面的问题,这样,服务模型中的任何需求变化,都会反映到用户每天的业务处理中,同样,由于低层技术模型驱动的,技术专家也可以根据这些变化的需求迅速而有效地作出应变。
SOA实践和过去解决企业架构传统方式的不同之处就在于其对敏捷性的支持,如前所说,SOA的第三条原则就在于他总在变化之中,这种恒在的变化性能环境是SOA实践的基石。涉众在一个必须的基础上影响到整个架构的变化,在当技术专家在每天的日常工作中不断对变化的业务需求作出响应的这种情况下,设计阶段和运行阶段之间的界限变得模糊起来,很难清晰地分离这两个阶段,我们已经为面向服务的架构提供了一个高层次的框架,其中MDA和Am的元素帮助工具的使用者来创建和维护SOA,但是,SOA中还缺少一些内容一那就是软件开发商和专业服务组织必须提供的,理想情况下,开发商必须提供面向服务的业务流程,工作流以及服务的协调工具和服务;;另外,能够以一种敏捷的,平台无关的方式充分反映业务服务的建模工具也是必须的;;技术专家必须配备可以从模型中自动生成代码,并在代码变化时更新模型的工具,最后,开发商必须提供支持SOA的软件,帮助面向服务的架构设计师以一种可信并且可伸缩的方式创建位于服务和低层技术之间的抽象层次,幸运的是,这方面的产品即将上市
另外,最重要的就是贯穿本文的自顶而下的SOA实现方法了,今天关于Web Services 的大部分思考都是自底而上的:“这是如何创建Web Service 的方法现在,我们来使用他们集成吧“,对Web Services 技术的这种方法是伟大的第一步,因为他可以惊人地降低集成的开销,这是现在的技术管理人员最乐意见到的了,但当经济进一步发展,IT走出低谷,企业会寻求IT帮助来提高组织战略意义上的核心价值,使用面向服务的架构,IT可以提供给企业实现业务敏捷性的这样一个框架
为什么选择面向服务架构(SOA)
不同种类的操作系统,应用软件,系统软件和应用基础结构(application infrastructure)相互交资,这便是IT企业的现状,一些现存的应用程序被用来处理当前的业务流程(Business Processes)
因此从头建立一个新的基础环境坏死不可能够
企业应该对业务的变化做出快速的反应,利用对现有的应用程序和应用基础架构(application infrastructure) 的投资来解决新的业务需求,为客户,商业软件伙伴以及应用商提供新的互动渠道,并呈现了一个可以支持有机业务的架构
SOA凭借其松耦合的特性,使得企业可以按照模块化的方式来添加新服务或更新服务或者跟新现有服务,以解决新的业务需要,提供选择从而可以通过不同的渠道提供服务,并可以把企业现有的或已有的应用作为服务,从而保护了现有的IT基础建设投资
一个使用SOA的企业,可以使用一组现有的应用来创建一个供应复合应用(supply chain composite application ),这些现有的应用通过标准接口提供功能