课程简介
1、全真案例,借助案例与设计模式知识的原理,借助最佳实践,帮助您提高设计能力,从而提高开发效率和设计质量
2、以新视角,揭示模式的本质、思想方法,剖析出模式之“道”,跳出“为模式而模式”的“陷阱”
3、提升设计能力,使开发人员由“编程小工”到设计专家
4、提出场景驱动设计,利用领域建模、职责驱动、扩展式设计以及重构,提高软件设计质量,实现卓越软件设计
5、关注业界内设计模式,以实战训练驱动对面向对象设计的理解与运用
目标收益
1、员工无法接手遗留系统,原因是代码杂乱,可读性差
2、团队成员没有设计模式知识与经验,无法实施敏捷开发
3、系统难以重构,不利于产品的重用与二次开发
4、开发效率得不到保障,因为详细设计人员不能理解架构文档与详细设计方案
5、设计方案难于应对需求变更
6、设计的系统架构缺乏可扩展性、可维护性和可测试性,不能合理地重用
7、架构、设计、开发三个环节中各个角色不能理解设计意图,很难沟通
培训对象
IT人员
课程大纲
第一单元: 面向对象设计: 角色、职责与协作 职责驱动设计 |
面向对象设计的核心驱动力是对象的职责,合理的职责分配是卓越软件设计的前提。只有合理地分辨对象的职责,才能够定义良好的对象,并实现符合系统一致性的对象协作关系。 1、职责的层次 通过职责层次模型对需求进行分析,识别出业务价值、业务功能与业务实现。职责层次的分解可以有效地帮助设计者辨别职责。 (1)职责层次的识别 (2)职责层次与软件架构层次之间的关系 (3)职责与概念、规约与实现 (4)案例分析:分析邮件服务器代码暴露的问题,在可重用性、代码可维护性、可扩展性等诸多方面着手,剖析代码坏味道。通过分辨职责层次,来改善设计。并提出需求变更,从而引入对Observer模式、Strategy模式、Simple Factory模式、Mediator模式与Chain Of Responsibility模式的对比与分析; (5)实战演练:设计一个作业调度框架,它能够根据指定的时间触发作业,执行自定义任务。 2、职责的分类 职责并不等于功能,也不等同于行为或方法。分析职责,应从对象的认知与行为入手。 3、对象的角色 角色、职责与协作是三位一体的关系,角色是发起职责的对象,职责则应该是对象之间的协作。不同角色的对象,履行的职责是不同的。 (1)信息持有者:信息的格式;是否需要持久化;信息源的改变,是否需要更新;处理信息的方式; (2)构造者:构造者与构造对象的关系;构造的方式;聚合与合成; (3)服务提供者:主动告知,被动告知;独立的行为;提供有业务价值的行为; (4)协调者:如何委派和转发请求;如何通知其他对象要做的工作;如何通知状态的变化; (5)控制者:控制者与被控制者的关系;控制的决策与逻辑;驱动其他对象;收集与决策有关的信息; (6)案例:处理HTTP请求与应答,体现信息持有者角色;JMS对Queue的创建体现构造者角色;税务报告的生成体现服务提供者角色;服务定位器体现协调者角色;内容验证器体现控制者角色; 4、职责与封装的关系 缺乏合理的封装,就会缺少正确的领域对象,从而导致领域信息散乱分布到系统各个方法,使得概念不够清晰,导致职责混乱。 5、模块级的职责分配 (1)问题分析:模块之间职责的分配,在面临三种问题时,应该如何应对?通过对具体问题的分析,讨论模块之间的职责分配,以及对高内聚、松耦合的理解。同时,该问题分析还将引入Template Method模式; (2)问题分析:错误的职责分配带来的循环依赖问题,以及对包的复用原则的违背,提出解决办法; (3)模块重用:对eBay模块的分析,以及对某大型系统架构的演进,提出模块重用的方式; 6、原则与模式 (1)单一职责原则:分析该原则的核心思想,关注对象的变化点; (2)案例分析:功能引擎中对功能对象的加载,如何体现职责分离带来的好处;通过对案例分析引入Proxy模式; (3)专家模式:专家模式的核心思想是信息的持有者是操作该信息的专家; (4)案例分析:报表参数的处理方式,如何通过识别设计违背了专家模式,并依据专家模式对设计进行改进,从而巧妙地利用多态消除代码坏味道,并进而通过引入Adapter模式处理模块之间的依赖关系; (5)自治对象:分析了自治对象的特征,分别包括:最小完备,稳定空间,自我履行与独立进化。 (6)案例分析:用户状态机,给出了某金融系统中复杂的用户状态迁移,体现的复杂授权、登录等业务逻辑,并由此引入State模式来简化设计,体现自治对象的特征。 |
第二单元 面向对象设计: 抽象与变化 扩展式设计 |
合理的职责分配并不能完全保证软件设计的卓越,因为需求变化是软件开发的常态,因此设计必须在一定程度满足变化,保证系统的可扩展性。 1、抽象的意义 抽象的关键在于寻找多个对象(或行为)具有的共同特征,并对特性进行泛化。泛化的特征可以暴露在外,从而隔离内部的实现。 (1)用例分析:对用例和参与者的泛化;遵循的原则; (2)案例分析:授权框架的设计,体现了对共同特征的提取,合理引入Chain Of Responsibility模式与Template Method模式; (3)案例分析:项目管理模型的抽象,通过对多种项目管理过程进行分析,对各种模型概念进行分类,并抽象出模型的共同特征,从而简化模型; 2、识别变化 要保证设计的可扩展性,主要过程是识别变化点,然后对变化进行封装。 (1)变化点:常见的变化点包括业务规则、算法策略、外部服务、硬件支持、命令请求、协议标准、数据格式、业务流程、系统配置、界面表现; (2)案例分析:电子商务系统的Invoice业务规则,引入Specification模式;CIMS系统的机器加载策略,引入Strategy模式;短信服务,引入Facade模式与Adapter模式;人力资源系统考勤模块,引入Gateway模式; (3)案例分析:CQRS框架,对命令处理逻辑的包装,引入Decorator模式,并通过分析变化点,引入另一种替代Decorator模式的设计。 3、依赖解耦 处理变化的关键是要解除对具体对象的依赖。 (1)表驱动法 (2)配置与反射 (3)IoC容器 (4)惯例优于配置 4、扩展式设计 扩展式设计分为三个步骤,分别为:分离职责各司其职,利用抽象统一接口,引用接口预留空白。扩展式设计可以有效地保证整个系统的可扩展性。 (1)扩展式设计的步骤 (2)实战演练:订单处理,通过三次迭代逐步改进原有设计,并分别遵循专家模式、分离原则与扩展式设计,保证设计在修改最小的前提下满足需求变化。在设计演进中,讨论对设计模式的合理运用,并引入Specification模式; (3)案例分析:配置管理框架的设计,该框架能够支持配置信息的多种存储形态,包括文件、数据库、LDAP等;支持多种获取配置的方式,如Web服务,REST服务。配置管理框架的接口需要保证其统一性和一致性,同时在满足可扩展要求下,提供接口的易用性。 (4)案例分析:消息队列规范的设计。通过分析JMS、MSMQ、RabbitMQ和NServiceBus的设计,理解抽象的含义,例如理解面向接口设计、接口隔离原则、按意图设计、Facade模式与企业集成模式。 (5)实战演练:CIMS基于消息的分布式架构。通过对服务的统一抽象,以及对消息处理的职责分配,建立一个协作合理的分布式架构。设计过程中会引入Command模式、Publisher – Subscriber模式、Message Bus模式、Message Translator模式、Lookup模式。 |
第三单元 场景驱动设计: 利用场景建模 设计过程 |
无论进行怎样的设计,都不能离开具体的场景。场景驱动设计的要义是基于场景有针对性地进行设计。场景既是设计的驱动力,又是设计的约束,从而获得恰如其分的设计。 1、场景的目标层次 (1)概要目标:系统层次的场景划分,每个概要目标可对应子系统的需求目标。通过概要目标引入领域驱动设计的Unbounded Context。 (2)用户目标:业务层次的场景划分,每个用户目标对应各个子系统所提供的业务价值,并以服务的形式暴露给调用者。 (3)子功能:功能层次的场景划分,每个子功能都对应于业务功能,并以领域对象或横切关注点的方式,由服务调用。 (4)案例分析:电子商务系统的场景目标划分,以层次模型的方式表现场景。 2、场景的6W模型 (1)6W的内容:分别为who(对应于角色)、why(对应于业务价值)、when(对应于对象的协作)、what(对应于业务功能)、where(对应于场景边界)和hoW(对应于业务实现); (2)6W模型的设计驱动力:6W模型的关键是在场景边界内,通过场景识别出角色,再以角色为设计入口,运用职责的层次模型识别出业务价值、业务功能和业务实现,从而根据职责模型获得领域模型,再通过时序图,处理对象之间的协作关系,进一步精炼出更为准确的领域模型。 3、场景驱动设计演练 (1)实战案例:某大型跨国公司的内部培训系统,包括培训计划制订,培训实施以及员工职业生涯规划等功能; (2)对整个系统进行分析,识别场景的目标层次; (3)划分需求场景,运用6W模型进行场景驱动设计; 场景一:将培训的Ticket分配给员工。在分配ticket时,需要指定deadline,以及取消票或deadline到期时的Action。同时,将该ticket的状态设置为pending; 场景二:在接收到分配ticket的通知后,并在设定的deadline之前,拒绝该ticket。此时,会自动执行事先分配给ticket的取消票的action; 场景三:根据设定的trigger周期,定期扫描在当日满足deadline条件的ticket;如果存在满足deadline条件的ticket,且ticket的状态不为accepted,则需要触发事先指定给该ticket的action。 场景四:无论是nomination,还是接收ticket、取消ticket,或者deadline以及取消执行的action,只要是对ticket进行了处理,都需要记录这次处理ticket的记录,以便于未来对该票的跟踪; 整个演练将完整介绍场景驱动设计的过程,并结合前面讲解的职责驱动设计与扩展式设计,确保优良的设计。案例会引入对领域建模的考量,识别职责、识别变化点并封装变化。设计会引入Strategy模式,Bridge模式、Repository模式、State模式以及Interceptor模式等,使设计满足可重用性、可扩展性。 4、卓越的软件设计 整个设计过程是由场景来驱动,通过角色识别职责,然后遵循高内聚原则对对象进行封装。合理的封装还必须保证对象之间的协作是松耦合。其中,可通过识别变化点,利用抽象对变化进行封装。卓越的软件设计还需要不断地演进,保证设计达到卓越的途径是识别坏味道,然后通过重构对代码进行改进;还可以运用探索式设计,对职责进行合理的分配。 (1)常见的坏味道:包括过长方法、过大的类、特性依恋、霰弹式修改、消息链、并行的继承体系、中间人等; (2)探索式方法:包括方法分组、观察隐藏方法、寻找可以更改的决定、寻找内部关系、寻找主要职责、草稿式重构与关注当前工作。 (3)卓越软件设计模型 |
第一单元: 面向对象设计: 角色、职责与协作 职责驱动设计 面向对象设计的核心驱动力是对象的职责,合理的职责分配是卓越软件设计的前提。只有合理地分辨对象的职责,才能够定义良好的对象,并实现符合系统一致性的对象协作关系。 1、职责的层次 通过职责层次模型对需求进行分析,识别出业务价值、业务功能与业务实现。职责层次的分解可以有效地帮助设计者辨别职责。 (1)职责层次的识别 (2)职责层次与软件架构层次之间的关系 (3)职责与概念、规约与实现 (4)案例分析:分析邮件服务器代码暴露的问题,在可重用性、代码可维护性、可扩展性等诸多方面着手,剖析代码坏味道。通过分辨职责层次,来改善设计。并提出需求变更,从而引入对Observer模式、Strategy模式、Simple Factory模式、Mediator模式与Chain Of Responsibility模式的对比与分析; (5)实战演练:设计一个作业调度框架,它能够根据指定的时间触发作业,执行自定义任务。 2、职责的分类 职责并不等于功能,也不等同于行为或方法。分析职责,应从对象的认知与行为入手。 3、对象的角色 角色、职责与协作是三位一体的关系,角色是发起职责的对象,职责则应该是对象之间的协作。不同角色的对象,履行的职责是不同的。 (1)信息持有者:信息的格式;是否需要持久化;信息源的改变,是否需要更新;处理信息的方式; (2)构造者:构造者与构造对象的关系;构造的方式;聚合与合成; (3)服务提供者:主动告知,被动告知;独立的行为;提供有业务价值的行为; (4)协调者:如何委派和转发请求;如何通知其他对象要做的工作;如何通知状态的变化; (5)控制者:控制者与被控制者的关系;控制的决策与逻辑;驱动其他对象;收集与决策有关的信息; (6)案例:处理HTTP请求与应答,体现信息持有者角色;JMS对Queue的创建体现构造者角色;税务报告的生成体现服务提供者角色;服务定位器体现协调者角色;内容验证器体现控制者角色; 4、职责与封装的关系 缺乏合理的封装,就会缺少正确的领域对象,从而导致领域信息散乱分布到系统各个方法,使得概念不够清晰,导致职责混乱。 5、模块级的职责分配 (1)问题分析:模块之间职责的分配,在面临三种问题时,应该如何应对?通过对具体问题的分析,讨论模块之间的职责分配,以及对高内聚、松耦合的理解。同时,该问题分析还将引入Template Method模式; (2)问题分析:错误的职责分配带来的循环依赖问题,以及对包的复用原则的违背,提出解决办法; (3)模块重用:对eBay模块的分析,以及对某大型系统架构的演进,提出模块重用的方式; 6、原则与模式 (1)单一职责原则:分析该原则的核心思想,关注对象的变化点; (2)案例分析:功能引擎中对功能对象的加载,如何体现职责分离带来的好处;通过对案例分析引入Proxy模式; (3)专家模式:专家模式的核心思想是信息的持有者是操作该信息的专家; (4)案例分析:报表参数的处理方式,如何通过识别设计违背了专家模式,并依据专家模式对设计进行改进,从而巧妙地利用多态消除代码坏味道,并进而通过引入Adapter模式处理模块之间的依赖关系; (5)自治对象:分析了自治对象的特征,分别包括:最小完备,稳定空间,自我履行与独立进化。 (6)案例分析:用户状态机,给出了某金融系统中复杂的用户状态迁移,体现的复杂授权、登录等业务逻辑,并由此引入State模式来简化设计,体现自治对象的特征。 |
第二单元 面向对象设计: 抽象与变化 扩展式设计 合理的职责分配并不能完全保证软件设计的卓越,因为需求变化是软件开发的常态,因此设计必须在一定程度满足变化,保证系统的可扩展性。 1、抽象的意义 抽象的关键在于寻找多个对象(或行为)具有的共同特征,并对特性进行泛化。泛化的特征可以暴露在外,从而隔离内部的实现。 (1)用例分析:对用例和参与者的泛化;遵循的原则; (2)案例分析:授权框架的设计,体现了对共同特征的提取,合理引入Chain Of Responsibility模式与Template Method模式; (3)案例分析:项目管理模型的抽象,通过对多种项目管理过程进行分析,对各种模型概念进行分类,并抽象出模型的共同特征,从而简化模型; 2、识别变化 要保证设计的可扩展性,主要过程是识别变化点,然后对变化进行封装。 (1)变化点:常见的变化点包括业务规则、算法策略、外部服务、硬件支持、命令请求、协议标准、数据格式、业务流程、系统配置、界面表现; (2)案例分析:电子商务系统的Invoice业务规则,引入Specification模式;CIMS系统的机器加载策略,引入Strategy模式;短信服务,引入Facade模式与Adapter模式;人力资源系统考勤模块,引入Gateway模式; (3)案例分析:CQRS框架,对命令处理逻辑的包装,引入Decorator模式,并通过分析变化点,引入另一种替代Decorator模式的设计。 3、依赖解耦 处理变化的关键是要解除对具体对象的依赖。 (1)表驱动法 (2)配置与反射 (3)IoC容器 (4)惯例优于配置 4、扩展式设计 扩展式设计分为三个步骤,分别为:分离职责各司其职,利用抽象统一接口,引用接口预留空白。扩展式设计可以有效地保证整个系统的可扩展性。 (1)扩展式设计的步骤 (2)实战演练:订单处理,通过三次迭代逐步改进原有设计,并分别遵循专家模式、分离原则与扩展式设计,保证设计在修改最小的前提下满足需求变化。在设计演进中,讨论对设计模式的合理运用,并引入Specification模式; (3)案例分析:配置管理框架的设计,该框架能够支持配置信息的多种存储形态,包括文件、数据库、LDAP等;支持多种获取配置的方式,如Web服务,REST服务。配置管理框架的接口需要保证其统一性和一致性,同时在满足可扩展要求下,提供接口的易用性。 (4)案例分析:消息队列规范的设计。通过分析JMS、MSMQ、RabbitMQ和NServiceBus的设计,理解抽象的含义,例如理解面向接口设计、接口隔离原则、按意图设计、Facade模式与企业集成模式。 (5)实战演练:CIMS基于消息的分布式架构。通过对服务的统一抽象,以及对消息处理的职责分配,建立一个协作合理的分布式架构。设计过程中会引入Command模式、Publisher – Subscriber模式、Message Bus模式、Message Translator模式、Lookup模式。 |
第三单元 场景驱动设计: 利用场景建模 设计过程 无论进行怎样的设计,都不能离开具体的场景。场景驱动设计的要义是基于场景有针对性地进行设计。场景既是设计的驱动力,又是设计的约束,从而获得恰如其分的设计。 1、场景的目标层次 (1)概要目标:系统层次的场景划分,每个概要目标可对应子系统的需求目标。通过概要目标引入领域驱动设计的Unbounded Context。 (2)用户目标:业务层次的场景划分,每个用户目标对应各个子系统所提供的业务价值,并以服务的形式暴露给调用者。 (3)子功能:功能层次的场景划分,每个子功能都对应于业务功能,并以领域对象或横切关注点的方式,由服务调用。 (4)案例分析:电子商务系统的场景目标划分,以层次模型的方式表现场景。 2、场景的6W模型 (1)6W的内容:分别为who(对应于角色)、why(对应于业务价值)、when(对应于对象的协作)、what(对应于业务功能)、where(对应于场景边界)和hoW(对应于业务实现); (2)6W模型的设计驱动力:6W模型的关键是在场景边界内,通过场景识别出角色,再以角色为设计入口,运用职责的层次模型识别出业务价值、业务功能和业务实现,从而根据职责模型获得领域模型,再通过时序图,处理对象之间的协作关系,进一步精炼出更为准确的领域模型。 3、场景驱动设计演练 (1)实战案例:某大型跨国公司的内部培训系统,包括培训计划制订,培训实施以及员工职业生涯规划等功能; (2)对整个系统进行分析,识别场景的目标层次; (3)划分需求场景,运用6W模型进行场景驱动设计; 场景一:将培训的Ticket分配给员工。在分配ticket时,需要指定deadline,以及取消票或deadline到期时的Action。同时,将该ticket的状态设置为pending; 场景二:在接收到分配ticket的通知后,并在设定的deadline之前,拒绝该ticket。此时,会自动执行事先分配给ticket的取消票的action; 场景三:根据设定的trigger周期,定期扫描在当日满足deadline条件的ticket;如果存在满足deadline条件的ticket,且ticket的状态不为accepted,则需要触发事先指定给该ticket的action。 场景四:无论是nomination,还是接收ticket、取消ticket,或者deadline以及取消执行的action,只要是对ticket进行了处理,都需要记录这次处理ticket的记录,以便于未来对该票的跟踪; 整个演练将完整介绍场景驱动设计的过程,并结合前面讲解的职责驱动设计与扩展式设计,确保优良的设计。案例会引入对领域建模的考量,识别职责、识别变化点并封装变化。设计会引入Strategy模式,Bridge模式、Repository模式、State模式以及Interceptor模式等,使设计满足可重用性、可扩展性。 4、卓越的软件设计 整个设计过程是由场景来驱动,通过角色识别职责,然后遵循高内聚原则对对象进行封装。合理的封装还必须保证对象之间的协作是松耦合。其中,可通过识别变化点,利用抽象对变化进行封装。卓越的软件设计还需要不断地演进,保证设计达到卓越的途径是识别坏味道,然后通过重构对代码进行改进;还可以运用探索式设计,对职责进行合理的分配。 (1)常见的坏味道:包括过长方法、过大的类、特性依恋、霰弹式修改、消息链、并行的继承体系、中间人等; (2)探索式方法:包括方法分组、观察隐藏方法、寻找可以更改的决定、寻找内部关系、寻找主要职责、草稿式重构与关注当前工作。 (3)卓越软件设计模型 |