重新翻了这本圣经级的关于重构的书籍,把第一章关影片租赁的例子在eclipse里重构了一把,总结一下用到的重构原则:
1. extractMethod
本例将switch和ifesle2个计算影片价格和计算影片积分的代码段提取出来,专门放入一个小方法中。其实提取出来的每一个方法都应具有一个明确的业务意义。所以欲所重构,必先熟悉业务,否则没有办法提取出小方法。
2. 代码代码命名rename和代码注释comment
关于代码命名,一段代码的生命意义,不是被机器编译运行,而是后来的维护者可以易读易懂易维护。
关于代码注释,除非一些非常明确的代码,还是应该加上注释。我不完全认同好的代码可以不加注释之说,我相信有时候,初读者看注释一定比代码更容易。一个完整的代码注释,包括不限于版权、类注释、字段注释、方法注释、以及方法内部的注释。
3. move method
根据类的单一责任原则,每一个类只应该处理自己相关的业务。
比如本例中,将获取影片价格和积分的方法从Customer移到Rental,因为这是Reantal的责任。
4. repalce temp with query
本例中,剔除类中的临时变量,这里涉及到重构和性能的平衡。
范例:循环语句,除了取每一个变量外,还要将各个变量累加得到一个总值。重构可能导致获取总值时循环了2次,平衡吧,如果不是性能的瓶颈,请选择这种重构方式。
5.封装变化,把不变的接口留给外部
计算影片价格,需要根据影片类型和租赁日期计算。最后我们选择将租赁日期(Rental)传给Moive,因为本业务中,影片类型可能发生变化,我们希望每次发生变化,对外影响最小。
6. replace condition with polymorphism
本例中的条件语句switch和ifelse滥用,因为没有抽象出Price。Price可以有各种子类(儿童片,新片、一般片子),每个片子,都有自己计算价格和积分的规则。
7.Template method
如果业务需要例外一种打印html的报表,我们可以利用Template方法,head,detail,tail,都可以抽象出来,暴露出变化的方法,因为很多东西是可以共用的。
困惑:
1. 面对重构和性能的平衡,大家是怎么做的?一般人都会说,这个这个计算了两遍,我有时也很迷茫
2. 重构势必导致很多小方法的产生,方法太多有时觉得很乱很散,这个粒度如何控制?
3. 我们公司采用SOA的架构,因为历史原因,我负责维护的系统,和外围系统交互的本应该是VO,但是现在暴露出去的是领域模型domain,这就导致了,如果暴露出去,一般情况下我们是不能更改的,因为如果更改了势必涉及外围系统的改造,所以我们是不能像本例中那样重构代码的。如果我们内部再建一套领域模型,和暴露给外围系统的VO区分开,代价很大。
4.如果不去重构暴露出去的领域模型,也许我们可以重构每个组件,但我们的组件是按照java的面向接口编程的,如果把一个方法提取到另外一个类中,接口层和实现层都需要加一个方法,这样值得吗?
5.书上的理论只能是理论,肯定会和我们的实际有所出入,不能完全按书上的理论来,要找到适合本系统本业务的合适的重构方法。
附上中午重构后的代码