1、为何要代码重构(Refactoring)程序员
在不改变系统功能的状况下,改变系统的实现方式。为何要这么作?投入精力不用来知足客户关心的需求,而是仅仅改变了软件的实现方式,这是不是在浪费客户的投资呢?数据库
代码重构的重要性要从软件的生命周期提及。软件不一样与普通的产品,他是一种智力产品,没有具体的物理形态。一个软件不可能发生物理损耗,界面上的按钮永远不会由于按动次数太多而发生接触不良。那么为何一个软件制造出来之后,却不能永远使用下去呢?编程
对软件的生命形成威胁的因素只有一个:需求的变动。一个软件老是为解决某种特定的需求而产生,时代在发展,客户的业务也在发生变化。有的需求相对稳定一些,有的需求变化的比较剧烈,还有的需求已经消失了,或者转化成了别的需求。在这种状况下,软件必须相应的改变。数组
考虑到成本和时间等因素,固然不是全部的需求变化都要在软件系统中实现。可是总的说来,软件要适应需求的变化,以保持本身的生命力。网络
这就产生了一种糟糕的现象:软件产品最初制造出来,是通过精心的设计,具备良好架构的。可是随着时间的发展、需求的变化,必须不断的修改原有的功能、追加新的功能,还免不了有一些缺陷须要修改。为了实现变动,不可避免的要违反最初的设计构架。通过一段时间之后,软件的架构就千疮百孔了。bug愈来愈多,愈来愈难维护,新的需求愈来愈难实现,软件的构架对新的需求渐渐的失去支持能力,而是成为一种制约。最后新需求的开发成本会超过开发一个新的软件的成本,这就是这个软件系统的生命走到尽头的时候。架构
代码重构就可以最大限度的避免这样一种现象。系统发展到必定阶段后,使用重构的方式,不改变系统的外部功能,只对内部的结构进行从新的整理。经过重构,不断的调整系统的结构,使系统对于需求的变动始终具备较强的适应能力。布局
2、经过代码重构能够达到如下的目标编码
持续偏纠和改进软件设计设计
重构和设计是相辅相成的,它和设计彼此互补。有了重构,你仍然必须作预先的设计,可是没必要是最优的设计,只须要一个合理的解决方案就够了,若是没有重构、程序设计会逐渐腐败变质,越来越像断线的风筝,脱缰的野马没法控制。重构其实就是整理代码,让全部带着发散倾向的代码回归本位。代理
使代码更易为人所理解
Martin Flower在《重构》中有一句经典的话:"任何一个傻瓜都能写出计算机能够理解的程序,只有写出人类容易理解的程序才是优秀的程序员。"对此,笔者感触很深,有些程序员老是可以快速编写出可运行的代码,但代码中晦涩的命名令人晕眩得须要紧握坐椅扶手,试想一个新兵到来接手这样的代码他会不会想当逃兵呢?
软件的生命周期每每须要多批程序员来维护,咱们每每忽略了这些后来人。为了使代码容易被他人理解,须要在实现软件功能时作许多额外的事件,如清晰的排版布局,简明扼要的注释,其中命名也是一个重要的方面。一个很好的办法就是采用暗喻命名,即以对象实现的功能的依据,用形象化或拟人化的手法进行命名,一个很好的态度就是将每一个代码元素像新生儿同样命名,也许笔者有点命名偏执狂的倾向,如能荣此雅号,将深以此为幸。
对于那些让人充满迷茫感甚至误导性的命名,须要果决地、大刀阔斧地整容,永远不要手下留情!
帮助发现隐藏的代码缺陷
重构代码时逼迫你加深理解原先所写的代码。笔者常有写下程序后,却发生对本身的程序逻辑不甚理解的情景,曾为此惊悚过,后来发现这种症状竟然是许多程序员常患的"感冒"。当你也发生这样的情形时,经过重构代码能够加深对原设计的理解,发现其中的问题和隐患,构建出更好的代码。
从长远来看,有助于提升编程效率
当你发现解决一个问题变得异常复杂时,每每不是问题自己形成的,而是你用错了方法,拙劣的设计每每致使臃肿的编码。
改善设计、提升可读性、减小缺陷都是为了稳住阵脚。良好的设计是成功的一半,停下来经过重构改进设计,或许会在当前减缓速度,但它带来的后发优点倒是不可低估的。
3、哪些状况须要考虑代码重构
臃肿的类: 类之因此会臃肿,是由于开发者缺少对最基本的编码原则,即“单一职责原则”(SRP)的理解。这些类每每会变得很臃肿,是因为不一样的且在功能上缺乏关联的方法都放在了相同的类里面。
长方法: 方法之因此会变得很长主要是有如下几个缘由:
一、许多没有关联性的、功能复杂的模块的代码都放在相同的方法内。这主要是开发者缺少SRP的概念。
二、多种条件都放在同一个方法内,这在长方法内常常会发生的。这是因为缺少McCabe代码复杂度和SRP的概念的比较。
大量的传参: 我常常遇到这几种状况,一些方法跟另外一些方法进行交互,或者调用另外一些方法的时候传入大量的参数。这就会出现若是更改了其中一个参数,就得在多个方法内进行更改。
常量值无处不在: 常常会发现开发者(尤为是新手)会使用一些具备明确含义的常量值(主要是魔鬼数字),但没有给它们赋予合适的常量变量。这会下降代码的可读性和可理解性。
模糊的方法名: 许多时候,如下取的方法名会影响代码的可读性和可理解性:
一、模糊的不具备任何意义的方法名
二、技术性的,却没有说起相关领域的名称
4、重构的方法
提取类/抽离方法
正如上面提到的,像“臃肿的类”(一个类提供了本该有几个类提供的功能)这种代码异味应该将原有类中的方法和属性移动到适当数目的新类中去。旧类中对应新类的方法和属性应该被移除。另外,有时候一些类过于臃肿是由于它包含了被其余类使用本应该是其余类的成员方法的成员方法。这些方法也应该被迁移到合适的类中。
提取方法
像上面提到的“过长的方法”这种代码异味能够经过从旧方法中提取代码到一个或多个新方法中消除。
分离条件
许多时候,一个方法很长是由于包含好几个分支语句(if-else)。这些分支条件能够被提取和移动到几个单独的方法中。这确实能大大改善代码可读性和可理解性。
引入参数对象/保留全局对象
在我作代码审查时发现另一个很常见的状况 - 好几个参数被传入方法。问题主要与须要从已有方法中增长或者移除一个方法参数有关。在这种场景,建议将相关方法参数组成一个对象(引入参数对象),让方法传递这些对象而不是每一个单独的参数。
用符号常量替换魔法数字
对于有意义的而且处处被使用的字面常量,应该为它们分配一个命名常量。这能大大加强代码可读性和可理解性。
重命名方法
正如上面提到的,模糊不清的方法名会影响代码的可以使用性。这些模糊不清的名称应该重命名为有意义的可能与业务术语有关的名称,来帮助开发者经过业务上下文更好地理解代码。这很须要技巧而且要求开发者与业务专家一块儿协做来理清代码须要知足的业务需求。有趣的是,这种重构方法看起来彷佛很是容易理解,可是经常被许多开发者忽视,虽然在Eclipse这种IDE的refactor菜单项中常常出现这一项。
5、当重构没有现成的明显的方向时,咱们能够遵循下面的原则
一、当属性、方法或类存在任何的须要复用的意向时,概括提炼它们。
二、不要低估小方法对代码整洁的做用。使用小方法能让你节省不少笔墨。
三、用封装控制可见度。
四、消除依赖。
五、简化构造方法——即便这样作会使代码变复杂。
六、不肯定时,将计算操做移入到这些数据的全部者对象里,或将数据移动到执行计算操做的对象里(也就是迪米特法则(Law of Demeter))。
七、使用小对象,松耦合,避免大对象,高聚合。
八、使用代理对象,模拟对象和辅助对象来隔离网络,数据库,文件和用户接口。
九、不肯定时,尽可能在model里添加代码,必要时才往controler添加代码。view里添加的都应该是便捷功能和简写方法,但不要局限于此。