GRASP:设计带职责的对象 徐迎晓 xuyingxiao@126.com 复旦大学软件学院.

Slides:



Advertisements
Similar presentations
胸痛中心的时间流程管理 上海胸科医院 方唯一.
Advertisements

<<會計資訊系統課程講義>> 統一塑模語言(UML)語法精要 -- 物件導向概念、需求分析及系統分析
Ch02物件導向程式設計 物件導向系統分析與設計.
Java Programming Hygiene - for DIDC
資料庫設計 Database Design.
雅思大作文的结构 Presented by: 总统秘书王富贵.
Oracle数据库 Oracle 子程序.
第9章 面向对象方法学引论 9.1 面向对象方法学概述 9.2 面向对象的概念 9.3 面向对象建模 9.4 对象模型 9.5 动态模型
第八章 分析與設計階段 – 物件導向設計(OOD)
全国计算机等级考试 二级基础知识 第二章 程序设计基础.
云实践引导产业升级 沈寓实 博士 教授 MBA 中国云体系产业创新战略联盟秘书长 微软云计算中国区总监 WinHEC 2015
Homework 4 an innovative design process model TEAM 7
Unit 4 I used to be afraid of the dark.
Group multicast fanOut Procedure
Thinking of Instrumentation Survivability Under Severe Accident
Excellence in Manufacturing 卓 越 制 造
形式语言与网络 计算环境构建 1.
Chapter 1 OBJECT-ORIENTED ANALYSIS AND DESIGN
Basis基本操作、使用者 管理與權限設定
Chapter 3 Case Studies.
第 1 章 ERP的演变.
軟體工程 -物件導向程式設計與UML系統分析實作
單元3:軟體設計 3-2 順序圖(Sequence Diagrams)
面向对象建模技术 软件工程系 林 琳.
Logistics 物流 昭安國際物流園區 總經理 曾玉勤.
Retail Customer Online Registration 零售顧客線上註冊教學
第4章(2) 空间数据库 —关系数据库 北京建筑工程学院 王文宇.
创建型设计模式.
製程能力分析 何正斌 教授 國立屏東科技大學工業管理學系.
第9章 類別圖與物件圖 9-1 類別圖與物件圖的基礎 9-2 類別圖的符號 9-3 類別關係 9-4 物件圖 9-5 繪製類別圖與物件圖
辅导课程六.
SAP 架構及基本操作 SAP前端軟體安裝與登入 Logical View of the SAP System SAP登入 IDES
Corporate Finance Ross  Westerfield  Jaffe
子博弈完美Nash均衡 我们知道,一个博弈可以有多于一个的Nash均衡。在某些情况下,我们可以按照“子博弈完美”的要求,把不符合这个要求的均衡去掉。 扩展型博弈G的一部分g叫做一个子博弈,如果g包含某个节点和它所有的后继点,并且一个G的信息集或者和g不相交,或者整个含于g。 一个Nash均衡称为子博弈完美的,如果它在每.
软件工程 Software Engineering
校園網路架構介紹與資源利用 主講人:趙志宏 圖書資訊館網路通訊組.
增强型MR可解决 临床放射成像的 多供应商互操作性问题
客户服务 询盘惯例.
第4章(1) 空间数据库 —数据库理论基础 北京建筑工程学院 王文宇.
Advanced Basic Key Terms Dependency Actor Generation association
两种不同类别的软件: 功能预定义软件;用户驱动的软件。他们对软件工程方法有不同的需求
Unit 11.Operating System 11.1 What’s OS 11.2 Related Courses
高性能计算与天文技术联合实验室 智能与计算学部 天津大学
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
Guide to a successful PowerPoint design – simple is best
高正宗 System Consultant Manager
SAP FI Module Account Payable Version:2.0版本 Date:2001/10/01 制作: 胡 敏.
BORROWING SUBTRACTION WITHIN 20
中国科学技术大学计算机系 陈香兰 2013Fall 第七讲 存储器管理 中国科学技术大学计算机系 陈香兰 2013Fall.
虚 拟 仪 器 virtual instrument
VisComposer 2019/4/17.
從 ER 到 Logical Schema ──兼談Schema Integration
Aspect Oriented Programming
徐迎晓 复旦大学软件学院 实现模型 徐迎晓 复旦大学软件学院.
The viewpoint (culture) [观点(文化)]
iSIGHT 基本培训 使用 Excel的栅栏问题
回顾.
Chapter 10 Mobile IP TCP/IP Protocol Suite
SAP 架構及基本操作 SAP前端軟體安裝與登入 Logical View of the SAP System SAP登入 IDES
Chapter 18 使用GRASP的对象设计示例.
Create and Use the Authorization Objects in ABAP
MODELING GENERALIZATION & REFINING THE DOMAIN MODEL
Delphi 7.0开发示例.
Resources Planning for Applied Research
Advanced Basic Key Terms Dependency Generalization Actor Stereotype
怎樣把同一評估 給與在不同班級的學生 How to administer the Same assessment to students from Different classes and groups.
OOA/OOD UML RUP Architecture Pattern MDA
國際會計準則(IFRS)推動現況及因應之道
徐迎晓 复旦大学软件学院 用例模型--用操作合约添加细节 徐迎晓 复旦大学软件学院.
MGT 213 System Management Server的昨天,今天和明天
Presentation transcript:

GRASP:设计带职责的对象 徐迎晓 xuyingxiao@126.com 复旦大学软件学院

设计带职责的对象 交互设计和职责分配的质量决定系统的质量 好的面向对象设计原则可用于交互图设计和职责分配—GRASP模式 可维护性 可理解性 可重用性 可扩展性 好的面向对象设计原则可用于交互图设计和职责分配—GRASP模式

GRASP:通用职责分配软件模式 将职责分配给对象的基本原则 General Responsibility Assignment Software Patterns 将职责分配给对象的基本原则

GRASP:设计带职责的对象 五个GRASP模式 应用GRASP实现Process Sale用例 可见性设计 类图设计

五个GRASP模式 . Low Coupling . High Cohesion . Controller . Creator . Information Expert

模式: Low Coupling Problem:如何降低依赖、减少改变的影响,增加重用性? Solution:分配职责时使耦合低

原理: 高耦合带来的问题 耦合表明两个类之间连接的强度,一个类是否依靠其他类 A具有低耦合,则A不依赖很多其他的类 其他类改变则可能自己也必须改变 单独(无其他类时)难以理解 由于需要很多其他类,难以重用

举例 we have a need to create a Payment instance and associate it with the Sale. 谁来创建Payment 实例?

两种都假定Sale和Payment之间有关联,register创建则增加关联,不好

讨论 低藕合模式常与专家、高内聚一起使用 是基本目标,所有设计决策中都要考虑 中等层度的藕合是正常和必需的(对象之间需要连接以便协作) 优点:不受其他组件变化的影响,易于理解,易于重用

类X和类Y之间常见的藕合 X有属性引用Y的实例 X对象调用Y对象的服务 X的方法引用Y的实例(参数,局部变量,返回值) X是Y直接或间接子类

But 对稳定元素的藕合和普遍的元素藕合很少会有问题 如类库

五个GRASP模式 . Low Coupling . High Cohesion . Controller . Creator . Information Expert

模式:Hign Cohesion Problem:如何使复杂性可管理? Solution:分配职责时使内聚度高

内聚:类的职责如何紧密关联 类或子系统等若职责紧密关联,且没有大量的工作,则具有高内聚度 高内聚则方法的数量相对较少 若task is large,则与其他对象协作 低内聚说明类做了很多无关的事情,或做了太多的事情 低内聚的问题:难以理解,重用,维护,易受变化的影响 修改:在进行测试和发布时,类通常是最基本的单元,如果其粒度太粗,在一个类中设计了大量的操作,则会有大量使用者使用该类的不同操作,但为了某一类使用者修改了某几个操作时,整个类就要重新发布,并有可能会影响到使用另几个操作的另一类使用者。 查找:此外,如果类中操作太多,类的使用者要从一长串操作中挑选自己所需要的也是很吃力的

不独立使用,而是与专家、低藕合模式一起使用 评估所有设计决策的一个准则 Register做很多系统操作,下图哪个好?

RDB-RPC-Interface class responsible for interacting with relational databases and for handling remote procedure calls (two vastly different functional areas) 几个不同内聚度的例子 --Very low cohesion 一个类独自负责不同功能区域的很多事情A class is solely responsible for many things in very different functional areas

RDBInterface class completely responsible for interacting with relational databases. hundreds or thousands of methods(all related) A lot of supporting code Low cohesion A class has sole responsibility for a complex task in one functional area.

RDBInterface class Only partially responsible for interacting with relational databases interacts with a dozen other classes related to RDB access High cohesion 一个功能区域,职责中等(与其他类协作完成任务)A class has moderate responsibilities in one functional area and collaborates with other classes to fulfill tasks.

Company class completely responsible for (a) knowing its employees and (b) knowing its financial information. total number of public methods is small the amount of supporting code is small Moderate cohesion (类具有轻量级的、独立的职责,职责覆盖几个不同的功能区域,职责相互之间的关系不大,但都与类的概念逻辑相关) A class has lightweight and sole responsibilities in a few different areas that are logically related to the class concept, but not to each other

可低内聚的场合 grouping of responsibilities or code into one class or component to simplify maintenance by one person 只有1,2个SQL专家,对OO不熟 software architect may decide to group all the SQL statements into one class, RDBOperations

可低内聚的场合2 distributed server objects less remote calls, and better performance. 远程服务器对象要fewer and larger, less cohesive,为很多操作提供接口 远程操作粗粒度,以便一次remote operation call可以做或请求更多的工作 Example 1: remote object with three fine-grained operations setName, setSalary, and setHireDate Example 2: one remote operation setData which receives a set of data Which is better? Solution 2 better ------------- create fewer and larger, less cohesive server objects that provide an interface for many operations remote operations are made more coarse-grained in order to do or request more work in remote operation call

五个GRASP模式 . Low Coupling . High Cohesion . Controller . Creator . Information Expert

模式:Controller Problem:谁负责处理系统输入事件? Solution:将处理系统输入事件的职责分配给代表以下的类: 代表整个系统、设备或子系统-外观Controller(facade controller) 代表整个业务过程或组织(facade controller) 代表现实世界中可能执行该任务的角色(role controller) 代表系统事件发生的用例场景,(use-case or session controller)

Problem: Solution (advice): The UI & domain layers should be loosely coupled Which object should coordinate msgs between the UI and other domain objects? Solution (advice): Assign responsibility to an object representing.. The ‘system’ or a ‘root’ object (Store, Bank) A device/subsystem (AccountingSystem, BankATM) A use case scenario (GameHandler) ‘Single channel of communication between layers’

“window,” “applet,” “widget,” “view,” and “document”不是控制器,而是将事件发往控制器 系统操作在设计时通常交给控制器

Controller是从界面层进入doamin layer的门面

可供选择的 代表整个系统、设备或子系统 代表整个业务过程或组织 代表现实世界中可能执行该任务的角色 代表系统事件发生的用例场景 Register, POSSystem 代表整个业务过程或组织 Store 代表现实世界中可能执行该任务的角色 Cashier 代表系统事件发生的用例场景 ProcessSaleHandler

对应前面四种

整个系统、设备或子系统

系统事件发生的用例场景

讨论 大多数系统接受外部输入事件(GUI,传感器信号,…) 一个用例中所有系统事件用一个控制器处理,不同用例用不同控制器 控制器通常将将需要做的工作委托给其他对象,自己并不做很多工作

优点 但要防止控制器过于臃肿 业务处理由业务对象完成,而不是把图形界面作为控制器,这样可重用性高 将控制器的职责委托给各个领域类,支持逻辑重用 但要防止控制器过于臃肿 可用多个控制器 可用角色控制器或用例控制器,而不是facade controller

图形界面

不好的做法

五个GRASP模式 . Low Coupling . High Cohesion . Controller . Creator . Information Expert

模式:Creator Problem:谁负责创建新的对象? Solution: 如果满足以下条件之一,则将创建类A的实例的职责分配给类B B聚合A对象 B包含A对象 B contains A objects. B记录A对象(前三个最常用) B紧密使用A对象 B具有创建A对象时需要传入的初始化数据 B是A的Creator 如果有多个类满足条件,优先选择聚合或包含关系 Aggregate aggregates Part, Container contains Content, and Recorder records Recorded

Name: Creator Problem: Who creates an A? Solution: (this can be viewed as advice) Assign class B the responsibility to create an instance of class A if one of these is true (the more the better): B "contains" or compositely aggregates A. B records A. B closely uses A. B has the initializing data for A.

举例 谁负责创建SalesLineltem对象? 应该Sales LineItem

讨论 低耦合 简明,封装 But 若出于性能考虑使用回收的实例,或根据外部的值从一组类似的类中挑选一个创建实例 对依赖的维护少 可重用性高 建议将创建工作交给helper class----Factory,而不使用本模式

五个GRASP模式 . Low Coupling . High Cohesion . Controller . Creator . Information Expert

模式:Information Expert Problem OOD中分配职责最基本的原则是什么? Solution将职责分配给Information Expert (拥有完成该职责所需要信息的类)

1.如果设计模型存在相关的类,则到领域模型中查找 2. 否则,查看领域模型,应用或扩展领域模型得到相应的设计类

画交互图时碰到的问题:计算总价(总计,grand total)的职责分配给谁? 检查领域模型或设计模型

计算总价需要知道所有销售条目(SalesLineltem)及其各个条目的总价(subtotals)之和 Sale包含SalesLineltem这些信息——所以计算总价(grand total)的职责分配给Sale。 SalesLineItem 子销售

此时对交互图和类图可以增加哪些内容?

各个条目的总价(subtotals.)分配给谁? 需要知道数量SalesLineltem.quantity和单价ProductSpecification.price  分配给SalesLineltem

交互图和类图增加什么内容?

获取单价的职责分配给谁?  ProductSpecification包含该信息

最终通过Information Expert模式得到的职责分配 为了能得到总价的信息:

最终通过Information Expert模式得到的协作图

讨论模式Information Expert 来自直觉--对象做的事情总是与其拥有的信息有关 常需要多个对象协作 But 影响耦合和内聚时,可能不使用Expert 将销售保存的数据库的职责分配给谁?

优点 低耦合--对象用自己的信息,封装性好 高内聚-行为分布在具有所需信息的类上,易于理解和维护

GRASP:设计带职责的对象 五个GRASP模式 应用GRASP实现Process Sale用例 可见性设计 类图设计

应用GRASP实现Process Sale 用例 用例实现是UP设计模型的一部分 建议并行画类图和交互图 初始阶段:设计模型和用例实现通常不做,因为涉及详细的设计决策,而初始阶段尚不成熟 细化阶段:创建体系结构上重要的或风险较大的用例实现 构造阶段:为剩下的设计问题创建用例实现

先为每个系统操作创建独立的图,将每个系统事件作为起始消息 若图太复杂,分解成小的图 使用系统操作合约和用例描述作为起点,使用GRASP等模式 可以直接从UC文本设计用例实现,但对某些系统操作,合约可以提供更多的细节和描述 如果我们以前跳过Contract的创建,仍旧可以通过用例文本创建交互图,但合约将相关信息以workable format组织和隔离出来,并且可鼓励在分析阶段进行这方面研究工作

Controller 协作图:每个系统事件要画一个

顺序图:可在一张图上

太长的也可每个系统事件 分开

makeNewSale

通过应用GRASP控制器模式,交互图以向Register软件对象发送makeNewSale消息开始 1.选择控制器类 This Register is a software object in the Design Model. not a real physical register is a software abstraction It’s name was chosen to lower the representational gap between our concept of the domain and the software

Fig. 18.6

enterItem UC 3. Cashier enters item identifier. 后面:选择控制器,显示Item Description和Price, 创建SalesLineItem,查找ProductSpecification, 从数据库获取ProductSpecification,多对象 UC 3. Cashier enters item identifier. 4. System records sale line item and presents item description, price, and running total.

选择控制器,显示Item Description和Price, 创建SalesLineItem,查找ProductSpecification, 从数据库获取ProductSpecification,多对象 1. 选择控制器 2. 显示ItemDescription and price(ignored, Model/View分离)---domain object不需要和图形界面通信 3. 创建SaleLineItem 4. enterItem从界面中得到的参数是id和qty,而 向sale发消息创建SalesLineItem时,SalesItem中保存的是spec和qty(SalesItem需要和spec关联),所以需要给定id得到spec.下下页: 5.从数据库获取ProductSpecification(信息提取延迟到以后设计) 6. 发往多对象的消息默认的解释是发向容器中的每个对象, 但对于find, add等明显的操作解释为对容器的操作

给定id得到spec,Product Catalog保存了所有id和description对应关系 信息专家-分配给Product Catalog

谁向ProductCatalog发送消息要ProductSpecification? 假设Register和ProductCatalog实例在UC启动时创建,二者之间存在永久connection,则可以由Register发送,见该图 ---这引入另一个概念:Visibility,A向B发送消息,A必须可见B

Fig. 18.7

endSale Cashier repeats steps 3-4 until indicates done. 指示重复 Cashier按下按钮指示结束Sale时发生 1.选择控制器 2. 设置Sale.isComplete属性 3. 显示信息 4. 计算Total Cashier repeats steps 3-4 until indicates done. 指示重复 5. System presents total with taxes calculated.

endSale 1.选择控制器 2. 设置Sale.isComplete属性---专家

Fig. 18.9

3. 显示信息---模型视图分离 4. 计算Total

{}中为getSubtotal()实现的半形式化描述,aSLI并未正式定义,但开发者可以理解是一个SaleLineItem实例

Fig. 18.11 & 18.12

makePayment 后面:选择控制器,创建Payment,记录已完成的Sale,计算余额 2004.12.5 8. System logs completed sale and sends sale and payment information to the external Accounting system and Inventory system

Make Payment: Creating the Payment 选择控制器,创建Payment * , 记录已完成的Sale,计算余额

CashTendered实际支付 Fig. 18.13

Make Payment: Logging a Completed Sale Who is responsible for knowing all the logged sales, and doing the logging? 选择控制器,创建Payment , 记录已完成的Sale*,计算余额

====需求指出Sale应该放在historical log中 从减少representational gap角度,Store知道所有logged sales是合理的.早期Store职责很少时可这么做 但when the design grows and the Store becomes uncohesive.低内聚,则可以交给SalesLedger(账簿) ------ the contract indicate relating the Sale to the Store. This is an example where the postconditions may not be what we want to actually achieve in the design. 领域模型也可跟着进化 ====E======= the requirements state that the sale should be placed in an historical log By the goal of low representational gap in the software design, it is reasonable for a Store to know all the logged sales

这里仍旧先由Store创建

Fig. 18.15

makePayment: Calculating the Balance The Process Sale use case implies that the balance due from a payment be printed on a receipt and displayed somehow. 选择控制器,创建Payment , 记录已完成的Sale,计算余额*

7a. Paying by cash: 1 收银员输入收取的现金数额 2 系统给出应找的余额,并弹出现金抽屉 3 收银员放入收取的现金,并拿出应找的余额给顾客 4 系统记录现金支付 1. Cashier enters the cash amount tendered. 2. System presents the balance due, and releases the cash drawer. 3. Cashier deposits cash tendered and returns balance in cash to Customer. 4. System records the cash payment.

Model-View Separation principle, we should not concern ourselves with how the balance will be displayed or printed

首先考虑信息专家,除非是创建者或控制器问题 计算找零,需要知道Sale总金额和payment中现金付款金额(cash tendered) -- Sale and Payment, 若Payment作为信息专家,则payment需要可见Sale,增加了耦合 Object Constraint Language (OCL).

Fig. 18.16

startUp 大部分系统都有startUp用例,startUp系统操作最早执行,但在考虑过其他系统操作后才开发。——最后做初始化设计 应用程序如何启动并初始化,依赖于语言和操作系统 常见的设计方法是创建initial domain object——the first software "domain" object created. 负责创建direct child domain objects. Store若作为initial domain object,则负责创建Register 何处创建初始领域对象?——Java main() 方法,也可由factory对象做 The initial domain object does not usually take control if there is a GUI; otherwise, it often does.

StartUp的开始 创建初始领域对象——create消息 初始领域对象若控制进程,再画一个交互图发送run或类似消息给初始领域对象

control will remain in the UI layer (such The startUp system operation occurs when a manager powers on the POS system and the software loads. control will remain in the UI layer (such as a Java JFrame) after the initial domain object is created. The initial domain object does not usually take control if there is a GUI; otherwise, it often does.

Choosing the Initial Domain Object 初始领域对象的选择:选靠近聚合或容器层次结构的根的类来创建领域对象 1. façade controller 如Register 2. 基本上包含了所有其他对象的对象,如Store 根据对耦合和内聚的影响,考虑用Register还是Store,这里选择Store

StartUp启动时对数据库的操作 ProductSpecification实例存储在存储介质如关系数据库或对象数据库中 StartUp时, 若很多,消耗内存和时间太多,可在需要时才装载 对象数据库易于动态将对象装载到内存,关系数据库可留到后面设计

StartUp创建其他哪些对象 考虑初始领域对象中要创建哪些对象,加哪些关联 根据以前设计工作(如EnterItem的设计)的需要来定

1.1是临时的,最终的设计中当需要ProductSpecification时才从数据库中生成 现实世界和软件世界的差别:当前需求中 软件世界中Store只需要创建一个Register

Fig. 18.20

常见设计:Main中创建一个UI对象和领域对象,并将领域对象传递给UI(如上) UI得到领域对象(Register)后就可以向其发送系统事件消息

设计1:将getTotal()放在Register中,UI和领域层低耦合,但Register内聚度低

UI需要知道任何与Sale相关的信息时,请求一个当前Sale对象的引用,直接向其发送消息

用例实现和UP 用例实现是UP设计模型的一部分 建议并行画类图和交互图 初始阶段:设计模型和用例实现通常不做,因为涉及详细的设计决策,而初始阶段尚不成熟 细化阶段:创建体系结构上重要的或风险较大的用例实现 构造阶段:为剩下的设计问题创建用例实现 MSE 2005.5.30 here

GRASP:设计带职责的对象 五个GRASP模式 应用GRASP实现Process Sale用例 可见性设计 类图设计

可见性设计 基本判断: 若对象A向对象B发消息,则B必须对A是可见的

四种可见方式 Attribute visibility– B是A的属性 Parameter visibility—B是A的方法的参数 Local visibility—B是A的局部对象(非方法的参数). • Global visibility—B是以某种方式全局可见的

属性可见 相对永久,最常见 public class Register { … private ProductCatalog catalog; }

属性可见

参数可见 Sale的方法makeLineItem( ), 其中 S1=new SaleLineItem()时使用的spec是由makeLineItem的参数传入的

相对临时的可见性,只在方法范围内可见 可见性的第二种常见形式

局部可见 相对临时的可见性,只在方法范围内可见 两种常见情况 创建局部实例,并赋给局部变量 将方法执行的返回对象赋给局部变量

全局可见 相对永久的可见性 C++全局变量 Singleton pattern

GRASP:设计带职责的对象 五个GRASP模式 应用GRASP实现Process Sale用例 可见性设计 类图设计

类图设计

依据 交互图 软件类和方法 概念模型 类定义的细节 由交互图确定软件类和方法

领域模型和设计类图

方法

Method Name Issues Method Names—create create message不同语言中实现不同 C++,自动或new调用构造器 Java,new 构造器 初始化是常见的activity,通常DCD中可省略 creation-related methods and constructors from a DCD. DCD Design Class Diagrams

Method Names—Accessing Methods getXXX(), setXXX() high noise-to-value ratio,for n attributes, there are 2n uninteresting methods. 通常省略

Method Names—Multiobjects 发向多对象的消息,针对的是容器本身(List, Map), 故ProductSpecification类不应该有find() 方法

Method Names—Language-Dependent Syntax 生成代码时自动转换成相应的语言格式

根据对象的不同,可简单(给开发人员读),可更详细(用工具, 可生成代码,如上图)

加上关联

和domain model中的类图不完全相同 如domain model中Register and ProductCatalog没有考虑需要关联,而创建交互图时发现Register软件对象根据id查找ProductSpecifications时需要与ProductCatalog连接

Adding Dependency Relationships depict non-attribute visibility between classes; in other words, parameter, global, or locally declared visibility. Register software object向ProductCatalog发送消息时,获得 ProductSpecification 类型的返回值,因此Register 短期局部和ProductSpecifications可见(1) Sale接收makeLineItem消息时,传入的是ProductSpecification参数,和ProductSpecification参数可见(2)

visibility marker for attribute or method current iteration does not have many interesting member details; all attributes are private and all methods public.

Rose演示