【重构学习】07 数据的重构

这里的数据指的大概就是字段(貌似这章有些东西也是过时了,因为现在的.NET已经发展了很久了,包括Java也是)

1、自封装字段(其实就是属性啦,过时了)

修改点:直接访问字段,但是与字段间的耦合关系逐渐变得笨拙

做法:为这个字段建立一个取值/设值函数,并且只以这些函数来访问数据

好吧,现在明白属性是怎么来的了吗,就是因为这个原因,所以有的人会干脆和你说,你不要写公共字段,直接写公共属性。

因为公共字段能做的公共属性都能做,不能做的公共属性也能做。

public string 我叫公共属性 { get; set; }

多写个这东西好用多了,以后万一有个什么反射的需要,也简单多了,举手之劳,所以忘记还有公共字段这回事吧。

2、以对象取代字段

修改点:你有一个字段,需要与其它数据和行为一起使用才有意义

做法:用对象取代字段

简单地说,你玩过DateTime这个类吗,就是系统的类,其实就是对数据的一个封装啊。

如果没有这个东西,那么你是不是要用年,月,日(就算没有时分秒吧),三个字段来表示。搞的多了自然就像自己封装一个Date类,哪天又多了个按格式输出的要求,是不是要再写个格式化函数

所以那么就把这些好基友都放在一起好了,于是DateTime就成了基友之家。(然而我们需要更多的DateTime样的基友之家)

3、将值对象改为引用对象

修改点:你从一个类衍生出许多彼此相等的实例,希望将它们替换为同一个对象

做法:将这个值对象变为引用对象

简单地说,这里所谓的值对象是指DateTime这种对象,即可以建立很多次,纯数据的传递,而所谓的引用对象是指缓存的东西,比如淘宝界面的分类数据,因为所有人看到的分类都是一样的,那么我们不需要每次都从数据库取值

缓存一下就好,不需要每次New一个分类对象,然后调用查询函数,而是去找缓存去看是否有了缓存,有了缓存,那么就调用,没有缓存那么就再从数据库里面取值。只要缓存一更改,大家看到的分类就都更改了。

好了,就是这么个意思

其中为了适应也许引用对象会根据不同的类型创建一个不同的对象,(就像有个墙类,上节课Troy教小朋友们如何搬砖砌墙,所以新建正常的墙的对象,这节课话题换了,Troy教小朋友们码长城,于是就新建一个长城对象)

当涉及到切换子类的时候,可以用这种方法使得客户端调用的时候不需要知道还有长城这个类,只需要用墙类里的工厂函数就好了,当然也许你下次还得搞个扛水泥去搞个水泥墙的类,那么在 工厂函数里再加就好了。

所以提到的一个重构方法:

将构造函数改为调用工厂函数,即

 public class Wall{
        public Wall(string length){
            //啦啦啦
        }
   }

改为

public class Wall{
        public static Wall Create(string type){
            if (type=="Great"){
                return new GreatWall("一万里");
            }
            else{
                return new Wall("一米");
            }
        }
        protected Wall(string length)
        {
            //啦啦啦
        }
    }
    public class GreatWall:Wall
    {
        public GreatWall(string length):base(length)
        {
            //啦啦啦
        }
    }

这种方法的用处在于客户调用不需要去知道子类,只需要知道type就行了,当然具体情况具体对待,你也可以不用这么写

然后这个所谓的引用变量的稳妥一点的做法还是要判断一下这个对象存不存在,不存在就去取值,存在就直接调用。

4、将引用对象改为值对象

  是的,你没有看错,当你千辛万苦改成了值对象之后,有个需求第二天可能又会让你改回来。。

  动机:因为你的引用对象很小且不可变,而且不易管理。

  不可变是什么鬼?我看了《重构》这个看了半天,最后才弄明白。

  还是用分类缓存来说,淘宝的缓存就是可变的,因为淘宝的缓存假如作为商家的你可以自己去去增加分类,然后刷新它,那么所有的客户得到的分类都变了。

  那么不可变是就是:

  

  我在本地把百度首页改成这样,但是你们这些人并不知道我已经在用谷歌了╮(╯▽╰)╭

  换句话说,有天,马老板说咱淘宝分类就这么搞了,无论怎样就这么多分类了,不许商家去增加分类,那么,这个缓存就是不可变的了,某天他说不要那么多分类了,就假货和真货两个类的时候,那么引用对象足够小了

  那么这个引用对象也就不需要了,改成值对象就好了,比如像百度一下直接作为文本,写死在页面上了。

  好吧,我就是这么理解的。

  正经话:引用对象就是客户公用的,当我去改动后,其他客户看到的也就变了,而值对象不是,当我改动后只有我自己这边变了。(懂了吗,我觉得自己已经讲得很清楚了)

5、以对象取代数组

  修改点:你有一个数组,其中的元素代表不同的东西

  做法:以对象替换数组,对于数组中的每个东西,以一个字段来表示。

  换句话说,有个混蛋把DateTime的年月日写在一个int date[3];这样的东西里面,其中date[0]代表年,date[1]代表月,你是否想要打死他?

  --未完待续

时间: 2024-10-15 04:10:42

【重构学习】07 数据的重构的相关文章

【重构学习】11 大型重构

好了,前面所有的都是很简单的例子,现在开始的是大型重构. 对于大型重构来说,情况复杂多变,耗时也会很长,前面的简单重构大多是在一个小时内可以完成,但是对于大型重构来说可能需要几个月,甚至数年.如果是一个运行中的系统,重构起来只能每天一点点去慢慢重构. (恕我直言,在国内恐怕这样的公司也很少.所以我们要自己养成随时重构的习惯,不要挖坑给自己埋最好.没谁能给你这么长时间重构,特别当你是个低端程序员的时候.你得相信,你所有偷懒的举动,都会给你以后的工作带来麻烦.除非你明天走人了,那么你的锅可能就给我背

【重构学习笔记】

重构的定义:重构是对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本 从定义里我们可以看出,重构是对代码和架构的一种修改,旨在提高代码的效率和可读性,来达到降低修改成本的目的.而重构对于用户体验来说,就像定义中说到的,只能对可观察行为作出很小的变化,甚至不造成变化. 关于同事些代码经常会把DAO注入到表现层Controller里面使用,我一直很反感这样的做法,奈何找不出可以反驳这些老员工的理由,确实才疏学浅了. 认真想想 例如,一般情况,我们会在Ser

C#重构学习2

转帖重构学习 重构?代码坏味道?看到这两个疑问,也许就知道本期的话题是关于“重构”的,重构无处不在,重构可大可小,重构随时随地.让重构时刻记在脑海,使自己的代码变的优美.就让这本“重构艺术”手册带你走进重构的世界,亲密接触重构,如欣赏艺术般,体会重构的魅力. 文章下载地址:http://files.cnblogs.com/xia520pi/C_Sharp_Refactoring.rar 文章的目录: 1.代码重构 1.1.版权声明 1.2.内容详情 2.项目重构方案设计 2.1.版权声明 2.2

【重构学习】08 条件表达式的重构

所谓条件表达式,就是分支语句,去掉分支语句咯 1.分解条件表达式 修改点:你有一个复杂的条件语句(就是if else语句) 做法:将条件表达式的三个部分分别提炼出独立函数 即 if (A部分) { B部分; } else { C部分; } 这三个部分都提炼成函数就好了. 2.合并条件表达式 修改点:你有一系列测试,都得到相同结果 做法:将这些测试合并成一个条件表达式,并将这个表达式提炼成一个独立函数 3.合并重复的条件片段 修改点:在条件表达式的每个分支上有着相同一段代码 做法:将这段重复代码搬

由学习《软件设计重构》所想到的代码review(二)

我们接第一篇由学习<软件设计重构>所想到的代码review(一) 来继续说明在代码review中,有哪些属于"层次结构"中的坏味道. 注:通过上图咱们看到了在层次结构中有九大问题点,咱们就从中找出三个典型的问题点给与分析和解释. 一.缺失的层次结构 问题点: public Insets getBorderInsets(Component c, Insets insets) { if(c instanceof AbstractButton) { margin = ((Abst

重构学习-重构原则

什么是重构: 视上下文重构有两个不同的定义,第一个定义是名词形式 对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本 重构的另一人用法是动词形式 使用一系列的重构手法,在不改变软件可观察行为的前提下调整其结构. 有人说重构就是整理代码 ,从某种角度上来说,是,但是重构不止于此,因为它提供了一种更为高效且受控的代码整理 技术,运用代码重构技术后你会发现对代码的整理会比以前更加高效. 重构的目的是使软件更容易被理解和侯.你可以在软件的内部做很多修改,但必须

重构学习

简化函数调用 Rename Method:只要你能理解一段程序的功能,就应该大胆地使用Rename Method将你所知道的东西传达给其他人,如果合适的话也可以修改变量名称和类名称. 函数参数的修改:Add Parameter和Remove Parameter,避免使用很长的参数队列 Preserve Whole Object:如果参数大多来自于一个对象,则把它们替换为单一对象 Introduce Parameter Object:把参数放到一个参数对象中 Replace Parameter w

RabbitMQ (消息队列)专题学习07 RPC

(使用Java客户端) 一.概述 在Work Queue的章节中我们学习了如何使用Work Queue分配耗时的任务给多个工作者,但是如果我们需要运行一个函数在远程计算机上,这是一个完全不同的情景,这种模式通常被称之为RPC. 在本章节的学习中,我们将使用RabbitMQ来构建一个RPC系统:一个远程客户端和一个可扩展的RPC服务器,我们没有任何费时的任务进行分配,我们将创建一个虚拟的RPC服务返回Fibonacci数. 1.1.客户端接口(Client Interface) 为了说明一个RPC

ThinkPhp学习07

原文:ThinkPhp学习07 简单CRUD操作 1 public function show() { 2 $m=M('User'); 3 4 // $arr=$m->find(2); //查找id=2的数据,find只能返回一条数据 5 //2.SELECT * FROM `tp_user` WHERE ( sex=1 ) 6 // $arr=$m->where('sex=1')->select(); 7 8 //3.INSERT INTO `tp_user` (`username`,