有时候你会遇到一系列复杂的表达式连续运算的时候,这个时候你可能根本招架不住如此长或者是如此复杂的长函数。这个时候你可以通过引用临时变量来储存他们的结果,将这些长函数的结果分成一个个临时变量来让函数清晰化。但在这里,我的想法与作者的想法是一样的,我会更倾向于去用Extract Method去将复杂函数弄清晰,而尽量不去Introduce Explaning Vaiable,因为Extract Method优点很多,除了不增加临时变量增加函数长度之外,他的生命周期也比临时变量来的长,他可以让类中的所有成员都可以用到。除非临时变量让Extract Method很难进行,我才会真正去考虑采用临时变量来解决。
做法一般是用const声明一个临时变量来存储表达式的值,然后对引用表达式结果的地方进行替换。下面看下具体例子
double price() { return m_quantity * m_itemPrice - qMax(0, m_quantity - 500) * m_itemPrice * 0.05 + qMin(m_quantity * m_itemPrice * 0.1, 100.0); }
对于这种长函数我们很难招架,可以进行Introduce Explaning Variable,将m_quanity * m_itemPrice进行提炼,得到如下
double price() { const double basePrice = m_quantity * m_itemPrice; return basePrice - qMax(0, m_quantity - 500) * m_itemPrice * 0.05 + qMin(basePrice * m_itemPrice * 0.1, 100.0); }
我们将basePrice以const double类型声明并且初始化,将所有引用这个表达式结果的地方进行替换,我们可以看到,算法的逻辑清晰了一点。
在这里为了验证我的观点,我们来用下Extract Method来进行重构,看看结果会有何不同。
double price() { return basePrice() - qMax(0, m_quantity - 500) * m_itemPrice * 0.05 + qMin(basePrice() * 0.1, 100.0); } double basePrice() { return m_quantity * m_itemPrice; }
看了运用Extract Method手法的结果,对比之后我们可以发现有前者有以下几个优点:
【1】也是最明显的,Extract Method之后的结果要比Introduce Explaning Variable清晰并且简短的多,其实这也是肯定的,因为后者会引入临时性变量,更加会增加函数的长度。
【2】对于basePrice的提炼,对于price()这个函数来说,Introduce Explaning Variable提炼的临时变量只能在本函数中使用,而Extract Method确可以在类中所有地方都可以使用。
综合来看,Extract Method确实要比Introduce Explaning Variable好用的多,而且我们可以发现,工作量来说两者几乎没什么差别。那么同学会问,那这个重构手法什么时候才会去用?还是有的,就是当Extract Method无法顺利展开的时候,比如临时变量很多不能提炼,这个时候引入临时性变量就容易的多。而且等到代码逻辑清晰之后,你再运用Replace Temp with Query也可以很轻松的去除那些临时性变量。如果你最终要使用Replace Method with Method Object,那么这个手法也就对你提炼提供了价值。