Vercoutere Vercoutere - 1 month ago 11
PHP Question

What is a good design pattern to avoid recalculations or double queries during a request?

When working with web based applications, usually query results (or the results of complex calculations that require substantial computing power) that don't change frequently would be cached in memory, or in a file based data store.
When these results are likely to change for every request, but are consumed by a number of classes in your application, what would be the best way to go about caching this information for the duration of your request while keeping things SOLID?

The most straight forward solution I see, and what I'm implementing right now, is for every such instance checking if the result has already been calculated/retrieved, and if not, calculating it and storing it in a variable.

public function getSomething()
{
if( ! isset($this->something) )
{
$this->something = $this->calculateSomething();
}

return $this->something;
}


The problems I see with this approach are as follows:


  • I have to make sure that everywhere I require "something", I have access to the same object instance (or I could use static variables which would be even worse). This can be achieved by using dependency injection and making sure that every time I request an instance from that class, the same one is returned, but somehow I can't help but feel I am applying an okay solution to the wrong problem. Eventually my app will be filled with specific instance dependencies. I'm not even really sure if this is a bad thing or not, feel free to correct me.

  • My classes will be filled with these if statements that are all essentially doing the same thing. (checking if a variable has been set, and if not, setting it, and then return said variable.) Yikes!



I have spent the night looking for a better solution, but could not come up with anything but caching results for one request only (using the decorator pattern to keep my classes clean), which also felt wrong.

What would be an elegant way to solve this common problem and is there a known design pattern that I could implement to do so?

Answer

I seem to have found the answer to my own question.

The technique (or pattern, if you want to call it that) is called memoization.

This article by Edd Mann provides a good practical example on how one could implement it:

http://eddmann.com/posts/implementing-and-using-memoization-in-php/

The code in this example is procedural but can easily be adapted for use in an object oriented environment.

All in all this is a pretty simple technique that could boost performance quite a bit in certain scenarios. I'm certainly glad I now have a word I can use when trying to explain this to someone else! :-)