Re: [PHP] Decorator with public methods

2008-12-27 Thread Nathan Nobbe
On Sat, Dec 27, 2008 at 12:02 AM, Larry Garfield la...@garfieldtech.comwrote:

 On Friday 26 December 2008 11:06:07 pm Nathan Nobbe wrote:

  to summarize, using your example above, i would most liely add doThings()
  to Baz, or create another decoration interface for doThings() if you plan
  on using the Bar implementation of doThings() in many places,
 
  interface G {
function doThings();
  }
 
  class Bar extends Decorator implements G {
function doThings() {
  // concreate implementation
}
  }
 
  class Baz implements F, G {
// recycle Bar::doThings()
public function doThings() {
  return $this-foo-doThings();
}
public function doOtherThings() {}
  }
 
  i appologize if this response is long winded, but im a big fan of the
  decorator, and ive actually got some pretty slick code in production in
 the
  photobucket code that uses the decorator pattern :D  it took about 2
 months
  to code, and i leraned a lot about some of the practical aspects of
  decroration, specifically within the realm of php.  i know i repeated a
 few
  things there, but i felt it neccessary to better explain myself.
 
  -nathan

 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.

i only pull interfaces into the equation when i what to bring a group of
things together, it certainly isnt necessary to define a second interface,
but i was just trying to highlight doThings() as your example essentailly
had 2 layers of decorators, G(F(Foo)), as i saw it.  from a design
perspective, yes, id probly not define G unless / until i saw a need to join
a group of classes explicitly.

-nathan


Re: [PHP] Decorator with public methods

2008-12-27 Thread Larry Garfield
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.  

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.

-- 
Larry Garfield
la...@garfieldtech.com

-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP] Decorator with public methods

2008-12-27 Thread phphelp -- kbk

On Dec 26, 2008, at 7:53 PM, Larry Garfield wrote:

I have an object to which I want to add behavior (methods).  I  
cannot use
inheritance here because the object is already of a type or subtype  
(vis, I am
already using inheritance for something else), and because I want  
to be able

to add multiple types of behavior at runtime.


If I understand what you are wanting to accomplish, perhaps a simpler  
solution:


Whenever I create a function in a core-level class, I add pre- and  
post- execution language to it. For example:


class foo_bar {

  function foo () {
if (!on_foo()) {
 return FALSE;
}
// normal foo code
// normal foo code
// normal foo code
// normal foo code
// normal foo code
if (!more_foo()) {
 return FALSE;
}
  }

  function on_foo() {
return TRUE;
  }

  function more_foo() {
return TRUE;
  }
}

-- then in the child class:
class child_bar extends foo_bar {

 function on_foo() {
  // runtime code
  // runtime code
  // runtime code
  // runtime code
  return TRUE; // (or FALSE)
 }
}

Ken

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP] Decorator with public methods

2008-12-27 Thread Nathan Nobbe
On Sat, Dec 27, 2008 at 12:56 PM, phphelp -- kbk phph...@comcast.netwrote:

 On Dec 26, 2008, at 7:53 PM, Larry Garfield wrote:

  I have an object to which I want to add behavior (methods).  I cannot use
 inheritance here because the object is already of a type or subtype (vis,
 I am
 already using inheritance for something else), and because I want to be
 able
 to add multiple types of behavior at runtime.


 If I understand what you are wanting to accomplish, perhaps a simpler
 solution:

 Whenever I create a function in a core-level class, I add pre- and post-
 execution language to it. For example:

 class foo_bar {

  function foo () {
if (!on_foo()) {
 return FALSE;
}
// normal foo code
// normal foo code
// normal foo code
// normal foo code
// normal foo code
if (!more_foo()) {
 return FALSE;
}
  }

  function on_foo() {
return TRUE;
  }

  function more_foo() {
return TRUE;
  }
 }

 -- then in the child class:
 class child_bar extends foo_bar {

  function on_foo() {
  // runtime code
  // runtime code
  // runtime code
  // runtime code
  return TRUE; // (or FALSE)
  }
 }


more commonly referred to as  the template method.

-nathan


Re: [PHP] Decorator with public methods

2008-12-27 Thread Nathan Nobbe
On Sat, Dec 27, 2008 at 12:35 PM, Larry Garfield la...@garfieldtech.comwrote:

 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


[PHP] Decorator with public methods

2008-12-26 Thread Larry Garfield
Excuse me a moment while I delve into complex OO. :-)

I have an object to which I want to add behavior (methods).  I cannot use 
inheritance here because the object is already of a type or subtype (vis, I am 
already using inheritance for something else), and because I want to be able 
to add multiple types of behavior at runtime.  The normal OO response to this 
situation is the Decorator pattern.



interface F {
  function doStuff();
}

class Foo {
  function doStuff() { ... }
}

class Decorator implements F {
  protected $foo;

  function __construct(Foo $foo) {
$this-foo = $foo;
  }

  function doStuff() {
$this-foo-doStuff();
  }
}

class Bar extends Decorator {
  function doThings() { ... }
}

$f = new Foo();

$b = new Bar($f);
$b-doStuff();
$b-doThings();



OK, great, that's wonderful.  You can also nest such decorators indefinitely, 
provided that they only override methods from Foo and change its behavior, 
then pass on up the chain.  Neat.  What you cannot do, however, is nest 
decorators that have public methods.  That is:



class Baz extends Decorator {
  function doOtherThings();
}

$f = new Baz(new Bar(new Foo));
$f-doOtherThings(); // Works.
$f-doStuff(); // Works.
$f-doThings(); // Fail.



Now, PHP does have a loophole around this problem in the form of __call().  
Specifically, instead of Decorator wrapping each method of F/Foo directly it 
implements __call():


class Decorator {
  protected $foo;

  function __construct(Foo $foo) {
$this-foo = $foo;
  }

  function __call($method, $args) {
return call_user_func_array(array($this-foo, $method), $args);
  }
}


That should work and allow the code snippet above to run, but it has two 
significant problems:

1) Because Decorator does not directly implement F, you cannot use type 
hinting.

2) __call() and call_user_func_array() are both fairly slow operations, and 
stacking them then becomes a nightmare for performance.

#1 can largely be solved by both directly implementing F *and* implementing 
__call(), but we're still left with the performance problems of #2.  While for 
some uses cases that is OK, it can add up to unpleasant microseconds lost.

Can anyone suggest an alternate solution that has less of a performance hit?

-- 
Larry Garfield
la...@garfieldtech.com

-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP] Decorator with public methods

2008-12-26 Thread Nathan Nobbe
On Fri, Dec 26, 2008 at 6:53 PM, Larry Garfield la...@garfieldtech.comwrote:

 Excuse me a moment while I delve into complex OO. :-)

 I have an object to which I want to add behavior (methods).  I cannot use
 inheritance here because the object is already of a type or subtype (vis, I
 am
 already using inheritance for something else), and because I want to be
 able
 to add multiple types of behavior at runtime.  The normal OO response to
 this
 situation is the Decorator pattern.

 

 interface F {
  function doStuff();
 }

 class Foo {
  function doStuff() { ... }
 }

 class Decorator implements F {
  protected $foo;

  function __construct(Foo $foo) {
$this-foo = $foo;
  }

  function doStuff() {
$this-foo-doStuff();
  }
 }

 class Bar extends Decorator {
  function doThings() { ... }
 }

 $f = new Foo();

 $b = new Bar($f);
 $b-doStuff();
 $b-doThings();

 

 OK, great, that's wonderful.  You can also nest such decorators
 indefinitely,
 provided that they only override methods from Foo and change its behavior,
 then pass on up the chain.  Neat.  What you cannot do, however, is nest
 decorators that have public methods.  That is:

 

 class Baz extends Decorator {
  function doOtherThings();
 }

 $f = new Baz(new Bar(new Foo));
 $f-doOtherThings(); // Works.
 $f-doStuff(); // Works.
 $f-doThings(); // Fail.

 

 Now, PHP does have a loophole around this problem in the form of __call().
 Specifically, instead of Decorator wrapping each method of F/Foo directly
 it
 implements __call():

 
 class Decorator {
  protected $foo;

  function __construct(Foo $foo) {
$this-foo = $foo;
  }

  function __call($method, $args) {
return call_user_func_array(array($this-foo, $method), $args);
  }
 }
 

 That should work and allow the code snippet above to run, but it has two
 significant problems:

 1) Because Decorator does not directly implement F, you cannot use type
 hinting.

 2) __call() and call_user_func_array() are both fairly slow operations, and
 stacking them then becomes a nightmare for performance.

 #1 can largely be solved by both directly implementing F *and* implementing
 __call(), but we're still left with the performance problems of #2.  While
 for
 some uses cases that is OK, it can add up to unpleasant microseconds lost.

 Can anyone suggest an alternate solution that has less of a performance
 hit?


the main drawback to decoration vs inheritance is the fact that code is not
essentially 'written for you', which results in lots of boilerplate code in
decorators, in my experience.  what that amounts to, is if you have 10
methods, whereby you only want to alter one of them in a decorator, then w/
decoration youve got 9 additional methods of crappy boilerplate code to
write, that you wouldnt have to when extending instead.

what is really irritating about the php __call() implementation is that
interfaces are not implemented by it.  i think this is pretty silly (there
may be a solid reason the internals people could mention).  what i mean is,
intuitively, i would expect

class A implements B {
  public function __call() {}
}

to work, no matter what B declares.  but it doesnt, WEAK, *cough* *cough*..

*sigh* sadly, i think the best solution is just to add bolierplate code in
your decorators, such that deocration methods explicitly implement the
interrface w/ each successive layer, and not incur the performance overhead
of __call().  essentially this is what the language would do for you when
extending something.  i rarely put methods all on one line elsewhere, but
when decorating ill just end up doing something like this

/* these are here just to implement interface F */
function doStuff() { return $this-doStuff(); }

another alternative is to really buy into the whole 'dynamic' thing, and
forget about the interface, roll w/ __call() and take the performance hit,
which is more akin to something like youd see in javascript.  personally i
like to use a medly of the two.

i never did much with it, but i suspect C++ templates make decoration nearly
as simple as inheritence, and avoid performace overhead of something like
__call().  which brings me to the third option, only really for the truely
brave php programmer.  templating php w/ php; its often done in code
generation systems, like propel and other orm's, but basically, you'd have a
template w/ skeletons for all the methods and then youd have to run some
sort of generation script in order to create concreate classes for actual
use.  esoteric, and perhaps a little ugly (editors dont really work 'right'
when templating php w/ php =/), but the technique is very powerful.

to summarize, using your example above, i would most liely add doThings() to
Baz, or create another decoration interface for doThings() if you plan on
using the Bar implementation of doThings() in many places,

interface G {
  function 

Re: [PHP] Decorator with public methods

2008-12-26 Thread Larry Garfield
On Friday 26 December 2008 11:06:07 pm Nathan Nobbe wrote:

 to summarize, using your example above, i would most liely add doThings()
 to Baz, or create another decoration interface for doThings() if you plan
 on using the Bar implementation of doThings() in many places,

 interface G {
   function doThings();
 }

 class Bar extends Decorator implements G {
   function doThings() {
 // concreate implementation
   }
 }

 class Baz implements F, G {
   // recycle Bar::doThings()
   public function doThings() {
 return $this-foo-doThings();
   }
   public function doOtherThings() {}
 }

 i appologize if this response is long winded, but im a big fan of the
 decorator, and ive actually got some pretty slick code in production in the
 photobucket code that uses the decorator pattern :D  it took about 2 months
 to code, and i leraned a lot about some of the practical aspects of
 decroration, specifically within the realm of php.  i know i repeated a few
 things there, but i felt it neccessary to better explain myself.

 -nathan

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.

-- 
Larry Garfield
la...@garfieldtech.com

-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php