debuggable

 
Contact Us
 

Composing Methods: Introduce Explaining Variable

Posted on 2/7/07 by Tim Koschützki

Introduce Explaining Variable

When you have a complicated expression that clutters up your code, introduce temporary variables for parts of the expression so the expression itself is readable again.

Motivation

Expressions can become very complex and hard to read. In such a circumstance temporary variables can be very helpful to maintain the readability of your code.

Introduce Explaining Variable is particularly useful with long if-statements. You can take each condition, introduce an explaining variable and the conditional logic will read very well.
Another occasion is a long algorithmn where each step in the calculation can be explained with a well-named temporary variable.

If you ask me you should prefer Extract Method if you can, because more smaller methods are usually more readable and (re-)usable. However, there are times when Extract method doesn't work, because you the code is too cluttered up. In such a case you should use Introduce Explaining Variable
to see what's going in the code. Then you can decide whether Extract Method is the way to go.

Mechanics

The mechanics of Introduce Explaining Variable are very simple:

  1. Declare a temporary variable and set it to the result of a part of the complex expression.
  2. Replace the result part of the expression with your new temp.
  3. Repeat for other parts of the expression.

Example Code

Okay we start with a calculation for a fictive price of an item. It could look something along the lines of the following:

function price() {
  // price is base price - quantity discount + extra fee
  return $this->quantity * $this->item_price -
    max(0, $this->quantity - 200) * $this->item_price * 0.08 +
    min($this->quantity * $this->item_price * 0.1, 100.0);
}

You probably agree it's very hard to read. We are in dare need of a comment to maintain readability. Without the comment, not only
your colleagues would get lost in the code, but so would you. :) We deicde we can introduce a temp for the base price to start things off:

function price() {
  // price is base price - quantity discount + extra fee
  $basePrice = $this->quantity * $this->item_price;
  return  $basePrice -
    max(0, $this->quantity - 200) * $this->item_price * 0.08 +
    min($basePrice * 0.1, 100.0);
}

Cool, a bit better so far. Now let's go for the quantity discount:

function price() {
  // price is base price - quantity discount + extra fee
  $basePrice = $this->quantity * $this->item_price;
  $quantityDiscount = max(0, $this->quantity - 200) * $this->item_price * 0.08;
  return  $basePrice - $quantityDiscount + min($basePrice * 0.1, 100.0);
}

Finally, the extra fee (whatever it is, it is evil:p):

function price() {
  $basePrice = $this->quantity * $this->item_price;
  $quantityDiscount = max(0, $this->quantity - 200) * $this->item_price * 0.08;
  $extraFee = min($basePrice * 0.1, 100.0);
  return  $basePrice - $quantityDiscount + $extraFee;
}

Notice that with our last refactoring the code speaks for itself and we should remove the comment altogether, as otherwise it would be
Duplicate knowledge.

We could have gone for Extract Method as well,
because small methods for all parts of the price expression would be very neat in an object environment. Why? Because they would be visible to all other methods of the class and can be used there. Initially, they would be private,
but you can always relax that later to make them visible to other objects as well.

Here is what this computation would look like with Extract Method:

function price() {
  return  $this->basePrice() - $this->quantityDiscount() + $this->extraFee();
}

function basePrice() {
  return $this->quantity * $this->item_price;
}

function quantityDiscount() {
  return max(0, $this->quantity - 200) * $this->item_price * 0.08;
}

function extraFee() {
  return min($this->basePrice() * 0.1, 100.0);
}

Looking good yes? For this example Extract method is indeed better, but I couldn't think of anything better to explain Introduce Explaining Variable to you. :) Perhaps some kind of conditional logic to check whether we are on IE or Mozilla would have been nice? Argh, too bad. :)

Cheers!

 
&nsbp;

You can skip to the end and add a comment.

[...] the PHP-Coding_Practices.com site, Tim Koschuetzki has posted an interesting suggestion for developers working with long expressions to make thing simpler - substituting temporary [...]

This post is too old. We do not allow comments here anymore in order to fight spam. If you have real feedback or questions for the post, please contact us.