Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.

Refactoring Perl #5 - Introduce Explaining Variable

by agianni (Hermit)
on Aug 02, 2007 at 18:21 UTC ( [id://630355] : perlmeditation . print w/replies, xml ) Need Help??

You have a complicated expression.

Put the result of the expression, or parts of the expression, in a temporary variable with a name that explains the purpose.

(Fowler, p. 124)

This refactoring pattern proves that context is the key refactoring decisions as it presents the exact opposite of the technique suggested in Inline Temp. Here's what it looks like using List::Util qw( min max ):

sub price{ my $self = shift; # price is base price - quantity discount + shipping return $self->{_quantity} * $self->{_item_price} - max( 0, $self->{_quantity} - 500) * $self->{_item_price} * 0.05 + min( $self->{_quantity} * $self->{_item_price} * 0.1, 100.0); }


sub price{ my $self = shift; my $base_price = $self->{_quantity} * $self->{_item_price}; my $quantity_discount = max( 0, $self->{_quantity} - 500) * $self->{_item_price} * 0.05; my $shipping = min( $self->{_quantity} * $self->{_item_price} * 0.1, 100.0); return $base_price - $quantity_discount + $shipping; }

Get the code

Interestingly enough, Fowler immediately follows this example with the following disclaimer:
For this example, I usually wouldn't have done the explaining temps; I would prefer to do that with Extract Method (p. 126)

and he goes on to show the refactoring using that technique. Fowler suggests that the appropriate time to use this technique is when "Extract Method is more effort" (p. 127). Obviously it's up to the programmer to decide what "more effort" is, but in my mind it'll be much of the time. In other words, this will generally be a better option than Extract Method unless the temps would be useful if shared through a method.

Another nice side effect, if not one of the primary intended effects of this technique is that it makes your code self-documenting. The comment at the top of the original code is unnecessary in the refactored version, as the last line essentially says the same thing explicitly in Perl.

perl -e 'split//,q{john hurl, pest caretaker}and(map{print @_[$_]}(joi +n(q{},map{sprintf(qq{%010u},$_)}(2**2*307*4993,5*101*641*5261,7*59*79 +*36997,13*17*71*45131,3**2*67*89*167*181))=~/\d{2}/g));'