Caching Design Patterns
Archive - Originally posted on "The Horse's Mouth" - 2012-08-20 10:57:38 - Graham Ellis
Scenario: John Smith checks out of room 4 at 8 a.m. on Thursday, and looking at our booking system, we see that the room's not been booked out again until Saturday evening, as a twin room, for Deborah Williams and Nancy Walker who are coming to Melksham to attend a WRAF reunion that evening at Melksham Assembly hall.
Quandry: Do we remake bedroom 4 into a lettable double room as soon as John checks out (a double is its most common configuration), or do we leave it unmade and prepare it just-in-time for use on Saturday? By making it up straight away, we run the risk of generating needless work for ourselves. But by leaving it, we run the risk of turning away "walk in" business if people show up at the door looking for a room that's immediately available for them.
The same quandry applies when you're programming using objects. When you construct an object, you'll typically store a number of data values (commonly known as properties or attributes) concerning the object, and later on you'll want to extract information / results based on that data. The quandry - Do you calculate the various results / extra information as you store the data, or do you wait until it's required later on?
The initial answer to this quandry is to take a look at the metrics of the likely use of the objects. If you're going to be creating thousands of objects, but only calling back for a few results from a small number of them, you'll want to wait until the answers are required. But on the other hand, if you're likely to create just a few objects, and then keep calling up the same results many times over, you should calculate as the objects are set up if you want to be efficient.
This initial answer is, however, simplistic. In reallity you won't know which way the balance will tip - especially if your class is going to be used by multiple applications - and the initial attribute values may get changed during the lifetime of an object, rendering the results of the calculations out-of-date (i.e. wrong) if you did them early. A good solution to this is a caching deign pattern.
A caching design pattern works like this:
1. As you create (construct) your object, you set a property that we'll call "cached" to 0 or false, and you do NOT do any result calculations.
2. When you call up a result later on through an accessor, you check if the cached value is 0 / false
• if it IS zero, you do the calculations, store the results into further variables in the object and set cached to 1 / true
• if it is 1, you simply return the values that were previously stored.
The caching design pattern has the further advantage that you can simply set the cached value to 0 / false if you change an attribute value during the life of the object, thus forcing a recalculation next time a result is called for. It've very neat and efficient.
Here's an example in PHP ... the constructor:
function __construct($name,$age,$factor,$breed) {
$this->name = $name;
$this->years = $age;
this->factor = $factor;
$this->breed = $breed;
$this->cached = 0;
}
and an accessor:
function geteffage() {
if (! $this->cached) {
$this->effing = $age * $factor;
$this->cached = 1;
}
return $this->effing;
}
Full source code of this example: [here]. Picture illustration this article - bedroom 4 at Well House Manor, which is open for public bookings if you fance a weekend away in Wiltshire