java什么是重构 何时使用重构_Java 之重构现有系统实战(一)

何时进行重构

重构可遵循三次法则:第一次做某件事时只管去做;第二次做类似的事会产生反感,但无论如何还是可以去做;第三次再做类似的事,你就应该重构,即 事不过三,三则重构。具体表现为:添加功能时重构、修补错误时重构、复审代码时重构。

对于现有代码根本无法正常运作、项目已近最后期限的场景不能进行重构,前者可以考虑拆分后重写,后者则是为了保证项目能正常上线。

具有哪些代码特征需要重构

2.1 Duplicated Code (重复代码)

如果你在一个以上的地点看到相同的程序结构,可以考虑设法将他们合而为一。

一般表现为:同一个类的两个函数含有相同的表达式;两个互为兄弟的子类内含有相同表达式;不同类中由于某种原因存在相同的或相似的表达式。

2.2 Long Method (过长函数)

如果一个函数超过了 50-80 行,你就可以考虑进行分解了。

一般从以下几点入手:分析临时变量和参数,考虑将注释部分封装到一个方法中,对于多个条件表达式和循环的部分进行封装。

2.3 Large Class (过大的类)

如果一个类有太多实例变量和函数,可以考虑将几个变量一起提炼到新类中,对于特征相似的函数可以考虑提炼到一个接口中,然后再针对不同接口分解这个类,拆分成多个实现类。

2.4 Long Parameter List (过长参数列)

如果函数的传参太多导致难以理解,且对于调用方造成了困扰,就应该考虑缩减了,最好函数的传参不要超过 10 个,如果太多可以考虑是否可以将传参封装到一个对象来进行传递。

2.5 Divergent Change (发散式变化) / Shotgun Surgery (霰弹式修改)

如果在修改程序某个功能时,需要修改多处地方,此时就应该考虑来重构它了,使该修改尽可能的集中在一个地方,便于后期维护。

2.6 Feature Envy (依恋情结)

如果某个类的函数为了计算某个值或其他行为需要从另一个对象那儿调用许多取值函数,此时就需要判断哪个类拥有最多被此函数使用的数据,然后就把这个函数和那些数据摆在一起。

最根本的原则:将总是一起变化的东西放在一起,数据和引用这些数据的行为总是一起变化的,如果出现例外,我们就搬移那些行为,保持变化只在一地发生。

2.7 Data Clumps (数据泥团)

如果两个类中相同的字段、许多函数签名中相同的参数出现三四项,此时就需要将这些字段/参数删除缩短,减少字段和参数的个数,提炼到一个独立对象中。

2.8 Primitive Obsession (基本类型偏执)

所谓的基本类型偏执就是:对于对象和基本类型的取舍,如果多个基本类型字段总被放在一起使用的话,那么可以考虑将其定义为一个对象来进行使用了。

2.9 Switch Statement ( switch 惊悚现身)

少用 switch (或 case )语句,因为会出现许多重复,每当看到 switch 语句,如果条件语句很复杂,你就应该考虑使用多态来替换它。

2.10 Parallel Inheritance Hierarchies (平行继承体系)

如果你发现某个继承体系的类名称前缀和另一个集成体系的类名称前缀完全相同,即如果你为某个类增加一个子类,必须也为另一个类相应的增加一个子类,此时应该考虑重构了。消除这种重复性的一般策略是:让一个继承体系的实例引用另一个继承体系的实例。

2.11 Lazy Class (冗赘类) / Speculative Generality (夸夸其谈未来性)

如果一个类的所得不值其身价,它就应该消失。

如果一个类本应该做某事却试图以各式各样的钩子和特殊情况来处理一些非必要的事情,那么就应该考虑移除它;比如抽象类没有太多作用的话就除掉,如果函数的参数未用到就应该去掉,如果函数或类的唯一用户是测试用例,就应该去掉等。

2.12 Temporary Filed (令人迷惑的暂时字段)

如果某个实例变量仅为某种特定场景而定或者一个类中有个复杂算法,需要好几个变量,但是这些字段只在该算法时才有效,其他情况下只会让人迷惑,此时应该考虑将这些变量和其相关函数提炼到一个独立类中,提炼后的新对象将是一个函数对象。

2.13 Message Chains (过度耦合的消息链)

如果一个对象请求另一个对象,然后再向后者请求另一个对象,然后在请求另一个对象,这就是消息链。通常最好的选择是:先观察消息链最终得到的对象是用来干什么的,看看能够把使用该对象的代码提炼到一个独立函数中,把这个函数推入到消息链。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
/* * 原始需求背景: * 网宿CDN要按月收取客户的服务费用,根据流量的大小、 * 服务的类型等,收取不同的费用,收费规则如下: * web应用:1000元/M * 流媒体应用:1000元/M*0.7 * 下载应用:1000元/M*0.5 * 月末打印报表时,要罗列每个用户每个频道的费用、客户总费用, * 还要打印该客户的重要性指数,重要性指数=网页流/100+下载流量/600; * * 需求变更场景: * 系统已经开发出来了,接下来,运维部门现在希望对系统做一点修改, * 首先,他们希望能够输出xml,这样可以被其它系统读取和处理,但是, * 这段代码根本不可能在输出xml的代码中复用report()的任何行为,唯一 * 可以做的就是重写一个xmlReport(),大量重复report()中的行为,当然, * 现在这个修改还不费劲,拷贝一份report()直接修改就是了。 * 不久,成本中心又要求修改计费规则,于是我们必须同时修改xmlReport() * 和report(),并确保其一致性,当后续还要修改的时候,复制-黏贴的问题就 * 浮现出来了,这造成了潜在的威胁。 * 再后来,客服部门希望修改服务类型和用户重要性指数的计算规则, * 但还没决定怎么改,他们设想了几种方案,这些方案会影响用户的计费规则, * 程序必须再次同时修改xmlReport()和report(),随着各种规则变得越来越复杂, * 适当的修改点越 来越难找,不犯错误的机会越来越少。 * 现在,我们运用所学的OO原则和方法开始进行改写吧。 */
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值