Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Avoiding conditionals in lazy loading

Just to clarify, I mean something like:

class foon {
   private $barn = null;

   public function getBarn() {
      if (is_null($this->barn)) {
         $this->barn = getBarnImpl();
      }
      return $this->barn;
   }
}

This is especially nice when you don't always need getBarn, and getBarn is particularly expensive (e.g. has a DB call). Is there any way to avoid the conditional? This takes up a lot of space, looks ugly, and seeing conditionals disappear is always nice. Is there some other paradigm to handle this lazy loading that I just can't see?

like image 516
Explosion Pills Avatar asked Jan 05 '12 22:01

Explosion Pills


2 Answers

By using php's __call() magic method, we can easily write a decorator object that intercepts all method calls, and caches the return values.

One time I did something like this:

class MethodReturnValueCache {
   protected $vals = array();
   protected $obj;
   function __construct($obj) {
       $this->obj = $obj;
   }
   function __call($meth, $args) {
       if (!array_key_exists($meth, $this->vals)) {
           $this->vals[$meth] = call_user_func_array(array($this->obj, $meth), $args);
       }
       return $this->vals[$meth];
   }
}

then

$cachedFoon = new MethodReturnValueCache(new foon);
$cachedFoon->getBarn();
like image 172
goat Avatar answered Sep 28 '22 05:09

goat


I've wondered this from time to time, but I certainly can't think of one. Unless you want to create a single function to handle this with arrays and reflective property lookups.

like image 29
Lightness Races in Orbit Avatar answered Sep 28 '22 05:09

Lightness Races in Orbit