如何实现结构设计培训向性能设计的转变

基于性能的设计方法
,内容来自筑龙网相关的培训课程、论坛帖子、行业资讯等。筑龙网为国内最权威最专业的建筑工程学习。交流平台,超过1000万设计师、工程师和造价师在筑龙网交流、学习更多相关资料请访问日更新500篇的!(发布于:日)
此时有人在和您一起浏览筑龙优搜库
大家都在学
论坛热贴排行
课时数:27
课时数:33
课程时长:13
筑龙网以“成就有梦想的建筑人”为企业使命,为建筑行业从业者提供基于、直播课程、专家答疑、论坛交流的专业学习服务;同时搭建基于建筑+互联网的创业项目孵化平台,为推动行业创新发展贡献力量。 >
基于性能的设计方法相关专题推荐当前位置: >>
软件架构设计模式与实践
软件架构设计模式与实践康凯1 目录? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 软件架构视图 软件生命周期与软件架构介绍 架构设计的GRASP模式 质量属性驱动架构设计策略 软件架构模式分析及其实际运用 架构设计原则 面向对象的设计原则 架构设计验证 数据访问层设计(持久层设计) 借鉴RUP中的
设计流程 领域模型及业务逻辑层在架构设计中的实现 设计模式本质 SOA的设计思想 软件架构实践 软件系统架构实践与剖析 前言 软件系统开始坏死的症状? 一个软件系统开始坏死时表现的症状有: C 硬化Rigidity――系统变得越来越难以变更,修复或增添新功 能的代价高昂; C 脆弱Fragility――对系统的任何哪怕是微小的变更都可能造 成四处(甚至是与变更处没有逻辑上的关联之处J崩溃; C 绑死Immobility――抽取系统的任何部分用来复用都非常困 难; C 胶着Viscosity――以与原有设计保持一致的方式来对实施变 更已经非常困难,诱使开发人员绕过它选择容易但有害的途 径,其结果却使系统死的更快。 ?什么是软件架构 C 软件架构的概念很混乱。如果你问五个不同的人,可能会得 到五种不同的答案。 C 软件架构概念主要分为两大流派: ? 组成派:软件架构 = 组件 + 交互。 ? 决策派:软件架构 = 重要决策集。C 组成派和决策派的概念相辅相成。 ? 软件架构要层次化并隔离关注点 C 复杂性是层次化的。 --《人月神话》 C 好的架构设计必须把变化点错落有致地封装到软件系统的 不同部分(即关注点分离)。 C 通过关注点分离,达到“系统中的一部分发生了变化,不 会影响其他部分”的目标。 ? 软件单元的粒度: C 粒度最小的单元通常是“类”。 C 几个类紧密协作形成“模块”。 C 完成相对独立的功能的多个模块构成了“子系统”。 C 多个子系统相互配合才能满足一个完整应用的需求,从而 构成了软件“系统”。 C 一个大型企业往往使用多套系统,多套系统通过互操作形 成“集成系统”。C 软件单元的粒度是相对的。同一个软件单元,在不同场景下 我们会以不同的粒度看待它。 ? 架构(Architecture)与框架(Framework)。 C 框架只是一种特殊的软件,框架也有架构。 C 可以通过架构框架化达到“架构重用”的目的,如很多人都 在用 Spring 框架提供的控制反转和依赖注入来构建自己的 架构。 ? 软件架构的作用 C 如果一个项目的系统架构(包括理论基础)尚未确定,就不应 该进行此系统的全面开发。-- Barry Boehm,《Engineering Context》 C 一个缺陷充斥的系统,将始终是一个缺陷充斥的系统。-Timothy C. Lethbridge,《面向对象软件工程》 ? 软件架构设计为什么这么难? C 因为它是跨越现实世界与计算机世界之间鸿沟的一座桥。 C 软件架构设计要完成从面向业务到面向技术的转换,在鸿沟 上架起一座桥梁。 C 需求 -& 架构设计 -& 软件架构 -& 系统开发 -& 软件系统 ?软件架构对新产品开发的作用:C 上承业务目标。 C 下接技术决策。 C 控制复杂性。? 先进行架构设计,后进行详细设计和编码实现,符合“ 基于问题深度分而治之”的理念。C 组织开发。? 软件架构方案在小组中间扮演了“桥梁”和“合作契约 ”的作用。C 利于迭代开发和增量交付。? 以架构为中心进行开发,为增量交付提供了良好的基础 。在架构经过验证之后,可以专注于功能的增量提交。C 提高质量。 ? 软件产品线:指具有一组可管理的、公共特性的、软件密集性 系统的集合,这些系统满足特定的市场需求或任务需求,并且 按照预定义方式从一个公共的核心资产集开发得到。 ? 软件产品线架构:针对一个公司或组织内的一系列产品而设计 的通用架构。 ? 软件架构对软件产品线开发的作用: C 固化核心知识; C 提供可重用资产; C 缩短推出产品的周期; C 降低开发和维护成本; C 提高产品质量; C 支持批量定制; ? 架构师应当为项目相关的不同角色而设计: C 架构师要为客户负责,满足他们的业务目标和约束条件。 C 架构师要为用户负责,满足他们关心的功能需求和运行期质 量属性。 C 架构师必须顾及处于协作分工“下游”的开发人员。 C 架构师必须考虑“周边”的管理人员,为他们进行分工管理 、协调控制和评估监控等工作提供清晰的基础。 软件架构视图――让设计建模更明白、更有效张云贵 “系统架构图”? ? 架构设计的多重视图 C 从根本上来说是因为需求种类的复杂性所致。 C 比如一个媒体发布系统: ? 功能需求:用户可以通过浏览器浏览媒体的发布。据此 初步设计出采用浏览器插件的方案; ? 约束条件:不能影响用户浏览器的安全性;细化设计方 案,需要对插件进行认证,自动判别客户端是否存在, 及版本比较;自动下载注册等。 ? 使用期质量属性:为保证浏览的流畅,应减少中间等待 的时间,因此应对下一步需使用的媒体做预测等。 ? 制作发布期的质量保证:保证在遇到较大的媒体时能保 持浏览的流畅,应在发布时将视频等流式化。 ?软件系统的需求种类复杂 ? 什么是软件架构视图 C 个架构视图是对于从某一视角或某一点上看到的系统所做的 简化描述,描述中涵盖了系统的某一特定方面,而省略了于 此方面无关的实体。C 架构要涵盖的内容和决策太多了,超过了人脑D一蹴而就‖的 能力范围,因此采用D分而治之‖的办法从不同视角分别设计 ;同时,也为软件架构的理解、交流和归档提供了方便。C 多视图方法是软件架构归档的方法,更是指导我们进行架构 设计的思维方法。
? 逻辑架构 C 逻辑架构关注功能。其设计着重考虑功能需求。 ? 开发架构 C 开发架构关注程序包。其设计着重考虑开发期质量属性,如可扩 展性、可重用性、可移植性、易理解性和易测试性等。 ? 运行架构 C 运行架构关注进程、线程、对象等运行时概念,以及相关的并发 、同步、通信等问题。 C 其设计着重考虑运行期质量属性,例如性能、可伸缩性、持续可 用性和安全性等。 ? 物理架构 C 物理架构关注软件系统最终如何安装或部署到物理机器。其设计 着重考虑“安装和部署需求”。以及如何部署机器和网络来配合 软件系统的可靠性、可伸缩性等要求。 ? 数据架构 C 数据架构关注持久化数据的存储方案。设计着重考虑“数据需求 ”。 关系? 逻辑视图。逻辑视图不仅关注用户可见的功能,还包括为实现用户功 能而必须提供的D辅助功能模块‖;它们可能是逻辑层、功能模块等。 ? 开发视图。开发视图关注程序包,不仅包括要编写的源程序,还包括 可以直接使用的第三方SDK和现成框架、类库,以及开发的系统将运 行于其上的系统软件或中间件。开发视图和逻辑视图之间可能存在一 定的映射关系:比如逻辑层一般会映射到多个程序包等。 ? 运行视图。和开发视图的关系:开发视图一般偏重程序包在编译时期 的静态依赖关系,而这些程序运行起来之后会表现为对象、线程、进 程,运行视图比较关注的正是这些运行时单元的交互问题。 ? 物理视图。和运行视图的关系:运行视图特别关注目标程序的动态执 行情况,而物理视图重视目标程序的静态位置问题;物理视图是综合 考虑软件系统和整个IT系统相互影响的架构视图。
? 软件生命周期与软件架构介绍 软件架构师的定位? 系统架构师的职责: ? 一、理解系统的业务需求,制定系统的整体框架(包括:技术 框架和业务框架) ? 二、对系统框架相关技术和业务进行培训,指导开发人员开发。 并解决系统开发、运行中出现的各种问题。 ? 系统架构师的目的: ? 对系统的重用、扩展、安全、性能、伸缩性、简洁等做系统级 的把握。 ? ? ? ? 系统架构师能力要求: 一、系统架构相关的知识和经验。 二、很强的自学能力、分析能力、解决问题的能力。 三、写作、沟通表达、培训。24 ? 角色 ? 软件架构师Software Architect ? 定义 ? 主导系统全局分析设计和实施、负责软件构架和关键技术决策 的角色25 ? 职责 C 领导与协调整个项目中的技术活动(分析、设计和实施等) C 推动主要的技术决策,并最终表达为软件构架 C 确定和文档化系统的相对构架而言意义重大的方面,包括系统的 需求、设计、实施和部署等“视图” C 确定设计元素的分组以及这些主要分组之间的接口 C 为技术决策提供规则,平衡各类涉众的不同关注点,化解技术风 险,并保证相关决定被有效的传达和贯彻 C 理解、评价并接收系统需求 C 评价和确认软件架构的实现26 ? 专业技能 ? 技术全面、成熟练达、洞察力强、经验丰富,具备在缺乏完整 信息、众多问题交织一团、模糊和矛盾的情况下,迅速抓住问 题要害,并做出合理的关键决定的能力。 ? 具备战略性和前瞻性思维能力,善于把握全局,能够在更高抽 象级别上进行思考。 ? 对项目开发涉及的所有问题领域都有经验,包括彻底地理解项 目需求,开展分析设计之类软件工程活动等。 ? 具备领导素质,以在各小组之间推进技术工作,并在项目压力 下做出牢靠的关键决策。 ? 拥有优秀的沟通能力,用以进行说服、鼓励和指导等活动,并 赢得项目成员的信任。27 ? 以目标导向和主动的方式来不带任何感情色彩地关注项目结果, 构架师应当是项目背后的技术推动力,而非构想者或梦想家 (追求完美) ? 精通构架设计的理论、实践和工具,并掌握多种参考构架、主 要的可重用构架机制和模式。 ? 具备系统设计员的所有技能,但涉及面更广、抽象级别更高。28 软件架构师的知识体系? 软件架构师作为整个软件系统结构的总设计师,其知识体系、 技能和经验决定了软件系统的可靠性、安全性、可维护性、可 扩展性和可移植性等方面的性能。因此一个优秀的软件架构师 必须具备相当丰富的知识、技能和经验。 ? 通过对比软件架构师和系统分析师在软件开发中的职责和角色, 不难发现软件架构师与系统分析师所必需的知识体系也是不尽 相同的,系统分析师的主要职责是在需求分析、开发管理、运 行维护等方面,而软件架构师的重点工作是在架构与设计这两 个关键环节上。因此在系统分析师必须具备的知识体系中对系 统的构架与设计等方面知识体系的要求就相对低些;而软件架 构师在需求分析、项目管理、运行维护等方面知识的要求也就 相对低些。29 ? 成为一名合格的软件架构师必须具备的知识 C 信息系统综合知识体系 C 软件架构知识体系30 ?? MFC,MSF,MOF,RUP,J2EE,Spring,SOA,JUnit, ORM,.Net ? MVC,UML,XML,Corba,MDA,MDD,Web-Service ? RSS,Web2.0,AJAX,Serverlet,Hibernate ? IOC, AOP ? Ruby On Rails ? Rup ? BPEL ? Workflow Engine ? LBS ? Oracle ? CMMI ? MQ ? …31 软件架构师在干什么?? 思考、思考、再思考 C 深入理解、准确把握建设的业务需求 C 分析所有可见的问题、障碍、风险 C 充分参考已有的成功方案,降低风险 ? 交流、讨论、博弈、质疑 C 对构思中的方案不断提出质疑,避免漏洞 C 广泛听取各层面的意见,开拓思路 C 反复质疑、逐步完善已有的设计构思 ? 在动手实现之前验证设计方案的正确性32 软件架构师的知识结构? 软件知识 C 最好要有系统开发全过程经验。 C 对 IT 建设生命周期各个环节有深入了解,包括:系统/模块 逻辑设计、物理设计、代码开发、项目管理、测试、发布、 运行维护等。 C 深入掌握1-2种主流技术平台上开发系统的方法。 C 了解多种应用系统的结构。 C 了解架构设计领域的主要理论、流派、框架。33 软件架构师的知识结构? 业务知识 C 深入了解系统建设的业务需求。 C 了解系统的非功能需求和运行维护需求。 C 了解企业 IT 公共设施、网络环境、外部系统。34 软件架构师的思维方式? 基于框架的思维 C 架构设计的层次(Enterprise, Application, etc) C IT 的生命周期(What, Why, Where, How, When, etc) C 成功经验以及方法论的指导 ? 合理把握技术细节 C 把握各个层次应有的内容 C 合理忽略不应有的技术细节35 软件架构师的思维方式? 风险管理意识 C 采用成功经验、避免不应有的风险 ? 多方位的开放思维 C 多维度、多方向、包容性、避免排他性 C 分析、质疑、抽象、归纳 C 没有绝对好的架构设计,只有相对优秀的方案36 ? 注意:并不存在通用的设计方法。我们认为,给定的某种固定 的方法总是会顾此失彼,而且这种不平衡性不太容易觉察。如 果给定的某种方法所注重的方面与系统需求不吻合,则这种方 法就会将设计引入歧途。所以我们给出的是一些技巧,任何一 次设计过程,都需要设计师仔细分析系统的需求和相关的约束 条件,灵活运用众多的设计技巧,针对不同的设计方案进行取 舍,做出合理的决策。37 ? 为了有效地控制设计工作的复杂性,一般把设计活动分为总体设计和 详细设计两个层次。总体设计主要关注于体系结构和接口这些全局性 的内容,而详细设计主要关注于每个模块内部的数据结构和算法。至 于数据,则在设计的各个层次都会涉及。? 软件设计是一个迭代的过程,是一个逐步细化和求精的过程。因此, 总体设计和详细设计之间的划分并不是绝对的。哪些是总体设计任务 ,哪些是详细设计任务,取决于设计师对于整个项目的把握,并没有 一个统一的标准。设计师在设计时实际是在做一系列的设计决策,来 满足系统的行为目标,质量目标和开发目标。如果一个结构对于完成 这些目标非常重要,则它是构架的一部分。相反,如果它可以留到以 后再完善,则它不是构架的组成部分。因此,总的说来,一个设计是 不是属于构架设计,要看你当前的设计目标。38 ? 管理陷阱 C 随着管理性责任的增加,你所从事技术性工作的时间就会显 著减少。这样,因为在完成技术性任务和保持职业技能上花 费时间的减少,你可能会失去技术优势。C 软件架构师和管理者有很大的差异:软件架构师是直接的技 术贡献者;而管理者则是通过协调其他人员的活动来间接做 出贡献。他们往往一起协作,构成高效的管理团队。以经验 看,把两者结合起来却不能长久地工作。 C 作为一名软件架构师,如果你已经建立起个人的职业原则的 话,就有可能避免成为管理者。 架构和设计应该做到何种程度? 软件架构必须设计到“能为开发人员提供足够的指导和限制” 的程度。 ? 分而治之的两种方式 C 分而治之的缘由:问题太复杂了,超出了人们能够“一蹴而 就”的范围。(接口和实现分离) C 一、先不把问题研究得那么深,那么细,浅尝辄止,见好就 收。这种分而治之的方式称为“按问题深度分而治之”。 C 二、先不研究整个问题,而是研究问题的一部分,分割问题 。这种分而治之的方式称为“按问题广度分而治之”。(比 如展现层、业务层和数据层的开发)40 ? 随着软件设计工作越来越复杂,将架构设计和详细设计分离已 成为普遍的做法。 ? 将设计分为架构设计和详细设计,是对“按问题深度分而治之 ”思想的运用。 C 所谓架构设计,就是关于如何构建软件的一些最重要的设 计决策; C 详细设计针对每个部分的内部进行设计。 ? 可以这么说,软件架构设计应当解决的是全局性的、涉及不同 “局部”之间交互的设计问题,而不同“局部”的设计由后续 的详细设计负责。41 ? 面对“技术复杂性”和“管理复杂性”这样的双重困难,以架 构为中心的开发方法是有效的途径: ? 一方面:“软件系统的架构涵盖了整个系统,尽管架构的有些 部分可能只有?一寸深‘”。构造一个具有一定抽象层次的解决方 案,而不是将所有细节统统展开,从而有效地控制了“技术复 杂性”。没有“把问题研究那么深、那么细”,属于“按问题 深度分而治之”42 ? 另一方面,因为“架构中包含了关于各元素应如何彼此相关的 信息”,从而可以把不同模块分配给不同小组分头开发,而软 件架构设计方案在这些小组中间扮演“桥梁”和“合作契约” 的作用。每个小组的工作覆盖了“整个问题的一部分”,各小 组之间可以互相独立地进行并行工作,这种“分割问题,各个 击破”的策略,属于“按问题广度分而治之”。 ? 这样一来,模块的技术细节被局部化到了小组内部,内部的细 节不会成为小组间协作沟通的主要内容,理顺了沟通的层次。 另外,对“人尽其才”也有好处,不同小组的成员需要精通的 技术各不相同。例如,用户界面层、数据管理层、系统交互 层。43 ? 架构要进行到什么程度 C 软件架构是团队开发的基础,应明确规定后期分头开发所必须的 公共设计约定,为分头开发提供足够的指导和限制。 C 另一方面,具体的架构设计程度还会因软件项目的不同而不同。 C 架构设计对软件的不同部分的设计程度并不是整齐划一的。(通信 机制、持久化机制、消息机制等对应的公共模块;具体的业务功 能模块在架构设计中往往设计程度不深。) ? 归纳: C 由于项目的不同、开发团队情况的不同,软件架构的设计程度会 有不同; C 软件架构应当为开发人员提供足够的指导和限制。44 高来高去式架构设计的症状 ? 不能为开发人员提供足够的指导和限制的那种架构设计方案。 高来高去式架构设计现象极为普遍,危害:C 缺少来自架构的足够的指导和限制,开发人员在进入分头开 发阶段之后会碰到很多问题,并且容易造成管理混乱,沟通 和协作效率低; C 对软件质量非常关键的全局性设计决定被拖延到分头开发期 间草率决定; C 没有完成化解重大技术风险的职责; C 团队成员对架构师意见大,团队士气受到打击。45 ? 症状一:缺失重要架构视图。给团队的不同角色提供指导。 ? 症状二:架构设计方案停留在概念性架构的层面,全局性的设 计决策最后由具体开发人员从局部视角考虑并确定下来,造成 技术和管理上的种种问题。 ? 症状三:名不副实的分层架构。对各层之间交互接口和交互机 制的设计严重不足。46 架构设计的GRASP模式47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
质量属性驱动架构设计策略 ? 软件质量及质量模型 C 软件质量是一个复杂的概念,不同的人从不同的角度来看软 件质量问题,会有不同的理解。 C 从用户的角度看,质量就是满足客户的需求; C 从开发者的角度看,质量 就是与需求说明保持一致; C 从产品的角度看,质量就是 产品的内在特点; C 从价值的角度看,质量就是客户是否 愿意购买。 ? 在软件项目开发过程中,项目经理眼中的质量就是能“令人满 意”地工作以完成预期功能的软件产品。 ? 所谓“令 人满意”,包括功能、性能、接口需求及其他指标, 如可靠性、可维护性、可复用性和正确性。 ? 然而在实际工作中,一旦出现问题时,项目管理人员必须权衡 利弊,作出取舍,在满足某一个指标的同时,牺牲另外一个或 几个指标。比如为了按期交货,需对软件功能进行分类,在第 一个版本中实现优先级较高的功能,在第二个版本中实 现优先 级较低的功能。因此,项目经理需要一个对其工作有指导意义 的质量模型和度量方法。该模型一方面可以帮助项目经理生产 出符合标准的软件产品,另一方面帮助项目经理识别可能影响 产品质量的风险。 ? 为什么那么多软件产品需要重新设计? C 难以维护? C 运行速度太慢? C 稳定性差? C 无法进行功能扩展? C 易遭受安全攻击? ? 忽视包括质量属性需求在内的非功能需求是致命的。 ? 质量属性分为: C 运行期质量属性 C 开发期质量属性? 各类需求架构设计的不同影响 C 高可移植性 ? 对硬件和平台相关特性进行封装、 隔离 C 高性能 ? 精心规划职责模型 ? 在质量属性方面需求折衷 ? 质量属性分析的位置 C 质量属性分析是概念性架 构设计的重要步骤。 C 通过质量属性分析,制定 出满足非功能需求的高层 设计决策。 C 质量属性分析所处的位置 如图所示 ?”属性-场景-决策”表法 C 运用“关键需求决定架构”的策略,使质量属性分析的“输 入”集中到关键质量属性需求。 C “属性-场景-决策”表方法提倡通过一组具体场景将要达到 的质量属性需求目标细化,再根据场景制定架构决策。 “属性-场景-决策“表法
? “属性-场景-决策”表法的好处: C 可操作性强。质量熟悉需求是笼统的目标,而一组质量场景 使之明确化。 C 避免过度设计。借助“属性-场景-决策”表对质量场景进行 评估,通过权衡场景发生的概率和遗漏它的代价,决定是否 应满足该场景的要求。 C 便于系统升级时参考。 例:可扩展性质量属性 ? 运用“属性-场景-决策”表方法,细化PM Tool的可扩展性需 求,制定架构决策,如下表所示: ? 非功能需求对软件架构的影响比功能需求更大。 ? “属性-场景-决策”表可以帮助软件架构师以一种更透明、更 可操作的方式完成从质量属性需求到质量场景的细化,最终根 据具体的场景有针对性地设计架构决策。
架构的目标? 正确性correctness ? 可靠性(Reliable): C 软件系统对于用户的商业经营和管理来说极为重要,因此软 件系统必须非常可靠。 C 健壮性robustness ? 安全性(Secure) : C 软件系统所承担的交易的商业价值极高,系统的安全性非常 重要。 ? 可伸缩性(Scalable) : C 软件必须能够在用户的使用率、用户的数目增加很快的情况 下,保持合理的性能。只有这样,才能适应用户的市场扩展 得可能性。 ? 可定制化(Customizable) : C 同样的一套软件,可以根据客户群的不同和市场需求的变化 进行调整。 ? 可扩展性(Extensible): C 在新技术出现的时候,一个软件系统应当允许导入新技术, 从而对现有系统进行功能和性能的扩展 ? 可复用性reusability ? 可维护性(Maintainable): C 软件系统的维护包括两方面,一是排除现有的错误,二是将 新的软件需求反映到现有系统中去。一个易于维护的系统可 以有效地降低技术支持的花费。 ? 兼容性compatibility ? 可移植性portability? 易用性ease of use? 高效性efficiency ? timeliness,economy and functionality ? 客户体验(Customer Experience): C 软件系统必须易于使用。? 市场时机(Time to Market): C 软件用户要面临同业竞争,软件提供商也要面临同业竞争。 以最快的速度争夺市场先机非常重要。 软件可维护性87 ? 重型和轻型方法 C 重型方法:偏重于计划、过程和中间产物 C 敏捷方法:更加看重人和沟通。人和沟通永远是第一位的, 而计划、过程和中间产物,只是保证沟通、实现目标的手段 。并非计划、过程、中间产物不重要,但不能本末倒置。 ? 评判软件成功的标准: C 很多。对敏捷方法:首先在于交付可用的软件。 C 为了保证软件的可用性,需求是根本。对于架构设计工作, 从需求出发来设计架构,是保证软件可用性的基本的保证。 ? 如何开始架构设计工作 C 考虑的平台、语言、开发环境、数据库等 C 误区:架构设计就是写一些空话,套话。 C 误区:对与客户具体情况密切相关的问题却未系统考虑。 C IT界的技术层出不穷,面对着如此之多的技术、平台、框架 、函数库,我们如何选择一组适合软件的技术? ? 要针对需求设计架构。 C 每个客户都有自身特点,如何才能够设计出符合客户利益的 架构? C 软件中往往都充斥着众多的问题,在一开始就把所有的问题 都想清楚往往很难做到,但是如果不解决问题,风险又居高 不下。 ? 架构设计就是铺设软件的主管道。根据什么来制定主管道的粗 细、路径等因素?是根据城市的人口、地理位置、水源等因素 。对应到软件设计,城市的各因素就是软件中的各种需求:功 能需求、非功能需求、变化案例等。? 例:城市中自来水管的架设是一项非常的复杂的工程。为了需 要满足每家每户的需要,自来水管组成了一个庞大的网络。在 这样一个复杂的网络中,如何完成铺设的任务呢。一般的做法 是,先找出问题的根源,也就是水的源头。从水源铺设一条管 道通至城市,然后根据城市的区域划分,设计出主管道,剩下 的就是使用的问题了,每家每户的管道最终都是连到主管道上 的。因此,虽然自来水网络庞大复杂。但是真正的主管道是比 较简单的。 ? 一般来说,功能需求决定业务架构、非功能需求决定技术架构,变化 案例决定架构的范围。 ? 功能需求决定软件能够做些什么。我们需要根据业务上的需求来设计 业务架构,以使得未来的软件能够满足客户的需要。 ? 非功能需求定义了性能、效率上的一些约束、规则。而我们的技术架 构要能够满足这些约束和规则。变化案例是对未来可能发生的变化的 一个估计,结合功能需求和非功能需求,我们就可以确定一个需求的 范围,进而确定一个架构的范围。 ? 例:一个字处理软件,功能需求可以简单概括为格式化用户输入的文 字,非功能需求可能是格式化大小为1000K的一段文字的处理速度不 能低于10S,变化案例可能是推出多种语言版本。则在设计业务架构 时,我们会集中于如何表示文字、图象、媒体等要素,此外需要有另 外的技术架构来处理速度问题,比如缓冲技术,对于变化案例,我们 也要考虑相应的架构,比如把字体独立于程序包的设计。 ? 架构设计的两项工作 C 分析:分析是分析需求 C 设计:设计软件的大致结构。 C 很多方法论分离二者,其实无一定的界限,做分析的时候会 想到如何设计,而思考如何设计反过来又会影响分析的效果 。可以说,两者间是相互联系和不断迭代的。 ? 需求与架构都应迭代进行 C 一点一点的作需求。这种做法在那些需求变化快的项目中尤 其适用。 C 由于我们采用的流程是一种迭代式的流程,这里我们将会面 临着如何对待上一次迭代的中间产物的问题。如果我们每一 次迭代都需要修改已存在的中间产物,那么这种维护的成本 未免过大。因此,敏捷方法论的基本做法是,扔掉那些已经 没有用处的中间产物。 C 软件要比文档重要。生成中间产物的目的都是为了生成最终 的程序,对于这些已经完成作用的模型,没有必要付出额外 的维护成本。 ? 架构设计中的一些提示(也是抛弃模型的必要条件): ? 简单化:简单的模型和简单的程序。模型和程序越复杂,就需要更多 的精力来处理它们。因此尽可能简化它们,为的是更容易的处理它们 。? 高效沟通渠道:通过增强沟通的效果来减少对中间产物的需要。试想 若随时能从客户处得到需求的细节资料,则前期需求调研就没有必要 做得太细。? 角色交叉轮换:开发人员间建立起交换角色的机制,能够尽量的避免 各子系统诸侯割据的局面。 ? 清晰的流程:或明确的过程。过程在方法论中是重点,敏捷方法论也 不例外。开发人员能够清楚的知道,今天做什么,明天做什么。过程 不是给别人看的,而是给自己用的。 ? 工具:好用的工具能够节省大量的时间,工具并不仅指CASE 工具,还包括版本控制工具、自动测试工具、画图工具、文档 制作和管理工具。使用工具要注意成本和效益的问题。 ? 标准和风格:语言标准不同是沟通的很大障碍。语言从某个角 度来看属于一种标准、一种风格。因此,一个团队如果采用同 样的编码标准、文档标准、注释风格、制图风格,那么这个团 队的沟通效率一定非常高。 ? 如果上述的环境都不具备,或是欠缺好几项,那你的文档的模 型还是留着的好。 ? 仅针对需求设计架构 C 不要做未来才有用的事情。 C 有时我们会把架构考虑得非常复杂,主要原因是把很多未来 的因素放入到现在来考虑。 C 或在开发第一个产品的时候就试图做成完美的框架。 C 以上的这两种思路有没有错呢?没有错,这只是如何看待投 入的问题,有人希望开始的时候多投入一些,这样后续的投 入就会节省下来。但在现实中,由于需求的不确定性,希望 通过增加开始阶段的投入来将降低未来的投入往往是难以做 到的,框架的设计也绝非一蹴而就的,因此这种做法并不好 。 C 同其它很多事物一样,架构设计应保持简单性和迭代过程! ? 引入模式 C 模式帮助我们抓住重点。 C 为了解决设计文档编辑器引出的七个问题,一共使用了8种 不同的模式。这8种模式的组合其实就是架构,因为它们解 决的,都是系统中最高层的问题。 C 架构也是存在模式的。比如,对于系统结构设计,我们使用 层模式;对于分布式系统,我们使用代理模式;对于交互系 统,我们使用MVC(模型-视图-控制器)模式。模式本来就 是针对特定问题的解,因此,针对需求的特点,我们也可以 采用相应的模式来设计架构。
? PetShot案例 C 在MVC图背后隐藏着的需求: C 系统需要支持多种用户界面,包括为普通用户提供的HTML界面, 为无线用户提供的WML界面,为管理员提供的Swing界面,以及 为B2B业务设计的WebService界面。这是系统最重要的需求,因 此,系统的设计者就需要确定一个稳定的架构,以解决多界面的 问题。 C 相对于多界面的问题,后端的业务处理逻辑都是一致的。比如 HTML界面和WML界面的功能并没有太大的差别。把处理逻辑和 界面分离开来还有额外的好处,可以在添加功能的同时,不涉及 界面的改动,反之亦然。(耦合度的问题)。 C MVC模式正可以适用于解决该问题。系统使用控制器来为业务逻 辑选择不同的界面,这就完成了MVC架构的设计思路。在架构设 计的工作中,我们手头上有模式这样一张好牌,有什么理由不去 使用它呢?
? 抓住重点 C 架构是一种抽象,即架构设计摒弃了具体的细节,仅仅抓住软件 最高层的概念,也就是最上层、优先级最高、风险最大的那部分 需求。 C 考虑、分析、解决一个问题,一定有一个渐进的过程。架构设计 就是解决问题其中比较早期的一个阶段,我们不会在架构设计这 个阶段投入过多的时间,因此关键点在于我们要能够在架构设计 中把握住需求的重点。 C 比如,分布式系统和交互系统,分布和交互就是这两个系统的重 点。那么,如果说我们面对的是一个分布式的交互系统,那么, 我们就需要把这两种特性做为重点来考虑,并以此为基础,设计 架构。而宠物商店的范例也是类似的,除了MVC的架构,还有很 多的设计问题需要解决,例如用于数据库访问的数据对象,用于 视图管理的前端控制器等。但是这些相对于MVC模式来说,属于 局部的,优先级较低的部分,可以在架构确定后再来设计。 ? 架构设计和领域专家 C 一个架构要设计的好,和对需求的理解是分不开的。因此在 现实中,业务领域专家凭借着他对业务领域的了解,能够帮 助开发人员设计出优秀的架构来。 C 架构是需要抽象的,它是现实社会活动的一个基本模型,而 业务领域的模型仅仅凭开发人员是很难设计出来的。在ERP 的发展史上,MRP发展为MRPII,再发展到闭环MRP,直 到发展成为现在的ERP,主要的因素是管理思想的演化,也 就是说,对业务领域的理解进步了,架构才有可能进步。 C 因此,敏捷型架构设计的过程中,我们也非常强调领域专家 的作用。 ? 软件约束条件与架构的影响 C 资金 C 时间 C 业务 C 运行环境 C 开发团队 C 实现技术等 领域模型设计? 领域模型(Domain Model) C 商业建模范畴的概念: 同行业企业的业务模型必定有很大 的共性和内在的规律性,由这个行业内的各个企业的业务模 型再向上抽象出来整个行业的业务模型,即领域模型。C 技术建模范畴的概念:用编程语言来实现商业领域模型。104 ? 关系: C 对行业经验积累不足的软件公司,开发软件由需求驱动,而 非商业的领域模型驱动。 C 商业领域模型与编程语言的不是一对一的对应关系。例如用 EJB2模型,需要最少两个以上的EJB,即一个 Session Bean,处理面向流程的控制逻辑,一个Entity Bean,处理 面向持久化的实体逻辑(持久化操作附着在Entity Bean的 Home接口上)。如果是更加复杂的领域模型,则需要更多 的EJB,一般一个领域模型需要多个Entity Bean和多个 Session Bean。 C 使用基于POJO模型的实现,则粗颗粒度的EJB要继续细分 :一个Entity Bean对应三个以上POJO:一个或者多个实体 类,DAO接口、DAO接口实现类;一个Session Bean要切 分为多个业务Bean。105 ? 层次结构 ? 领域模型 ? 从EJB到轻量级框架106 层次结构? 表现层(present) ? 业务层 ? 业务层外观 ? 业务服务层 ? 领域对象管理/服务/仓库层 ? 领域对象层 ? 持久层 ? 数据访问层 ? 数据库107 ? 领域模型中的各种角色: C 实体--有唯一的标识,并且要有属性和行为(非GET/SET),添加了 行为,使其具有生命力。往往在设计时,实体的形为最难决断。 为确定行为,我们必须识别它们的责任和协作。类的责任是指该 类要做、知道、或决定的一切,由一个或多个方法完成。类中有 属性和关联,协作就是为完成自己的责任所调用其它关联类。 C 值对象--没有标识没有行为。如Address类。 C 工厂---定义创建实体的方法,封装实例化对象并将一些关联对象 注入。 C 仓库(repository)管理实体的集合,主要有查找和删除实体的方法.实 现类可以调用执久化层(如Hibernate,Ibatis) C 服务(Service) ,实现整个应用程序的工作流(workflow)。服务包 含那些无法指派的单个实体的行为,由作用于多个对象方法组成 。如可以调用repository查找到实体对象,然后委派给这些对象。 服务和facade很像,但不一样,它不处理以下事情:1)执行事务 。2)收集返回给表现层的数据。3)脱钩对象。4)其它事情。服 务可以说是业务的协调者,业务逻辑可以分散到实体对象中。108 109 ? 2、层次之间的交互 C A、页面提交表单数据到Action,Action创建DTO对象并设 置相应属性值为表单数据 C B、Action传递DTO对象给Facade C C、Facade中套用ServiceTemplate事务模板以加入事务管 理,在ServiceTemplate中根据具体业务调用Factory或 Reposistory,分别create或者load出DomainModel对象 C D、Facade传递DomainModel对象给Service C E、Service执行具体业务逻辑(调用DomainModel对象相 应的业务方法) C F、Service调用Reposistory对状态已改变的DomainModel 对象进行持久化操作(调用相应DAO)110 ? 注: C 在Facade或Service中如果需要查询DomainModel对象中的 属性值,调用DomainModel对象的getDataInfo()方法得到 DataInfo对象,通过DataInfo对象查询所需数据,包括 Service返回给Fa? ade业务处理结果中所包含的业务数据。111 领域模型? ? ? ? 失血模型 贫血模型 充血模型 胀血模型112 失血模型? DO只有属性及其getter/setter方法,没有任何业务逻辑。 ? 缺点:行为与数据分离,很多情况导致维护与理解困难。113 贫血模型? DO包含不依赖于持久化的领域逻辑;依赖持久化的领域逻辑归 入Service层。 ? Service(业务逻辑,事务封装) ? DAO ? DO ? 优点: ? 各层单向依赖,结构清楚,易于实现和维护。 ? 设计简单易行,底层模型非常稳定。 ? 缺点: ? DO部分的持久化逻辑被放入Service层,不够OO。 ? Service层过重。114 充血模型? 与贫血模型类似,不同处在于如何划分业务逻辑:绝大多业务 逻辑都应该放在DO里(包括持久化逻辑),而Service层很薄,仅 仅封装事务和少量逻辑,不和DAO层打交道。 ? Service(事务封装) ? DO ? DAO ? 优点: ? 符合OO ? Service层很薄,只充当Facade的角色,不和DAO打交道。115 ? 缺点: ? DAO和DO双向依赖。 ? 如何划分Service层逻辑和Domain层逻辑没有确定的规则, 取决与设计人员自己的理解。 ? Service层封装事务,须对所有的DO逻辑提供相应的事务封 装方法,造成重定义所有的Domain logic。 ? Service的事务化封装的意义等于把OO的Domain logic转换 为过程的Service 事务脚本。充血模型在domain层实现的 OO在Service层又变成了面向过程。116 胀血模型? 取消Service层,只剩下DO和DAO层,在DO的domain logic上 面封装事务。 C DO(事务封装,业务逻辑) C DAO C (RoR甚至合并为一层) ? 优点: C 分层简化 C 符合OO ? 缺点: C service逻辑也强行放入DO ,引起了DO不稳定。 C DO暴露给web层过多的信息,可能引起不必要的耦合。117 ? 原则: C 业务对象封装了内在的业务逻辑,而应用服务封装了外在于 业务对象的业务逻辑。118 EJB到轻量级框架? EJB ? POJO (业务逻辑) + 轻量级框架([Hibernate、JDO、 iBATIS](持久化)、Spring(事务管理、安全))119 EJB? EJB: ? 编写分布式业务应用程序的Java标准架构。 ? 提供大量服务: C 声明型事务, EIB容器自动启动、提交和回滚事务。 C 业务逻辑能参与由远程客户发起的分布式事务。 C 提供声明型安全,大部分情况下不再摇要编写安全代码求( bean部署描述符里的条目指定准可以防问某个具体bean) 。120 ? 例:在两个账号间进行转账的服务。121 122 ? 新设计是面向对象、基于POJO, 而非基于EJB的过程式。 ? 它使用构建在JDBC上的持久层框架来访问数据库, 并不直接使 用JDBC。 ? 业务逻辑由POJO facade而非会话bean进行封装。 ? 事务由Spring框架而非EJB容器进行管理。 ? 业务逻辑向表现层返回实际的业务对象,而不是DTO。 ? 应用程序通过将组件的依赖作为setter或构造子参数传入来进行 组装,而不是之前采用Java命名和目录接口(JNDI )查询的组件。 ? 由于该设计面向对象,并采用上述轻量级技术,因此较之前看到的 EJB版本对开发人员要友好。123 ? 基于轻量级框架设计的好处是,它提供事务和持久化时并不要 求应用程序类实现任何特殊接口。甚至当应用程序的类需要运 行在事务里或是持久的时候,它们仍是POJO,设计者可以继 续享受POJO的种种好处。124 125 ? 面向对象的优点: ? 整个设计更易理解和维护。它并不是一个无所不能的大型类 , 而是由大量小类组成, 每个类只共有若干职责。此外,诸如 Account、BankingTransaction和OverdraftPolicy类都与现 实世界的概念对应, 因此易于理解。 ? 其次,面向对象设汁也更易测试: 所有类都能并且应当进行独 立的测试。EJB只能通过调用它的public 方法如Transter进 行测试,难度大。(只能测试p-blic方法暴露的复杂功能,无法 测试其中简单的部分)。 ? 面向对象象设计更易扩展, 它可使用设计模式,如Stategy和 Template等。EJB风格的过程式设计往往需耍修改核心代码 。126 ? 不适合用面向对象的场合: ? 大量数据集合的关系操作。 ? 以数据库为中心的管理程序 :这个领域所对应的现实世 界是一个面向关系的世界,表与表的关联体现的是彼此 的业务关系。 复杂的SQL固然不好维护,但业务真是复 杂到简单的SQL都难以描述的程度,采用面向对象描述 则更加困难,维护也更困难,同时还损失了效率。 ? 比较大的事务。 ? 性能要求高的地方。(直接用Sql或者存储过程;牺牲可维 护性和可复用性) ? 上层流程。127 ?消除DTO128 部署POJO程序129 130 131 软件架构模式分析及其实际运用 ? 软件架构C 软件架构概论 C 架构的目标 C 架构的种类? 软件框架 ? 常见的架构模式 软件架构概论? 系统架构是一个软件系统从整体到部分的最高层次的划分。 ? 一个系统通常是由元件组成的,而这些元件如何形成、相互之 间如何发生作用,则是关于这个系统本身结构的重要信息。? 详细地说,就是要包括架构元件(Architecture Component) 、联结器(Connector)、任务流(Task-flow)。所谓架构元 素,也就是组成系统的核心&砖瓦&,而联结器则描述这些元件 之间通讯的路径、通讯的机制、通讯的预期结果,任务流则描 述系统如何使用这些元件和联结器完成某一项需求。 ? 建造一个系统所作出的最高层次的、以后难以更改的,商业的 和技术的决定。 ? 在建造一个系统之前会有很多的重要决定需要事先作出,而一 旦系统开始进行详细设计甚至建造,这些决定就很难更改甚至 无法更改。显然,这样的决定必定是有关系统设计成败的最重 要决定,必须经过慎重的研究和考察。 架构的种类? 根据我们关注的角度不同,可以将架构分成三种: C 逻辑架构 C 物理架构 C 系统架构 逻辑架构? 软件系统中元件之间的关系,比如用户界面,数据库,外部系统接口,商业逻辑元件等等。 物理架构? ? 软件元件是怎样放到硬件上的 下图描述了一个分布于北京和上海的分布式系统的物理架构,图中所有的元件都是物理设备 ,包括网络分流器、代理服务器、WEB服务器、应用服务器、报表服务器、整合服务器、存 储服务器、主机等等。 系统架构? 系统的非功能性特征,如可扩展性、可靠性、强壮性、灵活性 、性能等。 ? 系统架构的设计要求架构师具备软件和硬件的功能和性能的过 硬知识,这一工作是架构设计工作中最困难的工作。 架构的两要素? 元件划分和设计决定。 ? 逻辑元件: C 一个软件系统中的元件首先是逻辑元件。这些逻辑元件如何 放到硬件上,以及这些元件如何为整个系统的可扩展性、可 靠性、强壮性、灵活性、性能等做出贡献,是非常重要的信 息。 ? 设计决定: C 进行软件设计需要做出的决定中,必然会包括逻辑结构、物 理结构,以及它们如何影响到系统的所有非功能性特征。这 些决定中会有很多是一旦作出,就很难更改的。 ? 基于数据库的系统架构: C 一般有多少个数据表,就会有多少页的架构设计文档。比如 一个中等的数据库应用系统通常含有一百个左右的数据表, 这样的一个系统设计通常需要有一百页左右的架构设计文档 。 ?从概念性架构到实际架构C 就是多 (Less is more.)。 -- 密斯? 凡德罗 C 概念性架构是对系统设计的最初构想。 C 一般来说,实际的软件架构设计过程是,先进行概念 性架构的设计,把最关键的设计要素和交互机制确定 下来,然后再考虑具体技术的运用,设计出实际架构 。 ? 架构设计中的关键要素及解决策略 C 策略是制胜的关键。-- 张明正,《挡不住的趋势》 C 最好的软件开发人员都知道一个秘密:美的东西比丑的东西 创建起来更廉价,也更快捷。-- Robert C. Martin, 《软件之 美》 C 时间就是系统架构的生命。-- Philippe Kruchten C 方法产生于恐惧。 C 面对时间紧迫的压力,我们有理由质疑那种不顾时间花销、 一味追求软件架构高质量的做法。软件架构是软件系统质量 的核心,必须足够重视,但在不适当的时候“用时间换完美 ”会毁掉整个项目。 C 架构设计并非“好的就是成功的”,而是“适合的才是成功 的”。 ?方法论 ?Alistair Cockburn 的七条定理,总结为:沟通和反馈。 C RUP、XP C 重量之争 ? 软件架构设计中的关键要素及解决策略: 关键要素 ----------------------------------------------1. 是否遗漏了至关重要的非功能需求? 2. 能否驯服数量巨大且频繁变化的需求? 3. 能否从容地设计软件架构的不同方面? 4. 是否及早验证架构方案并作出了调整? 策略 ----------------------全面认识需求。 关键需求决定架构。 多视图探寻架构。 及早验证架构。? ? ? ? ? ?软件架构设计过程总览 一般的软件过程: ? 需求分析的几个概念 C 需求捕获 vs 需求分析 vs 系统分析 ? 需求捕获是获取知识的过程,知识从无到有。 ? 需求分析是挖掘和整理知识的过程,它在已掌握知识的 基础上进行。 ? 系统分析?如果说需求分析致力于“做什么”,那么系 统分析则涉及“怎么做”。 C 软件架构师不必是需求捕获专家,也不必是编写《软件需求 规格说明书》的专家。但他一定应在需求分类、需求折衷和 需求变更的研究方面是专家,否则他和其他软件架构师相比 ,就输在了“起跑线”上。 ? 概念性架构设计 ? 概念性架构设计的迭代方式: C 1. 鲁棒性分析; C 2. 引入架构模式; C 3. 质量属性分析。 ? 鲁棒性分析 C 所谓鲁棒性分析是这样一种方法:通过分析用例规约中的事 件流,识别出实现用例规定的功能所需的主要对象及其职责 ,形成以职责模型为主的初步设计。 C 鲁棒性分析是从功能需求向设计方案过度的第一步,所获得 的初步设计是一种理想化的职责模型,它的重点是识别组成 软件系统的高级职责块、规划它们之间的关系。 C 鲁棒性分析填补了分析和设计之间的鸿沟。 C 鲁棒图包含三种元素:边界对象、控制对象和实体对象。 ? 引入架构模式 ? 较为经典的几种架构模式: C 分层、MVC、微内核、基于元模型的架构、管道-过滤器等 。 ? 质量属性分析 ? “属性-场景-决策”表方法: ? 细化架构设计 ? 架构细化工作主要体现在基于五视图方法进行架构细化: ? 约束 ↓ ┌───────┐ 领域模型 -& │基于五视图方法│ 关键需求 -& │ │-& 架构方案 概念架构 -& │ 进行架构细化 │ └───────┘ ↑ 经验
? 逻辑架构设计中,“发现通用机制”是应被特别强调的。 ? 机制(Mechanism)是模式的实例。机制是特定上下文中重复出 现的问题的特定解决方案。 ? 具有良好架构的系统具备概念完整性。它通过对系统架构建立 一种清晰的认识来发现通用的抽象和机制。利用这种共性使最 终产生的系统结构更为简单。 ? 实现并验证软件架构 C 好的策略必须是一再求证、测试、发现瑕疵漏洞,另想途径 或方法来弥补策略不足,有时甚至得全盘放弃,重新策划。 -- 张明正,《挡不住的趋势》C 架构原型对功能性需求的实现非常有限,那么“架构验证” 要验证什么? ? 答案是要验证架构对质量属性需求的支持程度,包括运 行期质量属性和开发期质量属性。 ? 验证架构的两种方法: C 原型法。 ? 对于项目型开发,常采用“原型法”。即对一组架构设 计决策在非功能需求方面的满足程度进行验证。该原型 往往是演进型,而非抛弃型。 C 框架法。 ? 对于产品型开发,采用“框架法”有更多优点。该方法 将架构设计方案用框架的形式实现,并在此基础上进行 评估验证。在框架实现后,在框架基础上实现部分应用 的功能,即实现一个小的垂直原型,从而进行实际非功 能测试和开发期质量属性评价。 软件框架? 什么是框架 ? 框架与架构的区别 ? 常见的框架 为什么要用框架? 因为软件系统发展到今天已经很复杂了,特别是服务器端软件 ,设计到的知识,内容,问题太多。在某些方面使用成熟的框 架,可以避免重复做已有的基础工作,而只需要集中精力完成 系统的业务逻辑设计。 ? 框架一般是成熟,稳健的,可以处理系统很多细节问题,比如 ,事物理,安全性,数据流控制等问题。 ? 框架一般都经过很多人使用,所以结构很好,所以扩展性也很 好,而且它是不断升级的,使用框架的开发者可以直接享受别 人升级代码带来的好处。 ? 框架一般处在低层应用平台(如J2EE)和高层业务逻辑之间的 中间层。 常见的JAVA框架? ? ? ? ? ? ? ? ? ? ? ? ? ? ? EJB Struts Spring Hibernate IBatis JSF tapestry WAF Turbine COCOON ECHO JATO TCF Ext …159 .NET 框架? .NET 框架是创建、部署和运行 Web 服务及其他应用程序的一 个环境。它包括三个主要部分:公共语言运行时、框架类和 ASP.NET。 ? .NET 框架对 Web 站点的支持: ASP.NET ? 在编写 Windows 软件(使用 ATL/COM、MFC、VB或标准 Win32)方面,与当前创建应用程序的方式相比.NET都具有的 优势。160 C++框架? 标准库 C Dinkumware C++ Library、RogueWave Standard C++ Library 、SGI STL 、STLport GUI C MFC、QT 、 WxWindows 、Fox 、WTL 、GTK、 BCG、 Xtreme Toolkit 网络通信 C ACE 、StreamModule、SimpleSocket 综合 C P::Classes、 ACDK - Artefaktur Component D evelopment Kit 、 dlib C++ library、 Chilkat C++ Libraries 、C++ Portable Types Library (P Types) 、LFC 其他库 C Loki 、ATL 、FC++: The Functional C++ Libr ary、FACT! 、Crypto++?? ?? ? Boost C Regex 正则表达式库 C Spirit LL parser framework,用C++代码直接表达EBNF C Graph 图组件和算法 C Lambda 在调用的地方定义短小匿名的函数对象 C concept check 检查泛型编程中的concept C Mpl 用模板实现的元编程框架 C Thread 可移植的C++多线程库 、 C Python 把C++类和函数映射到Python之中 C Pool 内存池管理 C smart_ptr 智能指针 ? XML C Xerces 、 XMLBooster 、Pull Parser 、 Xalan 、 CMarkup 、 libxml++ ? 科学计算 C Blitz++ 、POOMA 、MTL 、CGAL ? 游戏开发 C Audio/Video 3D C++ Programming&Library 、KlayGE 龚 敏敏、 OGRE ? 线程 C C++ Threads 、 ZThreads ? 序列化 C s11n 、Simple XML Persistence Library ? 字符串 C C++ Str Library 、 Common Text Transformation Library 、 GRETA 不同层次的模式? 架构模式(Architectural Pattern) ? 设计模式(Design Pattern) ? 代码模式(Coding Pattern)164 ? 区别:在于三种不同的模式存在于它们各自的抽象层次和具体 层次。 ? 架构模式是一个系统的高层次策略,涉及到大尺度的组件以及 整体性质。架构模式的好坏可以影响到总体布局和框架性结构 。 ? 设计模式是中等尺度的结构策略。这些中等尺度的结构实现了 一些大尺度组件的行为和它们之间的关系。模式的好坏不会影 响到系统的总体布局和总体框架。设计模式定义出子系统或组 件的微观结构。 ? 代码模式是特定的范例和与特定语言有关的编程技巧。代码模 式的好坏会影响到一个中等尺度组件的内部、外部的结构或行 为的底层细节,但不会影响到一个部件或子系统的中等尺度的 结构,更不会影响到系统的总体布局和大尺度框架。 架构模式(Architectural Pattern)? 软件体系结构通常被称为架构,指可以预制和可重构的软件框 架结构。架构尚处在发展期,对于其定义,学术界尚未形成一 个统一的意见,而不同角度的视点也会造成软件体系结构的不 同理解。 ? 众多软件架构概念都是围绕“组成”和“决策”两个视角展开 的。 ? Booch、Rumbaugh和Jacobson的定义 C 架构是一系列重要决策的集合,这些决策与以下内容有关: 软件的组织,构成系统的结构元素及其接口的选择,这些元 素在相互协作中明确表现出的行为,这些结构元素和行为元 素进一步组合所构成的更大规模的子系统,以及指导这一组 织――包括这些元素及其接口、它们的协作和它们的组合― ―架构风格。? IEEE 610.12-1990软件工程标准: C 架构是以组件、组件之间的关系、组件与环境之间的关系为 内容的某一系统的基本组织结构,以及指导上述内容设计与 演化的原理(Principle)。 ? Garlan的定义 C 架构包括组件(Component)、连接件(Connector)和约 束(Constrain)三大要素。 ? 组件可以是一组代码(例如程序模块),也可以是独立 的程序(例如数据库服务器)。 ? 连接件可以是过程调用、管道和消息等,用于表示组件 之间的相互关系。 ? “约束” 一般为对象连接时的规则,或指明构件连接的 形式和条件,例如,上层构件可要求下层构件的服务, 反之不行;两对象不得递规地发送消息;代码复制迁移 的一致性约束;什么条件下此种连接无效等。 ? Shaw的定义: C “软件系统的架构将系统描述为计算组件及组件之间的交互 ”。 C 架构=组件+交互 几种典型的架构模式? 系统软件C 分层(Layer) C 管道和过滤器(Pipes and Filters) C 黑板(Blackboard)? 开发分布式软件C 经纪人(Broker) C 客户/服务器(Client/Server) C 点对点(Peer to Peer)? 交互软件C 模型-视图-控制器(Model-View-Controller) C 显示-抽象-控制(Presentation-Abstraction-COntrol) 其它? ? ? ? 面向对象风格(ADT) 基于消息广播且面向图形用户界面的Chiron2风格 基于事件的隐式调用风格(Event-based, Implicit Invocation) … 分层(Layer)? 从不同的层次来观察系统,处理不同层次问题的对象被封装到 不同的层中。 ? 软件为什么要分层? 为了实现“高内聚、低耦合”。把问题划分开来各个解决,易 于控制,易于延展,易于分配资源… ? 面向对象的、基于模块化的组件设计需要能够方便地修改应用 程序的各个部分。完成这一目标的一种好方法就是在层上工作 ,将一个应用程序的主要功能分离到不同的层或者级中。 分层模型? 从本质上讲,层代表了一个应用程序主要的功能。一般地,我 们将应用程序功能分为三个方面,对应3层架构模式。它们是数 据层(data layer)、商务层(business layer)和表示层( presentation layer)。 ? 数据层:包含数据存储和与它交互的组件或服务。这些组件和 服务在功能上和中间层相互独立(尽管在物理上不必一定相互 独立--它们可以在同一台服务器上)。 ? 中间层:包括一个或者多个组件服务,它们应用商务规则、实 现应用程序逻辑并完成应用程序运行所需要的数据处理。作为 这个过程的一部分,中间层负责处理来自数据存储或者发送给 数据存储的数据。 ? 表示层:从中间层获得信息并显示给用户。该层同时也负责和 用户进行交互,比较返回的信息并将信息回送给中间层进行处 理。 ? 数据层从数据库中获得较为原始的数据,商务层把数据转换成 符合商务规则的有意义的信息,表示层把信息转换成对于用户 有意义的内容。 ? 这种分层设计方式很有用,因为每一层都可以独立地修改。我 们可以修改商务层,不断地从数据层接受相同的数据,并把这 些数据传递到表示层,而不用担心出现歧义。我们也可以修改 表示层,使得对于站点外观的修改不必改动下面的商务层逻辑 。 管道和过滤器(Pipes and Filters)? 管道和过滤器架构模式是为处理数据流的系统提供的一种模式 。它是由过滤器和管道组成的.每个处理步骤都被封装在一个过 滤器组件中,数据通过相邻过滤器之间的管道进行传输。每个 过滤器可以单独修改,功能单一,并且它们之间的顺序可以进 行配置。 ? 一个著名的例子是传统的编译器。传统的编译器一直被认为是 一种管道系统,在该系统中,一个阶段(包括词法分析、语法 分析、语义分析和代码生成)的输出是另一个阶段的输入。 ? 问题: ? 一个必须处理或转换输入数据流的系统。把这样的系统作为单个组件 实现是不容易的: C 系统必须由几个开发人员同时进行协作开发,整个系统任务自然 就被分解为几个处理阶段,而且需求很容易变动。因此你就要通 过替换或重新排序处理步骤来为将来的灵活性作规划。通过加入 这样的灵活性,采用现有处理组件构建是可以办到的。 ? 系统的设计尤其是处理步骤的内部连接,必须考虑以下因素: C 未来系统的升级通过替换某些处理步骤,或重组步骤。 C 不同的语境中小的处理步骤要比大的组件更易于重用。 C 不相连的处理步骤不可共享信息。 C 存在不同的输入数据源,可以用多种方式输出或存放最终结果。 解决方案与结构? 管道和过滤器体系架构模式把系统任务分成为几个独立的处理步骤。 这些步骤采用通过系统的数据流连接。一个步骤的输出是下一个步骤 的输入。每个处理步骤由一个过滤器组件实现,它处理或者转化数据 ,并且系统的输入可以是多种数据源。? 这种体系架构模式具有许多特性: C 过滤器是独立运行的部件。也就是除了输入和输出外,每个过滤 器不受任何其他过滤器运行的影响。在设计上,过滤器之间不共 享任何状态信息。 C 独立性还表现在它对其处理的上游和下游连接的过滤器是&无知&的 .它的设计和使用不对与其连接的任何过滤器施加限制,唯一关心 的是其输入数据的,然后进行加工处理,最后产生数据输出。 优点与缺点? 优点: C 结构简单:系统的行为是所有过滤器行为的简单复合。 C 系统易于维护和增强:增加新过滤器,替换旧过滤器。 C 支持复用:过滤器只同其输入、输出端口的数据相关。 C 各过滤器可以并发运行。 ? 缺点: C 容易导致批处理方式:每个过滤器从输入数据到输出数据的转换 是一个整体。转换通常不适合交互式的应用。 C 有时必须维护两个分离而又相关的流之间的对应关系。 C 同实现有关,过滤器之间的数据传输率较低,而且每个过滤器都 要作类似的数据打包和解包的工作。 黑板(Blackboard)? 又称看板模式:在这种架构中,有两种不同的构件:一种是表 示当前状态中心数据结构;另一种是一种相互独立的构件,这 些构件对中心数据进行操作。这种架构主要用于数据库和人工 智能系统的开发。 ? 模式识别、数据挖掘。 经纪人(Broker)? 客户和服务器通过一个经纪人部件进行通信,经纪人负责协调 客户和服务器之间的操作,并且为客户和服务器发送请求和结 果信息。 客户/服务器(Client/Server)? 系统分为客户和服务器,服务器一直处于侦听的状态,客户主 动连接服务器,每个服务器可以为多个客户服务。 优缺点? 优点: C 结构简单,系统中不同类型的任务分别由客户和服务器承担 ,有利于发挥不同机器平台的优势; C 支持分布式、并发环境,特别是当客户和服务器之间的关系 是多对多时,可以有效地提高资源的利用率和共享程度; C 服务器集中管理资源,有利于权限控制和系统安全。 ? 缺点: C 在大多数client-server风格的系统中,构件之间的连接通过 (远程)过程调用,接近于代码一级,表达能力较弱。 点对点(Peer to Peer)? 系统中的节点都处于平等的地位,每个节点都可以连接其他节 点。在这种架构中,一般需要由一个中心服务器完成发现和管 理节点的操作。ICQ以及Web Service技术的大多数应用,都是 典型的点对点结构。 模型-视图-控制器(MVC)? 当应用程序的用户界面非常复杂,且关于用户界面的需求很容 易变化时,我们可以把交互类型的软件抽象成模型、视图和控 制器这三类组件单元,这种抽象可以很好地分离用户界面和业 务逻辑,适应变化的需求。大多数现代交互软件都在一定程度 上符合这一架构模型的特点。 ? MVC模式最吸引人之处在于它迫使用户必须抽象自己的代码, 把项目分为表示、逻辑和控制三部分,每部分间的关联较小。 ? 以MVC模式构造软件,可以使得软件结构灵活、重用性好、扩展 性佳。 模型―视图―控制器交互的示意图 模型:视图:控制器:? 模型: ? 模型表示应用的数据及操作这些数据的逻辑方法。任何和整个 应用有关的持久性数据都应该放在模型中。对于模型,它所提供 的API不能只针对某一个专门的视图或控制器,应该更一般化以 适应不同客户的需求。 ? 视图: ? 视图将模型的当前状态展示给用户,具体的显示方法由视图负责, 因此一个模型可以适用多个不同的视图。在模型状态改变后,通 过模型和视图之间的协议,视图得知这种改变并修改自己的显示 。对于用户的输入,视图将它们交给控制器处理。 ? 控制器: ? 控制器负责交互和将用户输入的数据导入模型,它还利用用户的 输入将应用转向其他视图。一些非持久的临时数据也应该在视 图中存取。 采用MVC的好处? 显示、逻辑和数据分开,这样一方面的改变不会影响另一方面。 C 更新视图: C 如原来用的是CLI (Command Line Interface)的,后来要改成GUI, 只要了解原来的模型和控制器的接口,然后构造GUI,把它按过去的 协议和模型关联起来就可以了,这样做增加了组件的重用性和灵活 性。 C 复用视图: C 假设针对某个模型数据开发了一套View,那么在其他访问该模型数 据的地方,完全可以再次使用该套件或将现在的View组合成一个复 合视图。每个单视图有自己和模型的连接协议和自己的响应控制 器,这样开发就仅仅变成了简单的组合。 C 更新控制器: C 以在不更改视图显示的情况下,更改控制器,以达到更改视图与用户 交互的响应模式的目的。 在Java Web应用中的惯用法? 模型: ? 模型的构建方式可以随应用成本的不同而不同。 ? 在两层结构的应用中,Web层直接和持久数据层交互,此时的模 型通常是一系列的Java对象。这些对象可能是从关系型数据库 中通过查询得到的,或者是通过关系―对象映射框架得到的。? N层体系比较复杂,比如Web层和EJB服务器通信。虽然在 EJB2.0规范中,通过本地接口来提高实体Bean问效率,但Web 层直接访问实体Bean仍然是效率比较低的,因此在一般情况下 , Web层访问有由会话Bean返回的JavaBeans,这被称为值对 象模式( Value Obiect) 。 Event-based风格? 优点: C 支持复用,构件通过登记它所感兴趣的事件被引入系统; C 便于系统演化,构件可以容易地升级或更换。 ? 缺点: C 系统行为难以控制,发出事件的构件放弃了对系统的控制, 因此不能确定系统中有无或有多少其它构件对该事件感兴趣 ,系统的行为不能依赖于特定的处理顺序。 C 同事件关联的会有少量的数据,但有些情况下需要通过共享 区传递数据,这时就涉及到全局效率和资源管理问题。 架构设计原则 ? 软件被用来解决人们的业务或领域问题,开 发软件的过程就是 去获得解决业务问题结果发软件的过程就是去获得解决业务问 题结果 的过程。 人类在问题解决规律研究方面已经有大量的 现成成果;传统的问题解决步骤,实际上为 软件开发(解决软 件问题)提供了现成的 (战略级的)理论方法框架。 现代的软 件工程技术,其基础实际上就建立 在这些问题解决规律之上。 ? 前段中所描述的问题解决步骤,存在一个隐含的假定前提,就 是所有问题都能够采用同 样简单的方法、步骤来加以解决。对 于那些普通、单一的问题而言,这个假定是成立的;但对于软 件开发这种复杂和多方面问题交织在一起的情况,假定就不再 成立了。实际上,软件具有不一致性与多样性,不同性质的软 件,不相同的地方很多,所适应的 开发方法也可能完全不同。 ? 破除软件开发中的神秘主义 C 国内软件界存在一定程度的神秘主义倾向,在自己无力使用 常规软件工程途径解决软件问题后,往往简单地将软件开发 归于艺术化、玄学化。 C 经常看到的一种典型现象――某个高手熬了几个通宵,终于 拿出了一个精巧的设计方案;团队其他成员都很钦佩他,并想 向他学习其中设计的技巧;但高手吹嘘说这完全是靠其灵感 所得,思考过程毫无逻辑可言。 ? 光有宏观的过程、方法还不够 C 无论是简单的问题解决步骤,还是包含了大量实践活动的软 件过程域(科目),它们都属于宏观的解决途径。然而,任何软 件问题,其最终解决还是要落实到具体的细节之上,这些问题 细节需要采用与之相对应的微观方法来解决。 C 例如,架构设计作为技术解决过程域中的一项实践 (或者分 析设计科目中的一项活动),涉及到大量的模块划分问题;而帮 助人们进行划分的方法则主要有比较、分类等思维法。
? 抽象(Abstraction)、封装(Encapsulation)和信息隐藏( Information Hiding) ? 分而治之(Divide-And-Conquer)和模块化(modularization ) ? liskov替换原则(LSP) ? 策略和实现的分离(Separation of Policy and Implementation ) ? 接口和实现的分离(Separation of Interface and Implementation) ? 单一引用点(Single Point of Reference) 信息隐藏? 信息隐藏(Information hiding)是指隐藏(删除)了程序构件 操作的细节,只将访问该构件所必要的信息提供给访问该构件 的其他构件。 C在这一点上,OO方法和传统方法基本一致。因此,OO系统应 支持信息隐藏,除提供隐藏等级说明的量度外,还应提供OO 设计质量指标。 抽象? 抽象(Abstraction)使设计者只关心一个程序构件的主要细节( 数据和过程两者),而不考虑底层的细节。 C 抽象指关注事物中与问题相关的部分(通常是一个角度或方 面),而忽略其它不相关内容(细节)的一种思考方式; C 抽象依赖于选择的问题领域和角度; C 抽象是一种相对概念,在OO和传统开发方法中都被采用。 如处于抽象的较高层次时,我们可忽略更多的细节,当处于 抽象的较低层次时,可以引入更多的细节,即提供一个关于 概念或项的更详细的看法。 ? 抽象解决不了软件中过的规模问题 C 抽象能很好第降低单个软件原始的复杂度,但却解决不了软 件中的规模问题。 C ? 根据7+/―2原荆,人能够同时处理的元素是5-9个,当软件中 对象(种类)的数目超过一定限度后,人们就无法同时去思考和 处理这些对象了。 C 模块化通过划分,帮助人们将同时要考虑的对象数目减少到 普通智力的人能够胜任自如的地步。 ? 模块化(Modularity) C 指逻辑和物理上将事物分解为更小、更简单的分组(例如需 求和类),从而满足软件工程化管理的需要; C 模块化的实质--D分而治之”; C 在面向对象的范式中,子系统、包、构件和对象本身都是模 块化的实体元素。
? 模块化带来模块间关系处理的问题 C 将系统划分为若干模块后,人们可以分别在各模块I内部处 理那些数量已大幅减少的元素;但为了确保系统的完整一致, 同时还必须在系统层面未处理这些模块及其之间的关系。 C 根据7+/―2原则,人能够同时处理的元素是5~9个,但此间实 际上还有一个隐舍的条件,就是每个元素本身的复杂度也不 超过一定限度,由此,如果模块对外展现的内客过多,仍然是无 法在系统层面处理这些模块(及其关系)的。 C 封装在模块化划分的基础上迸一步简化了模块本身对外暴露 的复杂度。 ? 封装是指将特性(属性、行为)在物理上局限于一个单独的黑 盒抽象中,且将它们的实现(和相关的设计决定)隐藏于公共接口 背后; ? 在面向对象的范式中,从系统、子系统到对象都拥有封装的特性 。 ? 抽象类(还有接口)使得客户代码cl ient code只需要关注对象外 在行为中与它相关的部分(忽略对象固有的但井不相关的其它外 在行为.例如从其它类继承的操作); ? 对象的封装机制则封闭了对象所有的内部结构和内部行为,使客 户代码无需关注对象内部的细节。 ? 抽象 VS 封装 C 抽象和封装都是一种简化问题的思维方式,但它们实现简化 的方式不同?抽象剔除了不相关的内容,以突出重点;? 相对应 地,封装则隐藏了相关但不需要被知道 (不能被剔除)的内部 细节,以减少依赖。 C 剔除与隐藏对于外部(客户)而言,其效果是等价的 ? 简单模块化的问题 C 模块化通过划分来简化问题,但是简单的模I块化途径仍然 处理不了大规模模的事物。 C 针对一个具有1000个元素的系统,我们当然可以将其划分为 150个模块,这样每个模块的元素不超过7个,可以交给150个 人来分担完成;但是同时为了确保系统的完整和一致,需要有 人来协同150个人的工作,而这显然...? 层次化为模块化划分提供了一种递归途径,以支持处理更大规模 的事物。 ? 层次化指任何组织为一种树状结构的抽象级别或顺序; ? 在面向对象的范式中,层次结构包括: C 聚合层次结构Aggregation hierarchy C 包容层次结构containment hierarchy C 类层次结构class hierarchy C 泛化层次结构generaDzation hierarchy C 继承层次结构inheritance hierarchy C 具体化层次结构specialization hierarchy C 划分层次结构partition hierarchy C 类型层次结构type hierarchy
? 隔离关注面: C 软件中包含的内容纷繁复杂、规模巨大;前述的抽象、模块 化、封装、层次化等途径,实际上是从有形的实体结构方面 帮助人们简化问题;然而软件还包含其它非实体(例如功能、 性能、经济性等)方面Aspccts的内容,为了简化这些方面的问 题解决,人们需要研究其它的方法和途径。 ? 软件中的不同方面,往往被不同的涉众所关心,于是将其抽象为所 谓的“关注面”。
? 软件中胶着一体的各个方面(Aspect) C 实体对象有明显的边界,可以方便地被分割。而方面却不是 实体,其实质上只是附着在某个实体上的各类属性事物,例如, 一个业务应用中的实体类,它需要被持久化(保存在数据库中 ),还要满足权限控制的要求,最后为了方便测试,还要支待日 志记录等等;这些都是同一客体的不同侧面,它们不能独立于 客体而存在。 C 另外,软件中的不同方面Aspects内客,常常相互渗透而交织一 起,例如,上述实体类中的实现待久化代码与安全的就可能混 合在一块;又如目标系统的进程组织就首期逻辑结构影响, ? 隔离关注面 Separation of Concerns C 软件中的众多方面同时存在,并相互胶着,这使得开发活动 变得更为困难和复杂。 C 前述“分而治之”已经给了我们启示――必须将复杂和大规 模模的问题分解开未,分别加以解决。 C 然而方面不是实体,不能在物理上进行分割;不过,我们还是可 以从逻辑上来将同一方面的内客组织在一起,并与其它方面 的内客分隔开来。 C 无论是实体还是逻辑上的方面,都是涉众的“关注面”,由此 我们引入一个统一的概念 “隔离关注面”。它使得人们能 够分别地处理被分解的小问题,或同一问题的不同方面。 ? 隔离关注面的途径: C 在隔离关注面时,对于关系明确的场合,简单地分割就行了; 但对于关系交织一起,需一同考虑的场合,要先做概略的总体 考虑,然后再分开做处理。 C 隔离关注面的途径包括: ? 内外的隔离――部件对外公开的行为、及其与其它部件 之间的关系,与其自身的内部细节,被分开来处理。 ? 空间上的隔离――?软件部件的分割(模块化)、同一部件 不同侧面的分割(倒如某个类的逻辑包结构与其源码目录 文件被分别考虑)等, ? 时间上的隔离――划分良好的部件,可以安排在不同的时 间来完成;由于部件之间的依赖较弱,进而能够并行来进行 (开发).时间上的隔离首先依赖于空间上的隔离, ? 质量因素的隔离――同时满足不同的质量要求是非常困 难的。一则,同时为实现多个质量约束而设计将过于复杂 而难以开展。二则,不同的质量属性之间可能是相互冲突 的,要同时满足它们几乎是不可能的。因此,我们应当在不 同的时机,分别去考虑实现不同的质量要求,即隔离质量关 注点。 ? 隔离关注面的其它途径还有:问题域与解决域(实现域)分 离、人员职责与技能要求的划分等等 ?层次模式与架构中的分层 C 分层模式是一种将系统的行为或功能以层为 首要的组织单 位来进行分配(划分)的结构模 式 C 通常在逻辑上进行垂直的层次Layer划分,在物理上则进行 水平的层级Tier划分 C 分层要求层内的元素只依赖于当前层和之下的相邻 层中的 其它元素(并非绝对的要求) ? 分层是为了隔离各层的关注面 ? 分层的标准是: C 将相似的事物分组在一起 C 将不同的事物分开 ? 分层的目标在于隔离关注面: C 不同层的元素与不同领域相关,例如,业务层关 注业务领 域问题、中间件层关注适配操作系统的底层差异等软件自身 问题。 C 各层的元素属于同一抽象级别,而不同抽象级别的特性不同 ,要求的处理方式也不一样。 C 稳定与变化的隔离。 ? 指南:层次模式的优缺点 C 分层结构的优点: ? 上层可以直接使用下层,而不需要去了解下层的实现细 节 ? 上层对下层透明,因而可以改变底层的实现,而不影响上层的 应用 ? 可以减少不同层之间的依赖 ? 容易制定出层标准 ? 层可以用来建立提供给上层的多项服务 C 分层结构的缺点: ? 层不可能封装所有的功能,一旦有功能变动,可能会波 及所 有的层(例如领域对象增加一个属性) ? 穿过层次的调用,将引起效率降低;对于水平分布的层 级Tier 划分,效率降低则极为明显 ? 指南:划分应用层子系统 C 考察的因素 ? 用户的分类 ? 用户界面的粒度 ? 用户界面交互逻辑及其关联的复杂度 ? 用户界面的部署约束 C 划分方式 ? 围绕系统的用户执行者Actor,来划分应用子系统(物理 上隔离的可执行体) ? 使用工作视图模式,通过统一的主界面来访问应用子系 统(逻辑上的) ? 构架分析时所面对的通用问题 ? 开发健壮的构架(特别是分布式)通常要解决以下问题 C 选择候选层级Tier C 如何保持会话状态 C 确定共通的用户界面交互机制 C 确定共通的数据存取机制(OR-Mapping ) C 解决并发和同步冲突 C 支持事务处理 C 接口的定位与实例化机制(常用途径:名字服务) C 设计统一的异常机制 C 安全机制的实施 ? 上述问题中的大部分将抽象为分析机制 ? 通用问题被总结为分析机制列表 C GUI交互 C 遗留接口Legacy Interface C 持久化Persistency C 通讯Communication (IPC and RPC) C 消息路由Message routing C 分布式计算Distribution C 事务管理Transaction management C 进程控制与同步 (资源争用) C 信息交换、格式转换 C 安全Security C 安全Security C 错误侦察/处理/报告 C 冗余备份Redundancy 面向对象的设计原则 liskov替换原则(LSP) 子类型必须能够替换掉其基类型? 问题的根源是关于行为的: C 基类中有的行为在子类中不存在或不适当。 C IS A的本质是指行为的一致,而不是生活中的语言。 C 违反了LSP原则的本质是派生类的行为与基类中的不一致。 ? 如果违反了LSP原则,常会导致在运行时的类型判断(RTTI)违 反OCP原则。 C 例如:函数A的参数是基类型,调用时传递的对象是子类型 ,正常情况下,增加子类型都不会影响到函数A的,如果违 反了LSP,则函数A必须小心的判断传进来的具体类型,否 则就会出错,这就已经违反了OCP原则。 违反LSP导致违反OCP的简单例子 改善 例:会议管理系统? 问题描述 ? 用来管理各种各样的会议参与者信息。数据库里面有个表 Participants,里面的每条记录表示一个参会者。 ? 因为经常会发生用户误删掉某个参会者的信息。所以用户删除 时,并不会真的删除那参会者的信息,而只是将该记录的删除 标记设为true。24小时以后,系统会自动将这条记录删除。但 是在这24小时以内,如果用户改变主意了,系统还可以将这条 记录还原,将删除标记设置为false。
改善 例:GUI对象? 假定一个Component代表一个GUI对象,如按钮或者文本框等 。
改善2 例:Line 改善:提取公共部分替代继承 例: PresistentSet 需求变更? 需求变更 C 想在该层次中加入持久性(PresistentSet),即可以把其中 的元素写入流,稍后可能由另外的程序再从流中读回其中的 集合。? 可得的资源 C 能找到的,提供了持久化的第三方容器类不是一个模板类。 它只接受基类为PersistentObject的派生对象。? 自然的做法: C PresistentSet把它的所有方法都委托给了第三方实例。例如 Add方法将调用第三方实例的Add。
问题? 表面合理,其实隐藏着别扭的设计: C 加入到第三方持久性集合中的元素必须得从 PersistentObject派生,由于PersistentSet只是把调用委托给 第三方持久性集合,所任何要加入PersistentSet的元素也必 须从PersislentOhjet派生,可是Set的接口没有这样的限制, C 当客户程序向基类Set中加入元素时,客户程序不能确保该 Set实际上是否是一个PenistentSet因而,客户程序没有办法 知道它所加入的元素是否应该从PefiistentObject派生。 ? 后果 C 如果客户企图向PersislentSet中添加不是从PersstentObject派生 的对象,将会发生运行时错误。dynamic_cast会抛出异常,但是抽 象基类Set的所有现在的客户都不会预计到调用这种异常。 C 由于Set的派生类会导致这些函数出现错误,所以对类层次所做的 这种改动违反了LSP。 C 以前传递Set的派生对象时没有问题的函数,现在传递给它们 PersistentSet对象时却会引发运行时错误。 C 调试这种问题很困难,因为这个运行时错误发生之处距离实际的逻 辑错码很远。 C 逻辑错误可能是由于把PersistentSet传给了一个函数,也可能是由 于向PersistentSet加入的对象不是派生自PersistentObject。 ? 改善,通过约定解决问题: C 不知道的人不要用:约定不让PersistentSet和 PersistentObject暴露给整个应用程序。它们只被一个特定 的模块使用。该模块负责从持久性存储设备读出所有容器, 也负责把所有容器写入到持久性存储设备。 C 从容器写入流:Adapter:容器的内容先被复制到对应的 PersistentObject派生对象中,再加入到PersistentSets,然 后存入流中。C 从流中写入容器:Adapter:先把信息从流读到 PersistentSet中,再把PersistentObjects从PersistentSet中 取出,复制到常规的对象中,然后再加入到常规的Set中。 ? 问题: C 需要不断向开发人员解释。 C 人员没有弄清楚或者不同意,就会违反这个约定。而一次违反就会 致使整个结构的失败。 ? 改善 C PersistentSet和Set之间不存在IS―A关系,它不应派生自Set。 C 分离这个层次结构,但保留部分Set和PersistentSd之间有一些公 有的特性。其实仅仅是Add方法致使LSP原则出了问题。 C 创建了一个层次结构,其中Set和PersistentSet是兄弟关系,统一 在一个操作抽象接口下,就可对PersistentSet对象进行遍历以及 测试成员等关系操作,但它不能够把不是派生自PersistentObject 的对象加入到PersistentSet中。
DIP and IOC康凯 相关概念? 关于解耦 C 依赖倒置(DIP) C 控制反转(IoC) C 依赖注入(DI) C 服务定位器(SL) C 有些是手段,有些是原则,不过其间的差异并不太重要,更重要 的是其共同点:其根本目标都是解除依赖,将组件的配置与使用 分离开。? 其它名词 C 服务 C 组件 C 框架 C 类库 C 应用程序 接口和实现分离? 面向过程的接口与实现分离
依赖于特定函数的框架? 问题:双向依赖: ? 解决:通过回调函数消解框架到运用程序的依赖: ? 通过模板方式消解GUI框架到应用程序的依赖
? 应用程序来创建“服务类” 、Reader和Writer类的实例对象。把 Reader和Write注入“服务类”内部。 ? 这样,“服务类”中的代码就只和抽象接口相关的了。具体实现代码 发生变化时,“服务类”不会发生任何变化。添加新的实现时,也只 需要改变应用程序的代码,就可以定义并使用新的Reader和Writer类 。 ? “构造器注入” :应用程序通过Copy类的构造函数注入依赖关系。 ? “接口注入”:为Copy类抽象出一个注入接口,应用程序通过接口 注入依赖关系。 ? “设值注入”:为Copy类提供一个设值函数,应用程序通过调用设 值函数来注入依赖关系。
电影清单的例子? 一个组件,用于提供一份电影清单,清单上列出的影片都是由一位特 定的导演执导的。 class MovieLister { ... public Movie[] moviesDirectedBy(String arg) { List allMovies = finder.findAll(); for (Iterator it = allMovies.iterator(); it.hasNext();) { Movie movie = (Movie) it.next(); if (!movie.getDirector().equals(arg)) it.remove(); } return (Movie[]) allMovies.toArray(new Movie[allMovies.size()]); } } ? 其中真正想要考察的是如何将MovieLister对象与特定的finder对象连 接起来。 ? 要求:我们希望moviesDirectedBy方法完全不依赖于影片的实际存储 方式。 C 这个方法只能引用一个finder对象, C 而finder对象必须知道如何实现findAll的细节。 ? 给finder定义一个接口: public interface MovieFinder { List findAll(); } ? 当要实际寻找影片时,就必须涉及到MovieFinder 的某个具体子类。 在这里,我把“涉及具体子类”的代码放在MovieLister 类的构造函 数中。 对抗变化? 从一个逗号分隔的文本文件中获得影片列表。 ? class MovieLister... private MovieF public MovieLister() { finder = new ColonDelimitedMovieFinder(&movies1.txt&); } ? 对抗变化: C 文件清单的名字更改: ? 可以从一个配置文件获得文件名。 C 如果用SQL 数据库、XML 文件、web service,或者另一种格式 的文本文件来存储影片清单: ? 用另一个具体的类来获取数据。该类从MovieFinder接口派生 即可。 C 创建合适的MovieFinder派生类的实例: ? 不能对抗此变化。 客户代码? public void testWithPico() { MutablePicoContainer pico = configureContainer(); MovieLister lister = (MovieLister) pico.getComponentInstance(MovieLister.class);Movie[] movies = lister.moviesDirectedBy(&Sergio Leone&); assertEquals(&Once Upon a Time in the West&, movies[0].getTitle()); } Spring 注入? 为了让MovieLister 类接受注入,需要为它定义一个设值方法,它接 受类型为MovieFinder的参数: class MovieLister... private MovieF public void setFinder(MovieFinder finder) { this.finder = } ? 类似地在MovieFinder的实现类中,定义一个设值方法,接受类型为 String 的参数: class ColonMovieFinder... public void setFilename(String filename) { this.filename = } 配置文件? 设定配置文件:XML 文件是比较理想的配置方式。 &beans& &bean id=&MovieLister& class=&spring.MovieLister&& &property name=&finder&& &ref local=&MovieFinder&/& &/property& &/bean&&bean id=&MovieFinder& class=&spring.ColonMovieFinder&& &property name=&filename&& &value&movies1.txt&/value& &/property& &/bean& &/beans& 接口隔离原则(ISP) 例? 安全系统,有一些Door对象可以被加锁和解锁,并且Door对象 知道自己是开着还是关着的。 ? 需求变化: ? 实现一个TimedDoor,如果门开着的时间过长,它就会发出警 报声。为了做到这一点,TimeDoor对象需要和一个Timer的对 象交互。如何将TimerClient与TimedDoor类联系起来? 一种方案 问题? Door依赖于TimerClient C 并不是所有种类的Door都需要定时器。 C 违反LSP:不需时钟的派生类中需要提供TimeOut的退化方法。 C 不必要的复杂和重复性:使用这些派生类的客户程序被迫包含 TimerClient的定义。 ? Door接口被TimeOut方法污染了: C 持续的加入方法会使Door接口不断变胖。 C 每次Door中加入一个方法,其它派生类中都需要对自己不需要的 方法提供退化处理。 ? 客户对TimerClient接口的改变会影响接口使用者。 C 例如需要在Timer中注册多个超时通知(在TimeOut方法中加入超 时ID),则即使不需要定时器的类也会受影响。 使用委托分离接口 使用多重继承分离接口 内接口与外接口IOuter IInnerPackage InnerPackage 普通接口与智能接口INormalISmartPackage 架构设计验证 软件可维护性? ? ? ? ? 软件的可维护性概述 软件可维护策略 软件可扩展性(Extensibility)设计策略 软件灵活性(Flexibility)设计策略 软件可插入性(Pluggability)设计策略267 软件的可维护性概述? 软件可维护性的定义:软件能够被理解、校正、适应及增强功 能的容易程度。 ? 软件的可维护性、可使用性、可靠性是衡量软件质量的几个主 要特性,也是用户十分关心的几个问题。 ? 软件的可维护性是软件开发阶段的关键目标。影响软件可维护 性的因素较多,设计、编码及测试中的疏忽和低劣的软件配置 ,缺少文档等都对软件的可维护性产生不良影响。软件可维护 性可用下面七个质量特性来衡量,即可理解性、可测试性、可 修改性、可靠性、可移植性、可使用性和效率。对于不同类型 的维护,这七种特性的侧重点也是不相同。268 ? 可维护性和可复用性 C 一般来说,一个易于维护的系统,就是复用率较高的系统; 一个复用率较好的的系统,就是一个易于维护的系统。但是 ,实际上,可维护性和可复用性是两个独立的目标。 C 软件维护就是软件的再生。一个好的软件设计,必须能够允 许新的设计要求以比较容易和平稳的方式加入到已有的系统 中去,从而使这个系统能够不断的的焕发出活力。 C 一个可维护性较好的系统,应当允许维护工作能够以容易、 准确、安全和经济的形式进行。269 ? 导致可维护性较低的原因: C 1.过于僵硬:在系统中加入一个新的功能,不管大小都很难 ,不仅意味着建造一个独立的新的模块,而且因为这个新功 能会波及很多其他模块,最后成跨越几个模块的改动。 C 2.过于脆弱:与软件的过于僵硬同时存在,是软件系统在修 改已有代码时过于脆弱。对一个地方的修改,往往会导致看 上去没有什么关系的另外一个地方发生故障。 C 3.复用率低:所谓复用,就是指一个软件的组成部分,可以 在同一个项目的不同地方甚至另一个项目中重复使用。复用 率低,指当一段代码,函数,模块的功能可以在新的模块或 新的系统使用,但是已有代码依赖于其他很多东西,很难分 270 开。 C 4.黏度过高:一个改动可以保存原始设计意图和原始设计框 架的方式进行,也可以以破坏原始意图和框架进行。第一种 方法对系统的未来有利,第二种办法是权宜之计,可以}

我要回帖

更多关于 产品结构设计ccjoo 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信