小结_02:《重构:改善既有代码的设计》
来源:互联网 发布:浙大计算机 专硕 知乎 编辑:程序博客网 时间:2024/06/05 01:51
大型重构涉及如下四种工作:
1. Tease Apart Inheritance(梳理并分解继承体系)
继承的作用之一:可以明显减少子类中的代码量。
但是继承很容易被误用:今天为了一项小小的任务而加入一个小小的子类,明天为另一项任务在继承体系的另一个地方加入另一个子类。一个星期(一个月、一年。。)之后,这个体系将变成一个真正的泥淖;变得基本令人无法理解。
混乱的判别方法:判别继承体系是否承担了两项不同的责任的方法:如果继承体系中的某一特定层级上的所有类,其子类名称都以相同的形容词开始,那么这个体系很可能就是承担着两项不同的责任。(见下图所例:)
重构的做法:
a. 识别出继承体系所承担的不同责任,然后建立一个二维的表格标示出不同的任务。例如从以上继承体系中得到如下表格:
交易
活动交易
被动交易
表格化显示交易
b. 现在分辨一下这些不同的责任,发现“表格化显示交易”是一种显示风格,应该被放到另一个继承体系当中去,这样就得到了如下类图:
c. 针对原来继承体系中的每个子类,建立PresentationStyle的一个个子类,并将Deal类中用来保存PresentationStyle实例的那个实例变量初始化为适当的子类实例。
d. 然后,使用一些重构技巧,将Deal子类中与显示逻辑相关的函数和变量搬移到PresentationStyle相应的子类当中去。这样就消除了Deal继承体系下的用于显示的子类:
e. 现在可以分别简化两个继承体系了: 这次重构的效果依简化的结果而定;比如说,一般地我会幸运地发现,显示风格中“主动”和“被动”并不是那么重要,然后类图将被简化如下:
f. 甚至,连“单一显示”和“表格化显示”之间的差别,都可以运用若干变量来捕捉,根本不需要为它们建立相关子类:
第二种工作: Convert Procedural Design to Objects(将过程化设计转化为对象设计)
问题表现:类中有着长长的过程化函数和极少的数据,旁边则是一堆哑数据对象————除了数据访问函数以外没有其他任何函数。
重构办法:
a. 针对每一个记录类型(比如说关系数据库当中的每一个表),转变成一个哑数据对象
b. 针对每一处过程化风格,将该处的代码提炼到一个单独的类当中去。
c. 针对这个类中每一段长长的程序,实施Extract Method以及其他相关重构将它分解。再将分解后的函数分别移到它所相关的哑数据类中去。
d. 如果这个被重构的类完全被搬空了,那就把它干掉。
第三种工作: Separate Domain from Presentation(将领域和表述/显示分离)
简而言之,此方法将使你的代码具有MVC的风格
做法:
a. 为每个窗口(或者任何关于前端处理的责任)建立一个逻辑处理类
b. 如果窗口包含表格(或者批量数据),为每一行建立一个新类;以一个集合容纳这些新类;
c. 对窗口包含的数据(或者前台传过来的数据)做检查,如果数据只被用于UI,那么留下;如果数据不会被显示出来,服务于某种逻辑,那么把它移到“逻辑处理类”当中去;如果数据同时被UI和逻辑使用,那么把它复制一份,在UI类和逻辑处理类都存在,并设法使之同步。
d. 在UI类中隔离涉及“逻辑处理”的模块,将他们统统移到“逻辑处理类”当中去。
e. 最后进一步重构“逻辑处理类”。
第四种工作: Extract Hierarchy(提炼继承体系)
一开始设计者只想以一个类实现一个概念;但是随着设计方案的演化,最后可能一个类实现了两个、三个乃至十个不同的概念。
这种类可以被称为“瑞士军刀”般的类,能做各种事情,条件表达式遍布各处。
例如:一个电费计算程序:使用了大量条件逻辑来计算不同情况下的费用,冬季和夏季的电价不同,私宅用电、小型企业、大型企业、社会救济(包括残障人士)用电的价格也不同,这些将导致复杂的计算逻辑。
本重构将消除这种状况,但是前提条件是:“条件逻辑”在对象的整个生命周期保持不变。意即,持有该对象的类不会多次改动条件表达式所涉及的变量,并在改动之后调用其中的接口。
重构方法一:渐进法
a. 鉴别出“一种”变化情况,
b. 针对这种变化情况,新建一个子类,在源类中使用工厂方法返回这个子类;
c. 将含有条件逻辑的函数,一次一个地逐一复制到子类中,然后在明确情况下简化这些函数。
d. 重复上述过程,将所有“变化”的情况都分离出来,直到可以将超类声明为抽象类为止。
e. 删除超类中那些被所有子类覆写的函数本体,并将它们声明为抽象函数。
重构方法二:一次到位
a. 针对源类的每一种变化情况,建立一个子类。
b. 使用 Replace Constructor with Factory Method将原始类的构造函数转变为工厂函数,并令它针对每一种变化情况返回适当的子类实例;
c. 针对带有条件逻辑的函数,实施“多态化替换条件表达式”
d. Over
- 小结_02:《重构:改善既有代码的设计》
- 小结_01:《重构:改善既有代码的设计》
- 重构-改善既有代码的设计
- 重构-改善既有代码的设计
- 重构-改善既有代码的设计
- 重构-改善既有代码的设计
- 重构:改善既有代码的设计
- 重构--改善既有代码的设计
- 重构-改善既有代码的设计
- 重构-改善既有代码的设计
- 重构-改善既有代码的设计+
- 重构--改善既有代码的设计
- 重构 改善既有代码的设计
- 重构.改善既有代码的设计
- 重构:改善既有代码的设计
- 重构,改善既有代码的设计
- 重构改善既有代码的设计
- 重构-改善既有代码的设计
- 学习使用libevent(一)
- 视频编解码---x264用于编码,ffmpeg用于解码
- 用JAVA写的一个每月的日历程序,效果看正文。
- 多核时代的移动开发(一)-函数式编程思想到来
- Struts2入门到精通一——————Struts2初步
- 小结_02:《重构:改善既有代码的设计》
- Android 关于高仿 WIN8系统磁贴点击下沉倾斜效果的应用说明
- android cocos2d-x引擎优秀文章收集
- UVA 147 Dollars
- 从C到C++
- mysql问题(论坛解决问题收藏)
- poj 2424 餐厅与客人
- Discuz查询标签及带此标签的帖子总数
- C语言List使用样例