On Sat, Dec 27, 2008 at 12:35 PM, Larry Garfield <la...@garfieldtech.com>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

Reply via email to