你的程序中,某个字段被其所驻类之外的另一个类更多的用到。在目标类建立一个新字段,修改源字段的所有用户,令它们改用新字段。

       动机:在类之间移动状态和行为,是重构过程中必不可少的措施。随着系统发展,你会发现自己需要新的类,并需要将现有的工作责任拖到新的类中。在这个星期看似合理而正确的设计决策,到了下个星期可能不再正确。这没问题,如果你从来没遇到这种情况,那才有问题。

如果发现对于一个字段,在其所驻类之外的另一个类中有更多函数使用了它,就考虑搬移这个字段。上述所谓“使用”可能是通过设值/取值函数间接进行的。也可能移动该字段的用户(某个函数),这取决于是否需要保持接口不受变化。如果这些函数看上去很适合待在原地,就选择搬移字段。

使用Extract Class (提炼类)时,也可能需要搬移字段。此时可以先搬移字段,然后搬移函数。

做法:1、如果字段的访问级别是public,使用 Encapsulated Field (封装字段)将它们封装起来。如果你有可能移动那些频繁访问该字段的函数,或如果有许多函数访问某个字段,先使用 Self Encapsulate Field (自封装字段)也许会有帮助。

2、编译、测试。

3、在目标类中建立于源字段相同的字段,并同时建立相应的设值/取值函数。

4、编译目标类。

5、决定如何在源对象中引用目标对象。首先看是否有一个现成的字段或函数可以助你得到目标对象。如果没有,就看能否轻易建立这样一个函数。如果还不行,就得在源类中新建一个字段来存放目标对象。这可能是个永久性修改,但你也可以让它是暂时的。因为后续重构可能会把这个新建字段除掉。

6、删除源字段。

7、将所有对源字段的引用替换为某个目标函数的调用。如果需要读取该变量,就把对源字段的引用替换为对设值函数的调用。如果源字段不是private的,就必须在源类的所有子类中查找源字段的引用点,并进行相应替换。

8、编译、测试。

下面是Account class的部分代码:
class Account...
    private AccountType _type;
    private double _interestRate;
    double interestForAmount_days(double amount, int days) {
       return _interestRate * amount * days / 365;
    }

我想把表示利率的_interestRate搬移到AccountType class去。目前已有数个函数引用了它,interestForAmount_days()就是其一。下一步我要在AccountType中建立_interestRate field以及相应的访问函数:
class AccountType...
    private double _interestRate;

void setInterestRate(double arg) {
       _interestRate = arg;
    }
    double getInterestRate() {
       return _interestRate;
    }

这时候我可以编译新的 AccountType class。
现在,我需要让Account class中访问_interestRate field的函数转而使用AccountType对象,然后删除Account class中的_interestRate field。我必须删除source field,才能保证其访问函数的确改变了操作对象,因为编译器会帮我指出未正确获得修改的函数。

class Account...
    private double _interestRate;
    double interestForAmount_days(double amount, int days) {
       return _type.getInterestRate() * amount * days / 365;
    }

如果有很多函数已经使用了_interestRate field,我应该先运用Self Encapsulate Field(171):

class Account...
    private AccountType _type;
    private double _interestRate;
    double interestForAmount_days(double amount, int days) {
       return getInterestRate() * amount * days / 365;
    }
    private void setInterestRate(double arg) {
       _interestRate = arg;
    }
    private double getInterestRate() {
       return _interestRate;
    }

这样,在搬移field之后,我就只需要修改访问函数就行了:

double interestForAmount_days(double amount, int days) {
       return getInterestRate() * amount * days / 365;
    }
    private void setInterestRate(double arg) {
       _type.setInterestRate(arg);
    }
    private double getInterestRate() {
       return _type.getInterestRate();
    }

如果以后有必要,我可以修改访问函数(accessors)的用户,让它们使用新对象。Self Encapsulate Field(171)使我得以保持小步前进。如果我需要对class做许多处理,保持小步前进是有帮助的。特别值得一提的是:首先使用Self Encapsulate Field(171)使我得以更轻松使用Move Method(142)将函数搬移到target class中。如果待移函数引用了field的访问函数(accessors),那么那些引用点是无须修改的。

转载于:https://www.cnblogs.com/pony1223/p/7530450.html

重构改善既有代码设计--重构手法11:Move Field (搬移字段)相关推荐

  1. 重构改善既有代码设计--重构手法19:Replace Data Value with Object (以对象取代数据值)...

    你有一笔数据项(data item),需要额外的数据和行为. 将这笔数据项变成一个对象. class Order... private string customer; ==> class Or ...

  2. 《重构-改善既有代码设计》读书笔记-重构篇

    2019独角兽企业重金招聘Python工程师标准>>> 重构定义 名词 对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本.--<重 ...

  3. 重构-改善既有的代码设计-------代码的坏味道

    重构-改善既有的代码设计 代码的坏味道 神秘命名(Mysterious Name) 给函数.变量.模块和类命名时,要使它能清晰地表明自己的功能和用法,使得写下的代码直观明了. 常用重构手法为重命名,包 ...

  4. 重构改善既有代码设计

    目录 一.什么是重构 二.重构的目的和时机 2.1 目的 2.1.1 改进软件的设计 2.2.2 使软件更容易理解 2.2.3 帮助找到 BUG 2.2.4 提高编程速度 2.2 重构的时机 2.3 ...

  5. 重构-改善既有代码的设计:对象之间移动特性的八种方法(五)

    在面向对象编程过程中,明确该对象的职责.类应该是:做自己该做的事,应尽该尽的义务, 1.Move Method 移动函数 类的行为做到单一职责 不要越俎代庖: 你的程序中,有个函数与其所驻类之外的另一 ...

  6. 重构—改善既有代码的设计

    概述 1.1 参考资料 <重构-改善既有代码的设计>读后总结 <重构改善既有代码的设计> 22种代码的坏味道,一句话概括 1.2 何谓重构 首先要说明的是:视上下文不同,重构的 ...

  7. 『重构--改善既有代码的设计』读书笔记----序

    作为C++的程序员,我从大学就开始不间断的看书,看到如今上班,也始终坚持每天多多少少阅读技术文章,书看的很多,但很难有一本书,能让我去反复的翻阅.但唯独『重构--改善既有代码的设计』这本书让我重复看了 ...

  8. 重构 改善既有代码的设计:代码的坏

    以下内容来自<<重构 改善既有代码的设计>> 一.什么是重构 所谓重构(Refactoring)是这样一个过程:在不改变代码外在行为的前提下,对代码做出修改以改进程序的内部结构 ...

  9. 实践提高《重构改善既有代码的设计第2版》PDF中文+PDF英文+对比分析

    重构是编程的基础,是在不改变外部行为的前提下,有条不紊地改善代码.编程爱好者都知道,Martin Fowler 的<重构:改善既有代码的设计>已经成为全球有经验的程序员手中的利器,既可用来 ...

最新文章

  1. kvm上添加万兆网卡_部署kvm(二)
  2. sdk没有登录什么意思_不需要接入SDK的第三方登录及分享
  3. java map class_java – 将通用Class参数限制为实现Map的类
  4. 使用NDK过程中出现“Unresolved inclusion jni.h”
  5. python100行代码程序-100行python代码,轻松完成贪吃蛇小游戏
  6. Spring实战之二:装配Bean
  7. Sass学习笔记 -- 初步了解函数、运算、条件判断及循环
  8. 数据库索引的作用和优点缺点以及索引的11中用法
  9. python中使用什么导入模块-python—模块导入和类
  10. 作者:景志刚(1977-),男,就职于中国人民银行征信中心数据部
  11. 500多页的机器学习入门笔记,下载超5万次,都讲了些什么?
  12. java面试题常见的坑_java那些年踩过面试题的坑,你是否依旧记忆犹新!
  13. 【排序】剑指offer:数组中重复的数字
  14. Atitit 成果艺术 attilax著 艾提拉著 目录 1. 2 2. 理论类 2 2.1. xxx模型 曲线 定律 原则 曲线 2 3. 代码类成果 范例代码项目 代码类库 与代码片段
  15. 结构体别名typedef struct LNode{}LNode,*Linklist疑惑解答
  16. [史]《全球通史》上册——摘记
  17. 非负大整数加法---网易校招附加题
  18. 销量预测模型案例实战
  19. 动态路由和tab页切换路由
  20. [SUCTF 2019]EasySQL1

热门文章

  1. leetcode 53.最大子序和
  2. 用stm32开发时是直接买现成的开发板还是芯片?开发板学习,芯片硬件设计
  3. 李彦宏被提名工程院院士,而美女教授颜宁落选,当选为美国院士
  4. C++多线程中互斥量std::mutex与模板类std::lock_guard
  5. android view flipper,安卓控件——ViewFlipper
  6. java 工作3年水平_有着4年java工作经验,应该达到什么样的水平?
  7. centos安装python3小白_Centos7 安装Python3
  8. HashMap的负载因子为什么默认是0.75
  9. 048_String对象
  10. Magento 安装后台登不上的解决方法