I have some pattern that works great for me, but that I have some difficulty explaining to fellow programmers. I am looking for some justification or literature reference.
I personally work with PHP, but this would also be applicable to Java, Javascript, C++, and similar languages. Examples will be in PHP or Pseudocode, I hope you can live with this.
The idea is to use a lazy evaluation container for intermediate results, to avoid multiple computation of the same intermediate value.
"Dynamic programming":
http://en.wikipedia.org/wiki/Dynamic_programming
The dynamic programming approach seeks to solve each subproblem only once, thus reducing the number of computations: once the solution to a given subproblem has been computed, it is stored or "memo-ized": the next time the same solution is needed, it is simply looked up
Lazy evaluation container:
class LazyEvaluationContainer {
protected $values = array();
function get($key) {
if (isset($this->values[$key])) {
return $this->values[$key];
}
if (method_exists($this, $key)) {
return $this->values[$key] = $this->$key();
}
throw new Exception("Key $key not supported.");
}
protected function foo() {
// Make sure that bar() runs only once.
return $this->get('bar') + $this->get('bar');
}
protected function bar() {
.. // expensive computation.
}
}
Similar containers are used e.g. as dependency injection containers (DIC).
Details
I usually use some variation of this.
- It is possible to have the actual data methods in a different object than the data computation methods?
- It is possible to have computation methods with parameters, using a cache with a nested array?
- In PHP it is possible to use magic methods (__get() or __call()) for the main retrieval method. In combination with "@property" in the class docblock, this allows type hints for each "virtual" property.
- I often use method names like "get_someValue()", where "someValue" is the actual key, to distinguish from regular methods.
- It is possible to distribute the data computation to more than one object, to get some kind of separation of concerns?
- It is possible to pre-initialize some values?
EDIT: Questions
There is already a nice answer talking about a cute mechanic in Spring @Configuration classes.
To make this more useful and interesting, I extend/clarify the question a bit:
- Is storing intermediate values from dynamic programming a legitimate use case for this?
- What are the best practices to implement this in PHP? Is some of the stuff in "Details" bad and ugly?
If I understand you correctly, this is quite a standard procedure, although, as you rightly admit, associated with DI (or bootstrapping applications).
A concrete, canonical example would be any Spring
@Configuration
class with lazy bean definitions; I think it displays exactly the same behavior as you describe, although the actual code that accomplishes it is hidden from view (and generated behind the scenes). Actual Java code could be like this:Each method marked with
@Bean @Lazy
represents one "resource" that will be created once it is needed (and the method is called) and - no matter how many times it seems that the method is called - the object will only be created once (due to some magic that changes the actual code during loading). So even though it seems that increateOneThing()
is called two times increateOneThing()
, only one call will occur (and that's only after someone tries to callcreateSomeThirdThing()
or callsgetBean(SomeThirdThing.class)
onApplicationContext
).