面向方面的软件开发方法 CSAI华东区首席顾问 徐 锋
Agenda 面向对象开发技术与开发范型变迁 横切关注点 横切关注点的建模与分离 弹性体系结构演变 AOSD的应用
Code-Fix模型 --最原始的开发方式 程序越来越大,难以掌握—软件危机 结构化开发:SA、SD、SP --自顶向下,逐层分解 软件开发范型的变迁 Code-Fix模型 --最原始的开发方式 程序越来越大,难以掌握—软件危机 结构化开发:SA、SD、SP --自顶向下,逐层分解 数据与方法分离,内聚性不够—与现实世界模型不一致 面向对象开发:OOA、OOD、OOP –现实世界真实反映 其它:数据流理论 1970 1980 1990 结构化方法 数据流方法 面向对象
面向对象开发技术的核心特点 结构化理论:将应用分解为功能模块、子功能模块、功能接口;与现实问题域的东西没有直接联系! 面向对象理论:系统模型是对问题域的直接映射,即从现实世界中直接抽象出一个模型,然后在计算机中实现出来。
而面向对象分析、设计方法才是OO思想的真正标志。 面向对象开发技术的历史变迁 年 1980 1960 1970 1990 Lisp Simula67 SmallTalk72 SmallTalk80 C Objective-C C++ Java 面向对象程序语言 1970年 面向对象编程开启了面向对象发展之门。 而面向对象分析、设计方法才是OO思想的真正标志。 面向对象程序设计 面向对象设计 面向对象分析 1990年
需要支持多平台:SOA、ESB—连接组件 面向对象开发技术的今天—核心基础 核心基础:组件技术、UML建模技术 组件技术:大型项目与系统的必由之路 需要支持多平台:SOA、ESB—连接组件 拥有大量组件:重用、MDA—快速、廉价集成组件 响应日益复杂的业务操作:EA(连通软件与业务的鸿沟)、PLE(处理产品线可变性)、反向工程(重用遗留系统) 框架:J2EE、.NET等 独立与厂商的组件描述语言--UML
显然仅有组件和UML是不够的,因为我们还需要知道如何捕获组件!--答案就是最佳实践: 面向对象开发技术的今天—最佳实践 显然仅有组件和UML是不够的,因为我们还需要知道如何捕获组件!--答案就是最佳实践: 迭代开发 体系结构为中心 用例驱动
最佳实践1—迭代开发
最佳实践2—用例驱动
最佳实践3—体系结构为中心
Agenda 面向对象开发技术与开发范型变迁 横切关注点 横切关注点的建模与分离 弹性体系结构演变 AOSD的应用
嗯,一切似乎很完美。是什么打破了这一宁静? 横切关注点是打乱这一规则的“破坏分子”! 横切关注点包括两类: 横切关注点1—扩展 嗯,一切似乎很完美。是什么打破了这一宁静? 横切关注点是打乱这一规则的“破坏分子”! 横切关注点包括两类: 扩展:在基组件之上定义的组件,它用来表示附加的服务或功能 非功能属性 --AOP原先的发现 对等关注点:相互独立的功能点,各组件中参与类有较大的交叠 缠绕与分散 --Ivar博士的补充发现 弥补用例分析与实现的鸿沟
横切关注点1—扩展 AOP就是基于对非功能属性实现中发现的“重复”。 例如:留存、事务处理、安全、 性能优化、错误处理、日志、 调试、度量等。
横切关注点2—对等关注点 各个组件包含满足不同关注点的实现—缠绕状态 某个特定的关注点的实现分散在多个组件中—分散状态
横切关注点现行实行的不足 横切关注点1—扩展 代码的大量重复,涉及到多个功能性类 横切关注点2—对等功能点 当横切关注点的需求发生变化时,会造成大量修改 横切关注点的更新难以实现一致性 横切关注点2—对等功能点 捕获对等功能点的用例本身就涉及了多个类,容易使分析与设计的结果不能够有效地对应起来,影响了跟踪 功能的修改,可能涉及多 个类,从而影响系统的弹性 原有的用例建模在管理横 切关注点时存在问题
可以实现将类之外的附加行为合并到类本身 面向方面技术 本质:合成机制,分离横切关注点的方法 可以实现将类之外的附加行为合并到类本身 可以在编译时或运行时进行 可以将不同的关注点的实现分离到不同模块中 核心概念 aspect:核心类元,模块化单元 intertype:aspect的方法,定义为“原有类名.新操作名” --类扩展 pointcut:在aspect中说明原有类中的扩展点(连接点) --操作扩展 advice:捕获pointcut出现的特定事件 --操作扩展
Agenda 面向对象开发技术与开发范型变迁 横切关注点 横切关注点的建模与分离 弹性体系结构演变 AOSD的应用
基于用例对横切关注点建模 用例是对横切关注点建模的最好工具 用例描述的关键是事件流 用例扩展: pointcut
基于用例对横切关注点建模 用例包含: 用例泛化:
基于用例捕获横切关注点 应用(application)用例和基础结构(infrastructure)用例 理解涉众关注点 理解问题域(领域类,领域模型) 抽取系统特性(Feature List) 处理功能和非功能需求(应用用例、基础结构用例) 捕获应用用例 从特性中识别出参与者,合并为用例 识别用例变量,并处理用例变量 处理扩展用例 捕获基础结构用例 抽象为<执行事务>用例对基本事务进行建模 基础结构用例的结构化、描述基础结构用例 处理系统范围的关注点
用例切片 用例的实现是协作 : 协作标识了类及类的扩展 用例切片包括:协作 (交互图、类图)、特定的类、特定的扩展
基于用例切片实现分离 合并特定于某用例的类 : 合并用例特定的类扩展:
基于用例切片组成系统 通过用例切片(use case slice)和非特定用例切片(non-uc-specific slice)来叠加出系统:
用例模块 对于某个用例而言,都包括不同的模型(用例描述、分析、设计、实现、测试设计、测试实现),每个模型都可以组成一个切片,而将这些切片放在一个单独的包中,就称为用例模块
Agenda 面向对象开发技术与开发范型变迁 横切关注点 横切关注点的建模与分离 弹性体系结构演变 AOSD的应用
架构(Architecture) 什么是架构(体系结构)? 系统元素如何组织? 什么是好的架构 分离功能需求 系统如何实现所需功能? 系统如何满足预期性能、可靠性和其它质量特性 系统需要什么技术? 系统内部组织的结构是否能够弹性响应功能、技术、平台变化? 标准是否能够确保系统开发始终保持一致?采用什么设计模式? 什么是好的架构 分离功能需求 从功能需求中分离出非功能需求 分离平台特性 将测试从已测单元中分离出来
架构基线 架构基线:最终系统的早期版本,Skinny System! 用例驱动架构基线:寻找出关键用例子集 迭代地建立架构基线 包含了最终系统所具有的子系统、组件和节点的骨架 UP过程中,这一任务主要是在精化阶段完成 用例驱动架构基线:寻找出关键用例子集 演练了系统的关键功能和特性 涵盖了大部分的功能性、基础结构、平台特性等方面的风险 突出了系统中的一些具有高复杂度或高风险性的部分 是系统剩余系统的基础 迭代地建立架构基线
平台无关的结构(PIM) 元素结构:基于包和类的分层结构 用例结构:在元素结构的基础上添加了实际的内容 组成部分主要是领域相关的类 通常包括“应用层”和“领域层” 应用层的元素主要实现用中支持系统的主要参与者的工作流 领域层则要包括了描述重要领域概念的元素 用例结构:在元素结构的基础上添加了实际的内容
叠加平台相关特性(PSM) 选择平台 最小化用例设计(minimal use-case design) 系统的平台特性基于架构师选定的部署结构和进程结构 我们需要将平台特性与平台无关的部分分离—最小化用例设计 最小化用例设计(minimal use-case design) 可执行,并采用默认编程语言实现 是通过程序接口来激活的 分布性、内部进程的通信和平台相关消息通信都与其分离 所需的信息都在内存中
使功能需求保持分离 1 分离功能需求的最好办法是用例(应用用例) 应用用例的分析 使功能需求在分析模型中保持独立 什么是特定于某用例的、什么是独立于用例的,什么是特定于某应用的、什么是应用通用的 ,什么是领域通用的、什么是领域特定的。 这些问题的答案用于指导:如何将类归入到层、包,如果将类扩展归入到相应的切片、模型中 应用用例的分析 考虑用例规约,必要时进行更新 分析用例:识别出参与用例实现的分析类,并将行为分配给这些类 在系统元素结构中将类组织成为层和包,在用例结构中将类和类扩展组织成切片 将分析元素映射为设计元素、识别出接口及附加的设计元素 使功能需求在分析模型中保持独立 根据类参与实现的用例,形成合适的元素结构 将用例结构分为:针对某个特定用例行为的“用例切片”,不属于特定的某个用例的“非用例特定切片”
使功能需求保持分离 2 应用用例设计 使功能需求在设计模型中保持独立 识别设计元素:从分析模型中标识设计元素,根据实现需要引入新的设计元素 识别组件和接口:将分析为中的一部分演化为设计组件 完善设计元素 使功能需求在设计模型中保持独立 使类扩展保持分离:ReserveRoom类需要updateAvailability()和retrieveDetails()两个方法。前者是“预订房间”特用,后者是公用。其处理方法有四种: 现行选择 编程困难
使功能需求保持分离 3 使功能需求在设计模型中保持独立 使操作扩展保持独立 1)总和:两个用例切片需要从相同操作得到不同的输出,并且操作的职责是提供两种输出的合并 2)选择:当用例切片需要从同一个操作得到不同的输出,并且要求组合结果只有一种输出 操作扩展声明包括 1)结构上下文:说明哪个操作是要增加的 2)行为上下文:说明扩展何时执行 3)说明附加行为
使扩展的功能需求保持分离 1 面向方面技术能够使我们更好地在原有系统上进行扩展 识别类: 该扩展流程应该在pointcut UpdatingRoomAvailability返回没有空闲房时 系统建立一个针对选定房间类型的带唯一标识符的待处理订单,然后将其放到等候列表中,再将此唯一标识符返回给客户,用例结束。 识别类:
使扩展的功能需求保持分离 2 识别Pointcut,并将用例行为分配给类 标识结构上下文:确定在何处运行这些操作扩展来调用扩展用例 标识行为上下文:定义职责中的何处需要调用
使扩展的功能需求保持分离 3 因此,得到了一个独立的用例切片完成该扩展用例
使非功能需求保持分离 1 分离非功能需求最有效的工具是基础结构应用 识别类 标识Pointcut 将用例行为分配给类
使非功能需求保持分离 2 使基础结构用例保持分离 细化元素结构 在用例切片中使基础结构保持分离
使平台特性保持分离 最小设计视角 合并了平台特性
Agenda 面向对象开发技术与开发范型变迁 横切关注点 横切关注点的建模与分离 弹性体系结构演变 AOSD的应用
保持关注点分离带来的生产率提高 假设某系统有N个独立的需求,假设每个的工作量需X,则总工作量就是NX 若N个需求未良好分离,就意味着每个需求的实现与其它需求的实现相互交迭,最坏时可能是每个需求的实现与N-1个需求相关,如果交迭部分的开发量是Y,则任务量就成了NX+N(N-1)Y 假设N=20,X=20,Y=1,良好分离时工作量为400,未良好分离时显然就是780,接近一倍。 随着Y值的增加,未良好分离的 体系结构就会带来越大的成本。
从何处入手 用例建模与分析:对涉众关注点捕获的正确性和精确性是十分重要的。用例建模与分析适用于任何软件开发,不管是面向方面、面向对象还是其它的。建议针对基础结构服务编写用例。建议多练习,编写出客户和开发团队都易于理解的有效用例。 设计和实现:用例切片、用例结构、AOP都比较新,需要学习如何对aspect和用例切片进行建模,如何描述Pointcut。建议选择一个适用该方法解决的特定关注点。通过用例来描述它,并从此驱动到编码、测试的全过程。 测试:基于用例切片,可以很轻松地 将测试引入的控制和工具代码轻松地 去除。
在项目的不同阶段采用 计划阶段:很容易着手,从需求开始,从头贯穿AOSD; 细化阶段前期:已经完成了一部分迭代,有一些可以工作的用例和几个基础结构服务,则可以在没有开发的部分上应用用例切片,对已开发的基础结构服务可以考虑重新设计用例切片是否有价值; 细化阶段后期:如果已有一个可靠的架构,基本上不建议做修订和改变。但可以考虑用参数化pointcut来帮助你把基础结构服务和平台特性融合到系统中。还可以使用AspectJ来判断层和包之间是否存在依赖注入。 构建阶段:如果项目接近尾声,不必有太大改变,可以考虑会该方法进行测试。 完善阶段:可以用来对原系统更好的进行扩展。
Q&A 徐 锋 xf@csai.cn 谢谢各位!