1、1高级软件架构设计2目录o第一单元:软件生命周期与软件架构介绍第一单元:软件生命周期与软件架构介绍o第二单元:技术架构视图第二单元:技术架构视图面向对象程序设计原则与模式面向对象程序设计原则与模式 o用GRASP模式指导设计o领域模型o面向对象设计的基本原则o第三单元:用第三单元:用UML辅助系统分析与设计辅助系统分析与设计oUML简介及常见疑难问题辨析o借鉴RUP的UML建模与分析o第四单元:设计模式与软件设计思想第四单元:设计模式与软件设计思想o设计模式o常用的软件架构风格及适用情况分析oSOA 及分层架构设计o第五单元:架构设计实践第五单元:架构设计实践3第一单元:软件生命周期与软件架构
2、介绍4oIT行业的人才结构与软件架构师的定位o软件架构师应掌握的知识体系o软件架构设计的特点、层次、分类o软件架构的主要理论、方向和趋势o软件工厂,实现软件开发的产业化5软件架构师的定位o系统架构师的职责:o一、理解系统的业务需求,制定系统的整体框架(包括:技术框架和业务框架)o二、对系统框架相关技术和业务进行培训,指导开发人员开发。并解决系统开发、运行中出现的各种问题。o系统架构师的目的:o对系统的重用、扩展、安全、性能、伸缩性、简洁等做系统级的把握。o系统架构师能力要求:o一、系统架构相关的知识和经验。o二、很强的自学能力、分析能力、解决问题的能力。o三、写作、沟通表达、培训。6o角色o软
3、件架构师Software Architecto定义o主导系统全局分析设计和实施、负责软件构架和关键技术决策的角色7o职责n领导与协调整个项目中的技术活动(分析、设计和实施等)n推动主要的技术决策,并最终表达为软件构架n确定和文档化系统的相对构架而言意义重大的方面,包括系统的需求、设计、实施和部署等“视图”n确定设计元素的分组以及这些主要分组之间的接口n为技术决策提供规则,平衡各类涉众的不同关注点,化解技术风险,并保证相关决定被有效的传达和贯彻n理解、评价并接收系统需求n评价和确认软件架构的实现8o专业技能o技术全面、成熟练达、洞察力强、经验丰富,具备在缺乏完整信息、众多问题交织一团、模糊和矛盾
4、的情况下,迅速抓住问题要害,并做出合理的关键决定的能力。o具备战略性和前瞻性思维能力,善于把握全局,能够在更高抽象级别上进行思考。o对项目开发涉及的所有问题领域都有经验,包括彻底地理解项目需求,开展分析设计之类软件工程活动等。o具备领导素质,以在各小组之间推进技术工作,并在项目压力下做出牢靠的关键决策。o拥有优秀的沟通能力,用以进行说服、鼓励和指导等活动,并赢得项目成员的信任。9o以目标导向和主动的方式来不带任何感情色彩地关注项目结果,构架师应当是项目背后的技术推动力,而非构想者或梦想家(追求完美)o精通构架设计的理论、实践和工具,并掌握多种参考构架、主要的可重用构架机制和模式。o具备系统设计
5、员的所有技能,但涉及面更广、抽象级别更高。10软件架构师的知识体系o软件架构师作为整个软件系统结构的总设计师,其知识体系、技能和经验决定了软件系统的可靠性、安全性、可维护性、可扩展性和可移植性等方面的性能。因此一个优秀的软件架构师必须具备相当丰富的知识、技能和经验。o通过对比软件架构师和系统分析师在软件开发中的职责和角色,不难发现软件架构师与系统分析师所必需的知识体系也是不尽相同的,系统分析师的主要职责是在需求分析、开发管理、运行维护等方面,而软件架构师的重点工作是在架构与设计这两个关键环节上。因此在系统分析师必须具备的知识体系中对系统的构架与设计等方面知识体系的要求就相对低些;而软件架构师在
6、需求分析、项目管理、运行维护等方面知识的要求也就相对低些。11o成为一名合格的软件架构师必须具备的知识n信息系统综合知识体系n软件架构知识体系12?oMFC,MSF,MOF,RUP,J2EE,Spring,SOA,JUnit,ORM,.NetoMVC,UML,XML,Corba,MDA,MDD,Web-ServiceoRSS,Web2.0,AJAX,Serverlet,HibernateoIOC, AOPoRuby On RailsoRupoBPELoWorkflow EngineoLBSoOracleoCMMIoMQo13软件架构师在干什么?o思考、思考、再思考n深入理解、准确把握建设的业务
7、需求n分析所有可见的问题、障碍、风险n充分参考已有的成功方案,降低风险o交流、讨论、博弈、质疑n对构思中的方案不断提出质疑,避免漏洞n广泛听取各层面的意见,开拓思路n反复质疑、逐步完善已有的设计构思o在动手实现之前验证设计方案的正确性14软件架构师的知识结构o软件知识n最好要有系统开发全过程经验。n对 IT 建设生命周期各个环节有深入了解,包括:系统/模块逻辑设计、物理设计、代码开发、项目管理、测试、发布、运行维护等。n深入掌握1-2种主流技术平台上开发系统的方法。n了解多种应用系统的结构。n了解架构设计领域的主要理论、流派、框架。15软件架构师的知识结构o业务知识n深入了解系统建设的业务需求
8、。n了解系统的非功能需求和运行维护需求。n了解企业 IT 公共设施、网络环境、外部系统。16软件架构师的思维方式o基于框架的思维n架构设计的层次(Enterprise, Application, etc)nIT 的生命周期(What, Why, Where, How, When, etc)n成功经验以及方法论的指导o合理把握技术细节n把握各个层次应有的内容n合理忽略不应有的技术细节17软件架构师的思维方式o风险管理意识n采用成功经验、避免不应有的风险o多方位的开放思维n多维度、多方向、包容性、避免排他性n分析、质疑、抽象、归纳n没有绝对好的架构设计,只有相对优秀的方案18信息系统综合知识体系o
9、(1)计算机系统综合知识:包括计算机组成与体系结构、嵌入式系统和操作系统等方面的知识。o(2)系统配置和方法:包括系统配置技术和系统性能等方面的知识。o(3)典型系统应用:包括网络应用、数据库应用和多媒体系统等方面的知识。o(4)系统开发:包括程序设计语言、软件开发方法、需求分析和设计方法、测试评审方法、开发管理、应用系统构建、系统审计、外部资源使用和基于中间件的开发等方面的知识。o(5)安全性和可靠性技术:包括数据安全与保密、防闯入和防病毒、容错技术、可靠性模型与分析技术、系统可靠性、安全规章和保护私有信息规则等方面的知识。19o(6)标准化:包括标准化的基础知识、标准化分级、编码标准、数据
10、交换标准、软件工程标准、信息安全标准、基于构件的软件标准和标准化组织机构等方面的知识。o(7)信息化基础:包括政府信息化与电子政务、企业信息化与电子商务、信息化的有关的法律和规定等方面的知识。o(8)数学和英语:至少具有大学以上的数学和英语基础知识。20软件架构知识体系o(1)系统计划:包括项目的提出和可行性分析、系统方案的制定、评价和改进、新旧系统的分析与比较、现有软、硬件和数据资源的有效利用等。o(2)软件架构设计:包括软件架构的概念、软件架构与设计、架构风格、特定领域的架构风格、基于架构的软件开发方法、架构评估、软件产品线和系统演化等。o(3)设计模式:包括设计模式的概念、组成、分类和实
11、现、模式和软件架构的关系等。o(4)系统设计:包括处理流程设计、人机界面设计、文件与存储设计、数据库设计、网络应用系统的设计、系统运行环境的集成与设计、中间件与应用服务器、性能设计与性能评估等。o(5)软件建模:包括定义问题与归结模型、结构化系统建模与数据流图、面向对象系统建模、数据库建模和逆向工程等。o21o(6)分布式系统设计:包括分布式通信协议的设计、基于对象与web的分布式设计、基于消息和协同的分布式设计和异构分布式系统的互操作性设计等。o(7)嵌入式系统设计:包括实施任务调度和多任务设计、中断处理和异常处理、嵌入式系统开发设计等。o(8)系统可靠性分析与设计:包括系统故障模型和可靠性
12、模型、系统的可靠性分析与可靠度计算、提高系统可靠性的措施、系统的故障对策和系统的备份与恢复等。o(9)系统的安全性和保密性设计:包括系统的访问控制技术、数据的完整性、数据与文件的加密、通信的安全和系统的安全设计等。o(10)复杂架构设计:包括操作系统的架构、编译器的架构和大型基础库的架构等。22软件架构师的任职条件o根据软件架构师的职责和角色定位,以及知识体系,从实践的角度考虑,合格的软件架构师应该具有以下能力和经验:o(1)具有8年以上的软件项目开发实际工作经验,其中至少有3年以上的代码编写工作经验,4年以上的基于面向对象和构件开发方法的软件产品设计经验。 o(2)具有5个以上大中型开发项目
13、的总体规划、方案设计经验,有大中型应用系统开发和实施的成功案例。o(3)对相关的技术标准有深刻的认识,对软件工程标准和规范有良好的把握。 o(4)对.Net或Java技术及整个解决方案有深刻的理解及熟练的应用,精通Web Service,熟练掌握流行的架构。 23o(5)对设计模式有深刻的理解,并能在此基础上设计出适合产品特性和质量属性的框架。o(6)具有面向对象的分析、设计和开发能力,精通UML和XML,能熟练使用Rational Rose、PowerDesigner等工具进行设计。 o(7)具有良好的团队意识和协作精神,有较强的沟通能力和书面表达能力。o(8)具有旺盛的精力和学习能力,能快
14、速掌握新技术和新方法。 24第二单元:技术架构视图面向对象程序设计原则与模式252627用GRASP模式指导设计282930313233343536373839404142434445领域模型46o层次结构o领域模型o从EJB到轻量级框架47层次结构o表现层(present)o业务层业务层外观业务层核心领域对象管理/服务/仓库层领域对象层o持久层数据访问层o数据库48o领域模型中的各种角色:n实体-有唯一的标识,并且要有属性和行为(非GET/SET),添加了行为,使其具有生命力。往往在设计时,实体的形为最难决断。为确定行为,我们必须识别它们的责任和协作。类的责任是指该类要做、知道、或决定的一切
15、,由一个或多个方法完成。类中有属性和关联,协作就是为完成自己的责任所调用其它关联类。n值对象-没有标识没有行为。如Address类。n工厂-定义创建实体的方法,封装实例化对象并将一些关联对象注入。n仓库(repository)管理实体的集合,主要有查找和删除实体的方法.实现类可以调用执久化层(如Hibernate,Ibatis)n服务(Service) ,实现整个应用程序的工作流(workflow)。服务包含那些无法指派的单个实体的行为,由作用于多个对象方法组成。如可以调用repository查找到实体对象,然后委派给这些对象。服务和facade很像,但不一样,它不处理以下事情:1)执行事务。
16、2)收集返回给表现层的数据。3)脱钩对象。4)其它事情。服务可以说是业务的协调者,业务逻辑可以分散到实体对象中。49领域模型o失血模型o贫血模型o充血模型o胀血模型50失血模型oDO只有属性及其getter/setter方法,没有任何业务逻辑。o缺点:行为与数据分离,很多情况导致维护与理解困难。51贫血模型oDO包含不依赖于持久化的领域逻辑;依赖持久化的领域逻辑归入Service层。Service(业务逻辑,事务封装) DAODOo优点:各层单向依赖,结构清楚,易于实现和维护。设计简单易行,底层模型非常稳定。o缺点:DO部分的持久化逻辑被放入Service层,不够OO。Service层过重。5
17、2充血模型o与贫血模型类似,不同处在于如何划分业务逻辑:绝大多业务逻辑都应该放在DO里(包括持久化逻辑),而Service层很薄,仅仅封装事务和少量逻辑,不和DAO层打交道。Service(事务封装)DO DAOo优点:符合OOService层很薄,只充当Facade的角色,不和DAO打交道。53o缺点:DAO和DO双向依赖。如何划分Service层逻辑和Domain层逻辑没有确定的规则,取决与设计人员自己的理解。Service层封装事务,须对所有的DO逻辑提供相应的事务封装方法,造成重定义所有的Domain logic。Service的事务化封装的意义等于把OO的Domain logic转换
18、为过程的Service 事务脚本。充血模型在domain层实现的OO在Service层又变成了面向过程。 54胀血模型o取消Service层,只剩下DO和DAO层,在DO的domain logic上面封装事务。nDO(事务封装,业务逻辑)nDAOn(RoR甚至合并为一层) o优点:n分层简化n符合OOo缺点:nservice逻辑也强行放入DO ,引起了DO不稳定。nDO暴露给web层过多的信息,可能引起不必要的耦合。55o原则:n业务对象封装了内在的业务逻辑,而应用服务封装了外在于业务对象的业务逻辑。 56EJB到轻量级框架oEJBoPOJO (业务逻辑) + 轻量级框架(Hibernate、
19、JDO、iBATIS(持久化)、Spring(事务管理、安全)57EJBoEJB:o编写分布式业务应用程序的Java标准架构。o提供大量服务:n声明型事务, EIB容器自动启动、提交和回滚事务。n业务逻辑能参与由远程客户发起的分布式事务。n提供声明型安全,大部分情况下不再摇要编写安全代码求(bean部署描述符里的条目指定准可以防问某个具体bean)。58o例:在两个账号间进行转账的服务。59oPOJO(业务逻辑) +Hiibernate、JDO、iBATIS(持久化)、Spring(事务管理、安全)。oo 典型的EJB方法 POJO方法 oo组织 过程式业务逻辑 面向对象设计 oo实现 基于E
20、JB POJO oo数据库访问 JDBC/SQL或实体bean 持久层框架 oo返回给表示层的数据DTO 业务对象 oo事务管理 EJB容器管理的事务 Spring框架 oo应用程序组装 显式的JNDI查询 依赖注入 o60o新设计是面向对象、基于POJO, 而非基于EJB的过程式。o它使用构建在JDBC上的持久层框架来访问数据库, 并不直接使用JDBC。o业务逻辑由POJO facade而非会话bean进行封装。o事务由Spring框架而非EJB容器进行管理。o业务逻辑向表现层返回实际的业务对象,而不是DTO。o应用程序通过将组件的依赖作为setter或构造子参数传入来进行组装,而不是之前采
21、用Java命名和目录接口(JNDI )查询的组件。o由于该设计面向对象,并采用上述轻量级技术,因此较之前看到的EJB版本对开发人员要友好。61o基于轻量级框架设计的好处是,它提供事务和持久化时并不要求应用程序类实现任何特殊接口。甚至当应用程序的类需要运行在事务里或是持久的时候,它们仍是POJO,设计者可以继续享受POJO的种种好处。62o面向对象的优点:整个设计更易理解和维护。它并不是一个无所不能的大型类, 而是由大量小类组成, 每个类只共有若干职责。此外,诸如Account、BankingTransaction和OverdraftPolicy类都与现实世界的概念对应, 因此易于理解。其次,面
22、向对象设汁也更易测试: 所有类都能并且应当进行独立的测试。EJB只能通过调用它的public 方法如Transter进行测试,难度大。(只能测试p-blic方法暴露的复杂功能,无法测试其中简单的部分)。面向对象象设计更易扩展, 它可使用设计模式,如Stategy和Template等。EJB风格的过程式设计往往需耍修改核心代码。63o不适合用面向对象的场合:大量数据集合的关系操作。o 以数据库为中心的管理程序 :这个领域所对应的现实世界是一个面向关系的世界,表与表的关联体现的是彼此的业务关系。 复杂的SQL固然不好维护,但业务真是复杂到简单的SQL都难以描述的程度,采用面向对象描述则更加困难,维
23、护也更困难,同时还损失了效率。比较大的事务。性能要求高的地方。(直接用Sql或者存储过程;牺牲可维护性和可复用性)上层流程。64面向对象设计的基本原则6566liskov替换原则(LSP)67子类型必须能够替换掉其基类型o问题的根源是关于行为的:n基类中有的行为在子类中不存在或不适当。nIS A的本质是指行为的一致,而不是生活中的语言。n违反了LSP原则的本质是派生类的行为与基类中的不一致。o如果违反了LSP原则,常会导致在运行时的类型判断(RTTI)违反OCP原则。n例如:函数A的参数是基类型,调用时传递的对象是子类型,正常情况下,增加子类型都不会影响到函数A的,如果违反了LSP,则函数A必
24、须小心的判断传进来的具体类型,否则就会出错,这就已经违反了OCP原则。68接口隔离原则(ISP)69使用多个专门的接口比使用单一的总接口要好。一个类对另外一个类的依赖性应当是建立在最小的接口上的。一个接口代表一个角色,不应当将不同的角色都交给一个接口。没有关系的接口合并在一起,形成一个臃肿的大接口,这是对角色和接口的污染。“不应该强迫客户依赖于它们不用的方法。接口属于客户,不属于它所在的类层次结构。”这个说得很明白了,再通俗点说,不要强迫客户使用它们不用的方法,如果强迫用户使用它们不使用的方法,那么这些客户就会面临由于这些不使用的方法的改变所带来的改变。70例比如说电子商务的系统,有订单这个类
25、,有三个地方会使用到,一个是门户,只能有查询方法,一个是外部系统,有添加订单的方法,一个是管理后台,添加删除修改查询都要用到.根据接口隔离原则(ISP),一个类对另外一个类的依赖性应当是建立在最小的接口上.也就是说,对于门户,它只能依赖有一个查询方法的接口.71依赖倒置原则(DIP)72相关概念o关于解耦n依赖倒置(DIP)n控制反转(IoC)n依赖注入(DI)n服务定位器(SL)n有些是手段,有些是原则,不过其间的差异并不太重要,更重要的是其共同点:其根本目标都是解除依赖,将组件的配置与使用分离开。o其它名词n服务n组件n框架n类库n应用程序73接口和实现分离接口和实现分离 o面向过程的接口
26、与实现分离74757677电影清单的例子o一个组件,用于提供一份电影清单,清单上列出的影片都是由一位特定的导演执导的。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(); retur
27、n (Movie) allMovies.toArray(new MovieallMovies.size(); 78o其中真正想要考察的是如何将MovieLister对象与特定的finder对象连接起来。o要求:我们希望moviesDirectedBy方法完全不依赖于影片的实际存储方式。n这个方法只能引用一个finder对象,n而finder对象必须知道如何实现findAll的细节。o给finder定义一个接口: public interface MovieFinder List findAll(); o当要实际寻找影片时,就必须涉及到MovieFinder 的某个具体子类。在这里,我把“涉及具
28、体子类”的代码放在MovieLister 类的构造函数中。79对抗变化o从一个逗号分隔的文本文件中获得影片列表。oclass MovieLister. private MovieFinder finder; public MovieLister() finder = new ColonDelimitedMovieFinder(movies1.txt); o对抗变化:n文件清单的名字更改:o可以从一个配置文件获得文件名。n如果用SQL 数据库、XML 文件、web service,或者另一种格式的文本文件来存储影片清单:o用另一个具体的类来获取数据。该类从MovieFinder接口派生即可。n创
29、建合适的MovieFinder派生类的实例:o不能对抗此变化。80配置文件o设定配置文件:XML 文件是比较理想的配置方式。movies1.txt81第三单元:用UML辅助系统分析与设计82UML用来描述模型的内容有3种,分别是事物( Things )、关系Relationships )和图( Diagrams )。83UML中的关系oUML中的关系(Relationships )主要包括4种:o1、关联关系o2、依赖( Dependency)关系o3、泛化( Generalization )关系o4、实现( Realization )关系84一些常见问题辨析o类的层次结构表示o属性与聚合o关
30、联角色o关联类85层次结构PartAssemblyIComponent* *86领域建模重数87细化类模型88关联角色o关联角色名出现在关联终端的旁边。当仅仅使用关联名不足够表达清楚后,可以用关联角色名来加强表达。o可以把每个名称都当成伪属性,关联角色名提供了一种可以遍历关联的方法。PersonCompany0.1* *0.1+employee+employeremployeeJoe DoeMary BrownJean SmithemployerSimplexSimplexUnited Widgets89 o在创建类图时,应该为使用正确的角色名,而不是为每个引用引入一个独立的类。o因为角色名可
31、以区分对象,所以附在一个类上的关联名必须唯一(可以把角色名想象成类的伪属性)。同样,角色名不应该与类的属性名重复。ParentChild0.n20.n2Person*0.2+Child+Parent*0.290关联类o正如可以用属性描述类的对象一样,也可以用属性来描述关联的链接,可以把这样的一组属性组成关联类。91Actor的一些注意事项o包括人与系统,总是外部的。o定义了边界。oActor是“角色”,不是特定的人或特定的事。o要有恰当的名字。o可以泛化o不是可有可无的东西。另一方面它可以划分系统与外部实体的界限,是系统设计的起点。92用例的一些注意事项o是需求分析的第一步。用户首先关心功能。
32、o用例是对一个系统或一个应用的一种单一的使用方式所作的描述,是关于单个活动者在与系统对话中所执行的处理行为的陈述序列。o不是事件流。o不是需求规格说明,但反映了主要的功能性需求。o识别用例最好是从分析流开始。o每个用例都是独立的。o用例名用动宾结构描述,不要写成一个名词。o用例是分层的,一般而言,高层/中层用例更有实际意义。o不要将不同的用例混合在一起。o用例与编码:低层的用例可以辅助编码,高层的不能。o扩展用例:基础用例不必知道扩展用例的细节,只提供扩展点。93仓库信息系统的用例图94借鉴RUP的UML建模与分析95全局分析o全局分析侧重于定义拟建系统所采用的构架以及影响构架的要素。全局分析
33、充分利用相似或问题中的经验,避免在确定构架上浪费人力和物力。o选用架构模式o识别关键抽象:寻找那些无论在问题域或方案领域都具有普遍意义的概念点。o标识分析机制:将那些问题领域(应用逻辑)没有直接关联的计算机概念及相应的复杂行为表述为支撑分析工作的“占位符”。o选定分析局部:针对拟建系统的整体架构,找出那些蕴含相对高风险的局部作为工作内容。96全局分析o常见的分析机制留存分布式处理安全性进程间通信消息路由进程控制与同步交易事务管理信息交换信息的冗余错误检测、处理和报告数据格式转换97局部分析o提取分析类o转述需求场景o整理分析类98局部分析o分析类的类型划分众多实践表明,如果立足于软件功能需求,
34、拟建系统往往在三个维度易于发生变化:一、拟建系统和外部要素之间交互的边界;第二,拟建系统要记录和维护的信息;第三,拟建系统在运行中的控制逻辑。通常按照这三个变化因素的维度,将分析类划分为三种类型:边界类、控制类、实体类系统边界Use Case行为协调基本信息99局部分析100局部分析101局部分析102局部分析o整理分析类分析类是这样的类:它代表问题域中的简洁抽象;o分析类映射到真实世界的业务概念(并且据此仔细命名)。 问题域是首先产生软件系统(以及从此而来的软件开发活动)需求的域。通常,这是特定的业务领域,如在线销售或者客户关系管理。然而,务必注意,问题域可能根本不是任何特定业务活动,但 是
35、可能产生需要软件在其上运转的一块物理硬件这是嵌入式系统。基本上,所有业务软件开发服 务于某种业务需求,自动化一个已有业务过程或者开发具有有意义的软件组件的新产品。103分析类的职责o职责是类和它的客户之间的契约或者是类对它的客户的义务。本质上,职责是类提供给其他类的 服务。分析类具有直接同类(由它的名称所表达)的目的相一致的以及直接同该类正在建模的真实世 界“事物”相一致的非常内聚的职责集合,这一点是至关重要的。例如ShoppingBasket示例,你将期 望该类具有如下职责:向购物篮添加商品;从购物篮删除商品;显示购物篮中的商品。 这是内聚的职责集合,一切都是为了维护客户选择的商品集合。它是
36、内聚的,因为所有的职责都朝着相同的目标维护客户已经选择的商品集合。实际上,我们能够把这些职责概括为非常高级层 次的职责“维护购物篮”。同样,向 ShoppingBasket 中添加如下职责:104分析类的职责验证信用卡;接收付款;打印收据。 但这些职责似乎同购物篮的目的或直觉语法不匹配。它们不是内聚的,显然应该赋予其他什么类 可能是类CreditCardCompany、类Checkout以及类ReceiptPrinter。把职责适当地分配给分析类 以最大化每个类中的内聚性,是很重要的。o最后,良好的类与其他类之间具有最低数目的耦合。我们以给定类与其他类具有关系的数目来度量类间的耦合度。类间职责
37、的平均分布趋向于产生低耦合度。把控制或职责局限于单一的类趋向于增 加到该类的耦合度。105分析类经验法则o以下是创建形式良好的分析类的一些经验法则。每个类大约35个职责典型地,类应该保持尽可能简单,这通常限制类能够支持的35个职 责的数目。先前ShoppingBasket 的示例是带有小的和可管理数目职责的专注的类的好的示例。不存在独立的类好的OO分析和设计的精华是,类相互协作让用户受益。同样,每个类应该 同小部分类协作以提供所期望的功能。类可以把它们的一些职责托付给专注于特定功能的其他“辅助”类。当心很多非常小的类 有时很难取得正确的平衡。如果模型看起来具有大量的非常小的类, 每个类都具有一
38、个或者两个职责,那么你应该仔细查看以把一些小的类整合成更大的类。106当心少数几个非常庞大的类上述的反面是,模型具有很少的类,但每个类都是具有职责数 量(5)的庞大的类。解决问题的策略是依次查看这些类,看看是否每个类都能够被分解成为 两个或者多个能够承担恰当数目职责的、更小的类。当心“伪类”伪类其实是一般的过程函数,它伪装成类。当心万能类 存在似乎能够承担任何工作的类。看看名称为“system”和“controller”的 类!处理这个问题的策略是看看万能类的职责是否能够分解成内聚的子集。如果是,每个这些 内聚职责集合可能独立成类。这些更小的类协作以实现由原始万能类所提供的行为。107分析类经
39、验法则n避免深度继承树设计良好的继承层次的本质是继承层次中每个抽象层次应该具有良好定义 的目的。容易添加很多实际上不能服务于任何目的层次。n实际上,通常的错误是使用继承来实 现一种功能分解,其中每个抽象层次恰有一个职责! 无论从哪个方面来讲,这都是无意义的,是会导致复杂的、难以理解的模型。n在分析中,类代表业务事物,而业务事物趋向于形成更宽(不超过三层)的继承层次。 我们把三层或者更多层次的继承认为是“深度”继承。 108第四单元:设计模式与软件设计思想109设计模式在实际开发中的运用o复用现有的、高质量的、针对常见的重复出现问题的解决方案。o建立通用的术语以改善团队内部的沟通。o将思考转移到
40、更高的视角。o判断是否拥有正确的设计,而不仅仅使一个可以运行的设计。o改善代码的可修改性。o发现“庞大的继承体系”的替代方案。110GoF中的模式分类111设计模式的特点o设计模式最根本的意图是适应需求变化n隔离变化的部分与不变的部分,将之封装起来。o针对接口编程,而不要针对实现编程o达成高内聚合低耦合,提高复用o提倡优先使用聚合,而不是继承112例o一个日志记录工具。目前需要提供一个日志API,提供客户方便地调用。o该日志要求被记录到指定的文本文件中,记录的内容属于字符串类型,其值由客户提供。o可以容易地定义一个日志对象。public class Logpublic void Write(s
41、tring target, string log) /实现内容; 当客户需要调用日志的功能时,可以创建日志对象,完成日志的记录:Log log = new Log();log.Write(“error.log”, “log”);113114例o我们需要设计一个数据库组件,它能够访问Sql Server数据库。如果用ADO.Net,需要使用如下的对象:nSqlConnection, SqlCommand, SqlDataAdapter等。o不用模式的做法:可以直接创建这些对象:nSqlConnection connection = new SqlConnection(strConnection)
42、;nSqlCommand command = new SqlCommand(connection);nSqlDataAdapter adapter = new SqlDataAdapter();115策略(Strategy)模式116例:电子零售系统o该电子零售系统必须处理来自不同国家的销售定单。例如在美国与加拿大。需求如下:请况请况过程过程美国l据UPS的价格计算运费l使用美国邮政规则检查地址l根据销售额或服务,按照当地税收规则计算税费金额l使用美元处理款项加拿大 l根据主要的加拿大托运公司的价格计算运费l使用加拿大邮政规则检查地址l根据销售额或服务,按照加拿大各省的税收规则计算税费金额(G
43、ST和PST) l使用加拿大元处理款项117分析矩阵118桥接(Bridge)模式119o意图o“将抽象部分与它的实现部分分离,使它们都可以独立地变化”。o抽象部分是指“不同的事物在概念层次上的联系”。分离是指“让各部分的行为各自独立,或至少显式指出关联”。120例通过引入一个Rectangle抽象类,利用了这一事实:不同的Rectangle派生类之间唯一的差异是如何实现drawLine方法。V1Rectangle类的实现方式是:保存一个DP1对象的引用,使用DP1对象的draw_a_line方法。V2Rectangle类的实现方法是:保存一个DP2对象的引用,使用这个对象的drawline方
44、法。121需求变化o用户要求支持另一种形状圆形。122识别变化o首先识别出“什么在发生变化”。在上述的例子中,变化点是“不同类型的形状”和“不同类型的画图程序”。共同的“概念”则是“形状”和“画图程序”。o 用Shape类来封装拥有的形状的概念。形状有责任知道如何画自己。Drawing对象负责画线和圆。123描述变化o下一步是描述出现的特定变化:Shape类拥有矩形和圆形 。 画 图 程 序 分 别 拥 有 一 个 基 于 D P 1 的 对 象(V1Drawing)和一个基于DP2的对象(V2Drawing)。124桥接模式125命令(command)模式126o意图n将一个请求封装为一个对
45、象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作。o别名n动作(Action),事务(Transaction)o动机n有时必须向某对象提交请求,但并不知道关于被请求的操作或请求的接受者的任何信息。n例如,用户界面工具箱包括按钮和菜单这样的对象,它们执行请求响应用户输入。但工具箱不能显式的在按钮或菜单中实现该请求,因为只有使用工具箱的应用知道该由哪个对象做哪个操作。而工具箱的设计者无法知道请求的接受者或执行的操作。命令模式通过将请求本身变成一个对象来使工具箱对象可向未指定的应用对象提出请求。这个对象可被存储并像其他的对象一样被传递。这一模式的关键是一个抽
46、象的Command类。127常用的软件架构风格及适用情况分析 o软件架构o软件框架o常见的架构风格128软件架构概论o系统架构是一个软件系统从整体到部分的最高层次的划分。o一个系统通常是由元件组成的,而这些元件如何形成、相互之间如何发生作用,则是关于这个系统本身结构的重要信息。o详细地说,就是要包括架构元件(Architecture Component)、联结器(Connector)、任务流(Task-flow)。所谓架构元素,也就是组成系统的核心砖瓦,而联结器则描述这些元件之间通讯的路径、通讯的机制、通讯的预期结果,任务流则描述系统如何使用这些元件和联结器完成某一项需求。129o建造一个系统
47、所作出的最高层次的、以后难以更改的,商业的和技术的决定。o在建造一个系统之前会有很多的重要决定需要事先作出,而一旦系统开始进行详细设计甚至建造,这些决定就很难更改甚至无法更改。显然,这样的决定必定是有关系统设计成败的最重要决定,必须经过慎重的研究和考察。130架构的目标o可靠性(Reliable):n软件系统对于用户的商业经营和管理来说极为重要,因此软件系统必须非常可靠。o安全性(Secure) :n软件系统所承担的交易的商业价值极高,系统的安全性非常重要。o可伸缩性(Scalable) :n软件必须能够在用户的使用率、用户的数目增加很快的情况下,保持合理的性能。只有这样,才能适应用户的市场扩
48、展得可能性。131架构的目标o可定制化(Customizable) :n同样的一套软件,可以根据客户群的不同和市场需求的变化进行调整。o可扩展性(Extensible):n在新技术出现的时候,一个软件系统应当允许导入新技术,从而对现有系统进行功能和性能的扩展o可维护性(Maintainable):n软件系统的维护包括两方面,一是排除现有的错误,二是将新的软件需求反映到现有系统中去。一个易于维护的系统可以有效地降低技术支持的花费。132o客户体验(Customer Experience):n软件系统必须易于使用。o市场时机(Time to Market):n软件用户要面临同业竞争,软件提供商也要
49、面临同业竞争。以最快的速度争夺市场先机非常重要。133架构的种类o根据我们关注的角度不同,可以将架构分成三种:n逻辑架构n物理架构n系统架构134逻辑架构o软件系统中元件之间的关系,比如用户界面,数据库,外部系统接口,商业逻辑元件等等。135物理架构o软件元件是怎样放到硬件上的o下图描述了一个分布于北京和上海的分布式系统的物理架构,图中所有的元件都是物理设备,包括网络分流器、代理服务器、WEB服务器、应用服务器、报表服务器、整合服务器、存储服务器、主机等等。136系统架构o系统的非功能性特征,如可扩展性、可靠性、强壮性、灵活性、性能等。o系统架构的设计要求架构师具备软件和硬件的功能和性能的过硬
50、知识,这一工作是架构设计工作中最困难的工作。137架构的两要素o元件划分和设计决定。o逻辑元件:n一个软件系统中的元件首先是逻辑元件。这些逻辑元件如何放到硬件上,以及这些元件如何为整个系统的可扩展性、可靠性、强壮性、灵活性、性能等做出贡献,是非常重要的信息。o设计决定:n进行软件设计需要做出的决定中,必然会包括逻辑结构、物理结构,以及它们如何影响到系统的所有非功能性特征。这些决定中会有很多是一旦作出,就很难更改的。o基于数据库的系统架构:n一般有多少个数据表,就会有多少页的架构设计文档。比如一个中等的数据库应用系统通常含有一百个左右的数据表,这样的一个系统设计通常需要有一百页左右的架构设计文档