I have this calculator class that performs business calculations distributed among small methods. I'm split between choosing to save the state, or just calculate everytime a method is called. Am I doing unnecessary micro-optimization or not?

class Bill
{
    private $value1;
    private $rate1;

    private $value2;
    private $rate2;

    // ...code here

    function one ()
    {
        return $this->value1 * $this->rate1;
    }

    function two ()
    {
        return $this->value2 * $this->rate2;
    }

    funciton oneAndTwo ()
    {
        return $this->one() + $this->two();
    }

    function modifyOneAndTwo ()
    {
        return $this->oneAndTwo() * 2;
    }

    // ...more code here

    function save ()
    {
        $one = $this->one();
        $two = $this->two();
        $oneAndTwo = $this->oneAndTwo();
        $modifiedOneAndTwo = $this->modifyOneAndTwo();
        //save all values above to database
    }
}

Notice that everytime I call save() it would eventually call one() and two() thrice, and oneAndTwo() twice. This would be my first "real" application for a real business, and so I'm clueless when it comes to optimization. I've read some articles, but I didn't find any pertaining to these kind of scenarios.

This could be interesting …
Why could be characterized in any way as optimization (even micro as you said) ? .
You have private methods with no setters and no getters … why ? .
In the save method you said that you are saving those properties in db (how ? ) … ok what are you doing then with those values ?

Sorry, I think I inverted the question. The code above is "unoptimized" and I just left out the save to database part, but it's just a normal database operation, form SQL, send to database, etc.

Those methods are all public and they are called in other parts of the program, mostly for display. I'm thinking of just adding $one, $two, $oneAndTwo$, and $modoneAndTwo as class variables and save everytime a method is called, but I'm thinking if that would be unncessary microoptimization. I have quite a lot of these cases in other classes.

I thing I understood what you are asking and I will give you an answer based on an example.

Let’s suppose that we have a product object. It has price and a discount rate. When we want to take the discount price then it should be calculated using price and the discount rate. In the first scenario we do nothing for micro – optimization and the value of discount price is calculated every time we call it. In the second scenario we have a private property $discountPrice that resets every time the price or the discount rate is set. In that way when we get the discount price the calculation has already be done.

Here is the code for these two scenarios.

SCENARIO 1

<?php
/**
 * This is an example of a product object that has a behavior getDiscountPrice 
 * which returns value depend on other properties values 
 * ($price, $discountRate) with no optimization. 
 */
class Product
{
  private $price; 
  private $discountRate; 

  public function setPrice($price)
  {
    $this->price = $price; 
  }

  public function setDiscountRate($discountRate)
  {
    $this->discountRate = $discountRate; 
  }

  public function getPrice()
  {
    return $this->price; 
  }

  public function getDiscountRate()
  {
    return $this->discountRate; 
  }

  /**
   *    Lets assume that the discount price is the 
   *  price – discount rate * price and all that rounded in the second digit. 
   */
  public function getDiscountPrice()
  {
    return round($this->price - ($this->price * $this->discountRate),2); 
  }

}

// TESTING FIRST SCENARIO 
$startTime = microtime(true);
$product = new Product(); 
$product->setPrice(32.15);
$product->setDiscountRate(0.20);
echo "<br/>FIRST SCENARIO<br/>";
var_dump($product->getDiscountPrice()); 
echo "<br/>"; 
for($i=0; $i<10000; $i++)
{
  $test = $product->getDiscountPrice();
}
$endTime = microtime(true);
$scerarioTime = $endTime - $startTime;
echo "Getting 10.000 times the discount Price took ".$scerarioTime." seconds"
?>

SCENARIO 2

<?php
/**
 * 
 * Here we have a form of micro - optimization 
 */
class Product
{
  private $price; 
  private $discountRate; 
  private $discountPrice; 


  public function setPrice($price)
  {
    $this->price = $price; 
    $this->resetDiscountPrice();
  }

  public function setDiscountRate($discountRate)
  {
    $this->discountRate = $discountRate; 
    $this->resetDiscountPrice();
  }

  public function getPrice()
  {
    return $this->price; 
  }

  public function getDiscountRate()
  {
    return $this->discountRate; 
  }

  private function resetDiscountPrice()
  {
    if(isset($this->price) && isset($this->discountRate))
    {
      $this->discountPrice = round($this->price - ($this->price * $this->discountRate),2);
    }
  }

  public function getDiscountPrice()
  {
    return $this->discountPrice;
  }

}

// TESTING SECOND SCENARIO 
$startTime = microtime(true);
$product = new Product(); 
$product->setPrice(32.15);
$product->setDiscountRate(0.20);
echo "<br/>SECOND SCENARIO<br/>";
var_dump($product->getDiscountPrice()); 
echo "<br/>"; 
for($i=0; $i<10000; $i++)
{
  $test = $product->getDiscountPrice();
}
$endTime = microtime(true);
$scerarioTime = $endTime - $startTime;
echo "Getting 10.000 times the discount Price took ".$scerarioTime." seconds"


?>

Result in my server (the average of 20 times)
SCENARIO 1: 0.03096 Seconds
SCENARIO 2: 0.01972 Seconds

And my opinion over it:

Yes the second scenario is almost 0.63 times faster than the first one so it could be called micro – optimization .

But is it realistic to retrieve 10.000 times a property in a program; Even if it where and also where the coding practice for all such occasions in a program what you are really gaining (less then a 0.012 Second). The important thing is that the code is clean , easy to understand and therefore maintainable. If anybody starts making his code more complicated than he should gain more than that and of course writing a lot of comments explaining what he is doing.

My conclusion is that in such simple operations micro-optimization of such form has no meaning. If the logic was really complicated and more over required data retrieval from a db then yes would have a meaning.

Even then it is cleaner to have a plain PHP object with properties , getters and setters and few extra behavior with no business logic on them , and to set that property that is based in a complicated business logic from a layer above in the business model logic (perhaps from an assigner class).

Thanks for the comprehensive answer, I think I'll just forget the simple micro-optimizations. The additional layer sounds good, but I think I'll just reserve that if I'm ahead of schedule.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.