Refactoring 3: Replace Temp with Query


Posted in: refactoring | Save to del.icio.us | Twit This! 5 Jun 2009

Temporary variables are a integral part of any code. But a splattering of the same all over can make your code hard to understand or modify. Replace temp with query is a refactoring method where you replace temp variable expressions with methods. This method is often also required before you use the Extract Method refactoring.

A simple example
Take for example the following code with a Item class that exposes a single function get_price. ‘get_price’ returns the total amount of the items. I’ve hard coded the quantity and price variables to simplify the code so that we can focus on the essential element. It contains two temp variables - $base_price and $discount_factor - they are a perfect candidate for refactoring as they also do not modify any other objects.

 
class Item {
 
     private $_quantity = 100;
     private $_item_price = 29;
 
     public function get_price() {
 
          $base_price = $this->_quantity * $this->_item_price;
          $discount_factor = 0;
 
          if($base_price > 1000) {
               $discount_factor = 0.95;
          } else {
               $discount_factor = 0.98;
          }
 
          return ($base_price * $discount_factor);
     }
 
}
 
$item = new Item();
echo $item->get_price();

Now all we have to do is convert the temp variables right side expression into methods and use the same in get_price. To avoid introducing errors during refactoring we convert one temp variable at a time and test it before proceeding further. First we convert $base_price temp variable to a function.

 
class Item {
 
     private $_quantity = 100;
     private $_item_price = 29;
 
     private function base_price() {
          return ($this->_quantity * $this->_item_price);
     }
 
     public function get_price() {
          $base_price = $this->base_price();
          $discount_factor = 0;
 
          if($base_price > 1000) {
               $discount_factor = 0.95;
          } else {
               $discount_factor = 0.98;
          }
 
          return ($base_price * $discount_factor);
     }
 
}

Next we convert the $discount_factor variable expression to a function.

 
class Item {
 
     private $_quantity = 100;
     private $_item_price = 29;
 
     private function base_price() {
          return ($this->_quantity * $this->_item_price);
     }
 
     private function discount_factor() {
          if($this->base_price() > 1000)
               return 0.95;
          else
               return 0.98;
     }
 
     public function get_price() {
          $base_price = $this->base_price();
          $discount_factor = $this->discount_factor();
 
          return ($base_price * $discount_factor);
     }
 
}

Finally we eliminate the temp variables in the get_price function.

 
public function get_price() {
          return ($this->base_price() * $this->discount_factor());
     }

Using Replace Temp with Query is easier when the temp variables are assigned only once in a block of code, and also if they do not cause any side effects i.e the temp variables statement does not modify any object.
Note that in the above example before refactoring the $base_price and $discount_factor variables were assigned to only once each. Multiple assignments can make it a little trickier to use the current refactoring method.

Conclusion
This seems a long way to go to eliminate temporary variables, but besides clean code the other main advantage of using the above method is that now the base_price and the discount_factor methods are available to other members of the class to use.




Share this post

Share on Facebook
Share on Twitter
Share on StumbleUpon
Share on Delicious
Share on Digg
Share on Technorati
Share on Reddit
Feeds RSS Subscribe to site Feed

Other related posts



5 Responses

1

Raphaël Dehousse

June 8th, 2009 at 6:29 am

Hello,

Ok for the pattern but in your example, I would rather write :

private function discount_factor($base_price) {
if($base_price > 1000)
return 0.95;
else
return 0.98;
}

public function get_price() {
$base_price = $this->base_price();

return ($base_price * $this->discount_factor($base_price));
}

You will save one function call and like this, you can use discount_factor on other price than the base one of your class

Thanks for your articles !

Cheers,

Raphaël

2

Jon

June 10th, 2009 at 5:34 am

Thanks for this, great refactoring articles!

3

Refactoring 3: Replace Temp with Query : CodeDiesel

July 4th, 2009 at 12:34 am

[...] the original post here: Refactoring 3: Replace Temp with Query : CodeDiesel Share and [...]

4

Favio

August 7th, 2009 at 1:26 am

What do you think about writing the discount_factor function as:

private function discount_factor() {
if($this->base_price() > 1000) {
return 0.95;
}
return 0.98;
}

?

Anyway, you have a cool blog. :)

5

mathk

August 18th, 2009 at 12:35 am

I also see a main avantage:
If you ever decide to add a new item with a new way of computing the discount you just have to subclass your item and redefine the dicount_factor() method. Nothing more! :)

Comment Form

Use the html <code> tag to insert small source code snippets

For longer code examples use http://pastie.org/.

Get latest updates by E-mail

About this blog

This site is a digital habitat of Sameer, a freelance web developer working from Pune.More

Recent Comments

  • sameer: My apologies! I'm not conversant with SharePoint. [...]
  • avanthi: Is it possible to automate share point people picker control through selenium. When i record throug [...]
  • sameer: Check to see if the 'IDE > options > format' is set to HTML. [...]
  • sameer: Google strips any newline characters form the text. Although it does accept it with the online trans [...]
  • Arjan: Fiddler is a debugging tool for IE (not Microsoft's Fiddler) [...]
  • Susan Martin: while creating a test for site, command icons on IDE greyed out and do not respond when selected. I [...]
  • Saar: Thanks for this example. helped me a lot. I have 1 problem, I am translating chunks of code, but I [...]
  • sameer: You can add extra GET variables in the options array as below: $pager_options = array( 'mode [...]

  • Users Online

    • 9 Users Online
    • 9 Guests