Refactoring 3: Replace Temp with Query

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.

5 thoughts on “Refactoring 3: Replace Temp with Query

  1. 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. 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. 🙂

  3. 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! 🙂

Comments are closed.