JAVA代码重构--改善既有代码的设计(⼀)
JAVA代码重构–改善既有代码的设计(⼀)
本⽂主要借鉴了<;重构 改善既有代码的设计>与<;设计模式>这两本书;
主要解释重构的原理(principles)和最佳实践⽅式(best practices),并指出何时何地你应该开始挖掘你的代码以求改善。
<;重构 改善既有代码的设计>核⼼是⼀份完整的重构名录(catalog of refactoring),其中每⼀项都介绍⼀种经过实证的代码变换⼿法(code transformation)的动机和技术。某些项⽬如Extract Method和Move Field看起来可能很浅显,但不要掉以轻⼼,因为理解这类技术正是有条不紊地进⾏重构的关键。本书所提的这些重构准则将帮助你⼀次⼀⼩步地修改你的代码,这就减少了过程中的风险。很快你就会把这些重构准则和其名称加⼊⾃⼰的开发词典中,并且朗朗上⼝。
重构重点
1.Duplicated Code(重复代码)
同⼀个类的两个函数含有相同的表达式,需要将重复的这段代码提出来,让这两个函数都调⽤这段代码,两个互为兄弟的⼦类内含相同表达式,需要将代码提炼出来放⼊⽗类中;
java replace方法如果两个毫不相关的类出现Duplicated Code,需要将重复代码提炼到⼀个独⽴类中,然后在另⼀个类内使⽤这个新类,抑或这个函数可能属于第三个类,⽽另两个类应该引⽤这第三个类;
2.Long Method(过长函数)
拥有短函数的对象会活得⽐较好、⽐较长。解释能⼒、共享能⼒、选择能⼒——都是由⼩型函数⽀持的。每当感觉需要以注释来说明点什么的时候,就把需要说明的东西写进⼀个独⽴函数中,并以其⽤途命名
3.Large Class(过⼤的类)
⼀个类如果拥有太多代码,就需要将其拆分,可以先确定客户端如何使⽤它们,然后为每⼀种使⽤⽅式提炼出⼀个接⼝;
产⽣条件:这个类实例变量太多,必然会有Duplicated Code(重复代码) ;类内如果有太多代码,也会产⽣Duplicated Code,让整个类看起来混乱并最终⾛向死亡。
4.Long Parameter List(过长参数列)
太长的参数列难以理解,太多参数会造成前后不⼀致、不易使⽤,⽽且⼀旦需要更多数据,就不得不修改它,可以把函数所需要的东西通过对象传⼊;
⼀旦你需要更多的数据,你就不得不去修改它。相反如果你通过传⼊对象,⾸先你的参数列表就很短,其次如果你想增加别的变量,会有可能只需要在函数中对这个参数对象多加⼀次请求就⾏了。
如果向已有的对象发送⼀条请求可以取代⼀个参数,那么你应该使⽤Replace Parameter with Method。注意是已有的参数,不是不存在的参数。这个需要理解⼀下,已有的参数就是函数宿主类中的某⼀个对象字段,也可能是函数本⾝存在另⼀个对象参数,让这个对象来替换它。如果某些数据缺乏合理的对象归属。可以使⽤Introduce Parameter Object来为它们制造⼀个“参数对象”。
5.Divergent Change(发散式变化)
如果某个类经常因为不同的原因在不同的⽅向上发⽣变化,就会出现Divergent Change,如增加⼀个功能需要修改多处,这时应该把针对某⼀外界变化的所有相应修改都放在⼀个类中;时刻要记住这么⼀句话:针对某⼀外界变化的所有相应修改,都应该产⽣在单⼀类中,⽽这个新类中的所有内容都应该反应此变化。
6.Shotgun Surgery(霰弹式修改)
如果每遇到某种变化,就必须在许多不同的类内做出许多⼩修改,这就是Shotgun Surgery,应该把需要修改的代码放进同⼀个类,如果没有合适的类就创建⼀个
7.Feature Envy(依恋情结)
如果⼀个函数为了计算某个值,需要⽤到⼏个类的数据,就把函数移到最多被此函数使⽤的数据的类中;⾯向对象技术就是将数据和⾏为包装在⼀起。⼀个经典的坏味道的场景就是函数都某个类的兴趣⾼过对⾃⼰所处类的兴趣,往往焦点就是数据。很多时候我们可以看到这种场景,类A的中的函数为了进⾏计算获取了类B中⼏乎⼀半的数据,⾯对这种情况,其实很简单,就是使⽤Move Method将这个函数直接移到B中去,然后让类A的调⽤点就调⽤类B的这个函数。如果⼀个函数中,只有⼀部分受这种“依恋之苦”,你应该⽤Extract Method把这⼀部分提炼出来,然后通过Move Method把这个提炼的函数移动到他所依恋的类中去。如果出现⼀个函数需要⽤到⼏个类的时候,我们会很难判断究竟应该把它放哪。这个时候有个⼩技巧你只要记住,这个函数获取哪个类的数据最多,就把这个函数移动到哪个类中去。当然⾯对这种多重以来,你也可以⽤Extract Method将这个函数分解成⼀系列⼩函数然后移动到他们对应的需要的类中去也可以轻松完成。
8.Data Clumps(数据泥团)
总是绑在⼀起出现的数据应该拥有属于它们⾃⼰的对象,评判⽅法是:删掉众多数据中的⼀项,如果其他数据没有意义了,那就应该为它们产⽣⼀个新对象;可以使⽤复⽤,让他们拥有属于他们⾃⼰的⾏为,简化参数列表
9.Primitive Obsession(基本类型偏执)
⼤多数编程环境都有两种数据:结构类型允许你将数据组织成有意义的形式;基本类型则是构成结构类型的积⽊块。结构总是会带来⼀定的额外开销,它们可能代表着数据库中的表,如果只为做⼀两件事⽽创建结构类型也可能显得太⿇烦;
10.Switch Statements(switch)
⽂中作者⽤了“惊悚”来形容swtich语句,的确,⾯向对象中压根就不需要存在swtich,多态给了⽐swtich更优雅的解法。swtich语句本⾝就代表了重复,你在需要做类型判断的时候你就需要写这⼀长串的swtich不说,当你要增加新的类型你就需要寻这些所有的swtich,维护⼯作⾮常困难。⼤多数时候,当你⼀看到swtich语句,你就应该考虑⽤多态来优雅的解决。问题是这个多态应该出现在哪 ?swtich语句常常跟类型码有关,你所要做的就是寻与这些类型码有关的函数或类。应该先⽤Extract Method把这个swtich语句提炼到⼀个独⽴函数中去,然后运⽤Move Method把它搬移到需要多态性的那个类⾥。接下来你需要考虑是否使⽤Replace Type Code wtih Subclass或者Replace Type Code with State/Strategy。⼀旦这样的继承结构完成之后,你就可以运⽤Replace Condiional with Polymorphism来优雅的进⾏解决了。
11. Parallel Inheritance Hierarchies(平⾏继承体系)
Parallel Inheritance Hierarchies其实是Shotgun Surgery的特殊情况。意思就是当你为某⼀个类增加⼦类的同时你必须为别的类同时增加⼦类。有个简单办法可以判断,当你发现某个类的继承体系前缀和另外⼀个继承体系前者完全相同,你便闻到了这股坏味道。
解决这个办法的⼀般策略就是让⼀个继承体系的实例去引⽤另外⼀个继承体系的实例。然后不断运⽤Move Method和Move Field到被引⽤端,你就可以将引⽤端的继承体系完全打破,做到被引⽤端单⼀的继承体系。
12.Lazy Class(冗赘类)
虽然⾯向对象世界带给我们对象的魅⼒,但并不是类越多就越好。虽然加⼊间接层可以带来各种⽅便,但所有的类都是需要⼈能够去理解和维护的。对于那些实际作⽤不⼤的类,或者因为某些重构原因让它变得没有价值的时候,或开发者事前规划了某些类来应对变化,但实际上并没有发⽣这些变化。不论上述哪⼀种原因,就让这个类消失好了,这样减少你的⼯作量的同时也在减少别⼈的⼯作量,因为很有可能将来维护代码的⼈还是你⾃⼰。如果⼦类没有做⾜够的⼯作,可以运⽤Collapse Hierarchy来打破继承体系,对于⼏乎没有⽤的组件,你可以运⽤Inline Class来对付它们。
对象技术的新⼿通常不愿意在⼩任务上运⽤⼩对象,但是对象的⼀个极⼤的价值在于:它们模糊(甚⾄打破)了横亘于基本数据和体积较⼤的类之间的界限
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论