On Sat, Dec 27, 2008 at 12:35 PM, Larry Garfield <larry@xxxxxxxxxxxxxxxx>wrote: > On Saturday 27 December 2008 2:49:22 am Nathan Nobbe wrote: > > > > Thanks, Nathan. Unfortunately, what you describe is impossible. It > > > requires > > > me to know all the possible decorators ahead of time and implement the > > > interface for each in each decorator, at which point I've gotten no > > > benefit at > > > all over just putting everything in the original base class in the > first > > > place. > > > That defeats the purpose of decorators if I can't come up with a new > one > > > a month from now and not have to modify any of the existing code. > > > > i see it more on a need-to-expose basis. for example, why not, when > > presented w/ the current problem, just expose, Baz::doThings() now, b/c > you > > know you need it in Baz instances ? later if you find theres another > > method thats in Bar that isnt yet exposed, you just go in and add a > similar > > wrapper for it in Baz at that time. this is a typical flow in a layered > > architecture in my experience; often times controllers are revised to > > expose a new entry point for something on the backend that previously was > > unavailble from the front end, just as an example. > > Because this is for a shipping application, not an in-house app where a > month > from now I can go back and adjust the interface for every class. (It's > open > source, but still has a stable release version.) I need to be able to add > additional wrapping decorators *without* any modifications to the > underlying > object or its interfaces. then you can expose all methods from the underlying layer in the first place (which is basically what happens w/ inheritence, as i mentioned earlier). also, how bad will it be when a month from now you have to make some adjustments to the code? more than likely after the first cut, you may have to change something in more than one layer, but it should be minimal as long as you arent making any major overhauls to the code. you add or change one method in a lower, layer so you need to change it in another place, one layer above, i dont see that being so bad. what you are worried about is the classic case martin fowler put forth, which is a short coming of a layered architecture, namely, in the worst case scenario, a modification at the lowest layer requires modifications to each successive layer. > As I said, the interface problem is solvable by having explicit delegating > methods in the base decorator class and then only using __call() for nested > decorators, which will be a much much smaller portion of the time. It's > the > performance cost of __call() and the extra call stack layers that are my > concern at the moment. there is one semi-micro optimization w/ __call(), and that is to use a variable function rather than call_user_func*. however, as you surely already know, this only works iff you know the number of parameters that need to be passed intot the function which is being wrapped. something like this, function __call($method, $args) { return $this->foo->$method($args[0], $args[1]); } the performance hit from __call() is just the price for a highly dynamic system; but you can have a faster system, at the slight risk of carpel-tunnel :) -nathan