Re: [PHP-DEV] Decorators Revisited

2012-08-15 Thread Andrew Faulds



On 14 August 2012 at 20:58 Stas Malyshev smalys...@sugarcrm.com wrote:

 Hi!

  Simply because your object responds to all the same methods of, for
  example, the FooInterface, does not make it a FooInterface subtype.  It
  just means that in the duck typing sense of the phrase, it can act
  like a FooInterface for people that are not necessarily concerned that
  it's actually not is_a() FooInterface.

 Excellent point here. I have a feeling that with these proposals people
 want to eat a cake and have it too. To have strictly defined typing
 structure enforced by strict parameter checks, instanceof checks, etc.
 and at the same time have the freedom of duck typing. I don't think it's
 going to work well - if you want duck typing, that's one thing, if you
 want class hierarchy, that's another thing. Both are viable models for
 different cases, but I don't see how they can work using the same
 operators and language constructs. They should be distinct.


This is something which bothers me about PHP as it is at the moment. PHP seems
to me like it should be a dynamic language, and it is quite dynamic: no static
typing, has weak typing, you can add instance members at runtime, etc.

However, there has been a trend for adding more... non-dynamic (?) features to
the language. Interfaces for example. Yet you can also duck-type things. I think
PHP risks becoming very unclear as to what the right way to do things is. It
must be confusing to write code that has to deal with both duck-typing and
interfaces. I just think perhaps PHP should decide if it's supposed to be
dynamic or non-dynamic, because just now it looks like a confusing mix of both.
(although I guess duck-typing can be used for interfaces, just not really the
other way round, i.e. if you expect an object of an interface you can't just
pass one implementing the required methods)

Or, if it is going to support both models, it should at least have first-class
support for both. Being able to dynamically modify classes, for instance.

 Now, we could probably make duck typing a bit easier by allowing to
 check if specific object can respond to specific interface. But I'm not
 sure if it's worth the effort - why not just have it implement the
 interface then? In any case, I think duck typing improvement may be a
 good place for proposals, but let's not confuse it with inheritance
 hierarchy.

What if asking for an interface just checked to see if a class implemented the
required types, and implements didn't make the class have that interface, but
just made the compiler error if it didn't implement everything required.

 --
 Stanislav Malyshev, Software Architect
 SugarCRM: http://www.sugarcrm.com/
 (408)454-6900 ext. 227

 --
 PHP Internals - PHP Runtime Development Mailing List
 To unsubscribe, visit: http://www.php.net/unsub.php

--
Andrew Faulds
http://ajf.me/

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Decorators Revisited

2012-08-14 Thread Stas Malyshev
Hi!

 2. Move instanceof to a handler from the current standalone function. Then
 each (pecl level) class could choose its own implementation if it is
 needed. The function could still exist for BC reasons, but would proxy to
 the handler method if it existed... Then, the wrapped class (the additional
 pointer) would only need to live on the objects internal store...

I don't think overriding instanceof is a very good idea. instanceof has
very defined meaning, which implies certain contract between classes and
their clients, and allowing everybody to override it to mean whatever
one likes looks very dangerous to me.

-- 
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Decorators Revisited

2012-08-14 Thread Benjamin Eberlei
On Tue, Aug 14, 2012 at 8:36 AM, Stas Malyshev smalys...@sugarcrm.comwrote:

 Hi!

  2. Move instanceof to a handler from the current standalone function.
 Then
  each (pecl level) class could choose its own implementation if it is
  needed. The function could still exist for BC reasons, but would proxy to
  the handler method if it existed... Then, the wrapped class (the
 additional
  pointer) would only need to live on the objects internal store...

 I don't think overriding instanceof is a very good idea. instanceof has
 very defined meaning, which implies certain contract between classes and
 their clients, and allowing everybody to override it to mean whatever
 one likes looks very dangerous to me.


I think you are excagerating, the proposal is not allowing everybody to
overwrite instanceof it to do whatever. That would be if we could overwrite
the implementation of instanceof in userland.
Instead it simplifies applying the decorator pattern on the language level,
and the instanceof only in this use-case.

@Anthony: Does this handle get_class() as well and all the Reflection APIs?


Re: [PHP-DEV] Decorators Revisited

2012-08-14 Thread Stan Vass
Would this work with methods which take arguments by reference or return by 
reference?


Stan 



--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Decorators Revisited

2012-08-14 Thread Pierre Joye
hi Anthony,

On Sun, Aug 12, 2012 at 8:17 PM, Anthony Ferrara ircmax...@gmail.com wrote:

 What do you think? Is this a route that I should continue down? Or is there
 something fundamental that I'm missing here? I know that Reflection,
 get_interfaces(), etc would need to be updated to account for this.

 Thoughts?

I very much like this idea! And I'm convinced that more
tests/efforts/thoughts should be put into this.

One point I worry about is performance. As of 5.3  5.4, the object
usage performance has been significantly improved. I wonder what would
be the impact of this change on this gain. Did you look at that
already? Surely too early but still good to get an idea or to keep
this parameter in mind:).

Keep the great work!

Cheers,
-- 
Pierre

@pierrejoye | http://blog.thepimp.net | http://www.libgd.org

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Decorators Revisited

2012-08-14 Thread Ralph Schindler
In general, I think it would be nice to have something that does this 
for you, but I am not necessarily a fan of changing the meaning of 
instanceof.



That's a lot of boilerplate for each possible iteration. This is one reason
people like traits so much, as it's easier to just do automated copy/paste
than use the proper patterns.


Couldn't a dynamic trait be a better?  It would work like this:

trait SplDynamicProxyTrait {

  protected $proxyObject;

  // enumerate all public method with the following:
  public function $name($signature) {
return $this-proxyObject::$name($signature);
  }

}

usage would then be the following:

class MyDecorator implements FooInterface {
  use SplDynamicProxyTrait; // compile time code generation
  public function __construct(Foo $foo) {
 $this-proxyObject = $foo;
  }
  // override trait
  public function method2($a) {
if (!$this-hasCache('method2', $a)) {
  $ret = $this-proxyObject-method2($a);
  $this-setCache('method2', $a, $ret);
}
return $this-getCache('method2', $a);
  }
}



So, example code like:

class Foo {}
class Bar extends SplDecorator {}
$b = new Bar(new Foo);
var_dump($b instanceof Foo); // true

It also works with type hints:
function test(Foo $f) {}
test($b);


These would all still work, instanceof would actually be an instanceof 
though.



Now, there's a lot more to do (property cascading, interface validation,
etc), but the initial proof-of-concept is there.



What do you think? Is this a route that I should continue down? Or is there
something fundamental that I'm missing here? I know that Reflection,
get_interfaces(), etc would need to be updated to account for this.

Thoughts?


In the above scenario, we've reused traits and we haven't broken 
instanceof or the liskov principle (which basically your implementation 
does since SplDectorator bypasses all method signature checking until 
runtime).


Thoughts? :)

-ralph


--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Decorators Revisited

2012-08-14 Thread Anthony Ferrara
Ralph,

On Tue, Aug 14, 2012 at 12:49 PM, Ralph Schindler
ra...@ralphschindler.comwrote:

 In general, I think it would be nice to have something that does this for
 you, but I am not necessarily a fan of changing the meaning of instanceof.


  That's a lot of boilerplate for each possible iteration. This is one
 reason
 people like traits so much, as it's easier to just do automated copy/paste
 than use the proper patterns.


 Couldn't a dynamic trait be a better?  It would work like this:

 trait SplDynamicProxyTrait {

   protected $proxyObject;

   // enumerate all public method with the following:
   public function $name($signature) {
 return $this-proxyObject::$name($**signature);
   }

 }

 usage would then be the following:

 class MyDecorator implements FooInterface {
   use SplDynamicProxyTrait; // compile time code generation
   public function __construct(Foo $foo) {
  $this-proxyObject = $foo;
   }
   // override trait

   public function method2($a) {
 if (!$this-hasCache('method2', $a)) {
   $ret = $this-proxyObject-method2($**a);

   $this-setCache('method2', $a, $ret);
 }
 return $this-getCache('method2', $a);
   }
 }


  So, example code like:

 class Foo {}
 class Bar extends SplDecorator {}
 $b = new Bar(new Foo);
 var_dump($b instanceof Foo); // true

 It also works with type hints:
 function test(Foo $f) {}
 test($b);


 These would all still work, instanceof would actually be an instanceof
 though.


  Now, there's a lot more to do (property cascading, interface validation,
 etc), but the initial proof-of-concept is there.


  What do you think? Is this a route that I should continue down? Or is
 there
 something fundamental that I'm missing here? I know that Reflection,
 get_interfaces(), etc would need to be updated to account for this.

 Thoughts?


 In the above scenario, we've reused traits and we haven't broken
 instanceof or the liskov principle (which basically your implementation
 does since SplDectorator bypasses all method signature checking until
 runtime).

 Thoughts? :)

 -ralph


Well, I like it at first glance. There are two main problems that I see
with it:

1. It still requires a separate decorator class for every combination of
interfaces you want to decorate. So, for example if you wanted to decorate
a Foo interface, but sometimes it's used with Iterator as well. Then you'd
need two classes. If there was a third interface, you'd need four separate
classes. Same problem with class bloat minus a lot of the boilerplate.

2. It's still not possible to decorate a typed class. So I can't decorate
PDO without first extending PDO with a user-supplied interface.

And I don't understand how this breaks LSP... We're not extending the
decorated class. In fact, we can add construct time checking to ensure the
original interfaces are all enforced (and even go a step further and ensure
that all method signatures are the same that are overridden). LSP is not a
compile time concern, it's a purely runtime concern (in PHP at least). The
fact that interface contracts are enforced at compile time is nice, but
it's not a strict necessity to enforcing LSP.

Anthony


Re: [PHP-DEV] Decorators Revisited

2012-08-14 Thread Ralph Schindler



Well, I like it at first glance. There are two main problems that I see
with it:

1. It still requires a separate decorator class for every combination of
interfaces you want to decorate. So, for example if you wanted to
decorate a Foo interface, but sometimes it's used with Iterator as well.
Then you'd need two classes. If there was a third interface, you'd need
four separate classes. Same problem with class bloat minus a lot of the
boilerplate.


You'd need a class anyway for your custom logic to live, that custom 
logic is the reason you want a Proxy in the first place.  In your 
example, you want to proxy and object, but for one of the method, 
presumable an expensive method, you want to be able to cache the output 
before needing to go to the actual object.


If Iterator was required for the Foo contract/interface, that would have 
bee in the Foo interface definition as well.


Even in your example, you still have this:

  class Bar extends SplDecorator {}

But what you are really intending is:

  class Bar extends MagicToMakeThisActLikeAnyType {}

Ultimately, the instance you are decorating and decorator itself need to 
be type equivalent.  Meaning the generally accepted understanding of 
is_a() and instanceof constructs need to also apply to the decorator 
object just as it would any other object.



2. It's still not possible to decorate a typed class. So I can't
decorate PDO without first extending PDO with a user-supplied interface.


I don't follow.  What do you mean by a typed class?


And I don't understand how this breaks LSP... We're not extending the
decorated class. In fact, we can add construct time checking to ensure
the original interfaces are all enforced (and even go a step further and


That is where we are going to differ.

Simply because your object responds to all the same methods of, for 
example, the FooInterface, does not make it a FooInterface subtype.  It 
just means that in the duck typing sense of the phrase, it can act 
like a FooInterface for people that are not necessarily concerned that 
it's actually not is_a() FooInterface.


In other words, yes, it will pass all sorts of method_exists() checks, 
but it'd never be able to pass an instanceof, is_a, or is_subclass_of() 
check on FooInterface.



ensure that all method signatures are the same that are overridden). LSP
is not a compile time concern, it's a purely runtime concern (in PHP at


When I say compile time I mean PHP's compile time, in so far as PHP is 
a compile and execute style interpreted language.


The following script demonstrates the enforcement of subtype expectations:

?php
interface Foo { public function bar(); }
class Bar implements Foo { public function bar(array $a) {} }
?

That will produce: PHP Fatal error:  Declaration of Bar::bar() must be 
compatible with that of Foo::bar() in ...


That is an LSP check, and it is done at PHP's compile time.  The rule 
Preconditions cannot be strengthened in a subtype is violated since 
you attempted to add an argument to the bar() method of the Foo contract.



least). The fact that interface contracts are enforced at compile time
is nice, but it's not a strict necessity to enforcing LSP.


Why not do it at compile time? When php is building up its class entry 
table, it should be in its best interest to not have incomplete or 
invalid types in there, right?



But, I do support getting more duck typing facilities in PHP, and 
reusing traits in places where we need more compiler assisted copy/paste 
when boilerplate is cumbersome.


-ralph


--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Decorators Revisited

2012-08-14 Thread Stas Malyshev
Hi!

 Simply because your object responds to all the same methods of, for 
 example, the FooInterface, does not make it a FooInterface subtype.  It 
 just means that in the duck typing sense of the phrase, it can act 
 like a FooInterface for people that are not necessarily concerned that 
 it's actually not is_a() FooInterface.

Excellent point here. I have a feeling that with these proposals people
want to eat a cake and have it too. To have strictly defined typing
structure enforced by strict parameter checks, instanceof checks, etc.
and at the same time have the freedom of duck typing. I don't think it's
going to work well - if you want duck typing, that's one thing, if you
want class hierarchy, that's another thing. Both are viable models for
different cases, but I don't see how they can work using the same
operators and language constructs. They should be distinct.

Now, we could probably make duck typing a bit easier by allowing to
check if specific object can respond to specific interface. But I'm not
sure if it's worth the effort - why not just have it implement the
interface then? In any case, I think duck typing improvement may be a
good place for proposals, but let's not confuse it with inheritance
hierarchy.
-- 
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Decorators Revisited

2012-08-14 Thread Anthony Ferrara
Ralph,

On Tue, Aug 14, 2012 at 3:30 PM, Ralph Schindler
ra...@ralphschindler.comwrote:


  Well, I like it at first glance. There are two main problems that I see
 with it:

 1. It still requires a separate decorator class for every combination of
 interfaces you want to decorate. So, for example if you wanted to
 decorate a Foo interface, but sometimes it's used with Iterator as well.
 Then you'd need two classes. If there was a third interface, you'd need
 four separate classes. Same problem with class bloat minus a lot of the
 boilerplate.


 You'd need a class anyway for your custom logic to live, that custom logic
 is the reason you want a Proxy in the first place.  In your example, you
 want to proxy and object, but for one of the method, presumable an
 expensive method, you want to be able to cache the output before needing to
 go to the actual object.

 If Iterator was required for the Foo contract/interface, that would have
 bee in the Foo interface definition as well.


No, it would be required by the class itself. That's the point. I don't
want to decorate an interface, but an instance. Otherwise it makes
decorating real world classes much more difficult (which was the pain I'm
looking to clean up).


 Even in your example, you still have this:

   class Bar extends SplDecorator {}

 But what you are really intending is:

   class Bar extends MagicToMakeThisActLikeAnyType {}

 Ultimately, the instance you are decorating and decorator itself need to
 be type equivalent.  Meaning the generally accepted understanding of
 is_a() and instanceof constructs need to also apply to the decorator object
 just as it would any other object.


It sounds to me like you haven't tried to use decorators for any complex
logic. Making it type equivalent leads to very vebose code. And a PITA to
write. This is one of the reasons that traits are so heralded. Because
problems that are easy to solve with decorators (in general) are difficult
to solve with PHP, so people wind up writing copy/paste systems (which is
what traits are) to solve them in a more brittle and less flexible manner.

I'm after flexibility in addition to enforcement. They are not opposites.
The whole point of interfaces is not typing, but a contract. There's
nothing stopping you from making an Iterator which uses the valid() class
to do logic. The accepted contract though says what it should do. But
interfaces are only half of that contract. We assume that if you implement
an interface that you're going to abide by the whole contract. But without
interface level preconditions, postconditions and invarients, it's not an
All or nothing approach. By using interfaces I can gain some compile-time
assurance that the contract is met, but only manual review will confirm
this.

What I'm proposing here can be abused. Sure, it can be used to do all sorts
of nasty things. But so can traits. So can eval. So can inheritance. So can
regular expressions. That doesn't mean that they aren't incredibly useful...


  2. It's still not possible to decorate a typed class. So I can't
 decorate PDO without first extending PDO with a user-supplied interface.


 I don't follow.  What do you mean by a typed class?


A class which is checked for directly. There is plenty of user-land code
that uses PDO as a type hint. That means I'd need to extend PDO to add
functionality, thereby rendering decorators useless (and instead causing
all sorts of issue). And even if I wanted to make a new class for my using
to decorate, I'd need to create an interface and class:

interface PDOLike {
}
class MyPDO extends PDO implements PDOLike {
}

That winds up creating really weird coupling and hard to reuse code. So
that means that I either need to depend on my PDO instance, or not be able
to use decorators at all. Not a good tradeoff if you ask me.


  And I don't understand how this breaks LSP... We're not extending the
 decorated class. In fact, we can add construct time checking to ensure
 the original interfaces are all enforced (and even go a step further and


 That is where we are going to differ.

 Simply because your object responds to all the same methods of, for
 example, the FooInterface, does not make it a FooInterface subtype.  It
 just means that in the duck typing sense of the phrase, it can act like a
 FooInterface for people that are not necessarily concerned that it's
 actually not is_a() FooInterface.


But the flip side is true as well. Just because a class implements a
FooInterface doesn't mean it can act like a FooInterface is supposed to.
That's one reason that relying on interfaces alone for that much is a
mistake. It takes review. Or (in other languages) formal contracts to
ensure that the contract is enforced.

And since interfaces in PHP are weak signature based contracts, we can
implement them dynamically without absolutely any break in the contract.
That's why this style system (letting a decorator assume the interfaces of
the parents, as long as the decorator 

Re: [PHP-DEV] Decorators Revisited

2012-08-14 Thread Ralph Schindler

Hey Anthony,

There's a lot here, so I'm only going to address a few things.


It sounds to me like you haven't tried to use decorators for any complex
logic. Making it type equivalent leads to very vebose code. And a PITA


I actually have used both Decorators and Proxies (it's cousin) a number 
of times and some in complex situations (these are all ZF2) 
http://git.io/HdRe6g (Zend\Di), http://git.io/6EGv4Q 
(Zend\ServiceManager), and http://git.io/DhXDFA (Zend\Db Sql 
Abstraction), all that aside ...



to write. This is one of the reasons that traits are so heralded.
Because problems that are easy to solve with decorators (in general) are
difficult to solve with PHP, so people wind up writing copy/paste


If what you're trying to do is decorate an instance of a particular 
concrete type, the basic structure/foundation for creating a Decorator 
(as defined by wikipedia), can be achieved in PHP with about 3 lines of 
code:


class FooDecorator extends Foo {
protected $subject;
public function __construct(Foo $foo) {
$this-subject = $foo;
foreach (get_object_vars($foo) as $n = $v) {
$this-{$n} = $foo-{$n};
}
}
}

At this point, any instance of new Foo is statefully and type equivalent 
to new FooDecorator($foo).  Now, you're free to add in your custom 
decoration logic, overridden methods, additional methods, new 
interfaces, etc.  An instance of FooDecorator can be used an any place 
an instance of Foo would have been used.  i.e., it's bound to the Foo 
context.



Let's get one thing clear here. It's not a LSP check. In that exact
example it is. But in general, it also prevents the LSP valid:

interface foo { public function bar(array $a); }
class Bar implements Foo { public function bar($a); }

That's 100% in compliance with LSP. Yet it's disallowed. The reason is
that interfaces are not primarily a LSP enforcer. They are primarily a
contract enforcer. LSP is a usual side-effect, but it's not a guarantee.


I'll give you this one.

That is an example of contravariance of method arguments, which I'd 
argue should probably be allowed (if it's not that expensive to do so). 
 PHP does not specifically say it or define type sets, but one would 
assume that no type required should mean all types which technically 
might include array.



And I don't need to resort to duck typing for it to work. All I need is
the ability to decorate at will. I'm not talking about nuking the
meaning of the interfaces (as they'd be proxied to). But more just


We're going to have to disagree on the meaning of interfaces. 
Interfaces are a foundational element of a class based type hierarchy. 
If you want Interfaces without them being in an instance type hierarchy, 
I'm not sure what you call that; but it's not an Interface. The 
decisions made in the PHP group around the class type system more 
closely resemble those made by Java and C#.


Concerning your code snippets above.

It sounds like you want to dynamically build classes and methods, on the 
fly, or you want a magical subclass that is free from the current rules 
of is_a, instanceof, etc.


Put another way, some developer somewhere built a system and has a 
method signature like


class Controller {
   public function dispatch(Dispatchable $dispatchable) { ... }
}

and they have provided the Dispatchable interface.  But you want to take 
any old object that does not implement Dispatchable and be able to 
modify it on the fly to bypass his type check in his type check in the 
method signature of his dispatch().



to solve this problem. I'm talking about runtime composability of
functionality. Not compile time. I want to be able to construct my
objects from other interactions (like database settings), not just be
limited to having to copy/paste for everything.


That's just crazy talk right there! ;)

composing functionality != composing types

In PHP (currently, as anything could change), is_a, instanceof and 
method type signatures are used by people who believe in a class based 
type inheritance system and the system of checks built around that.


Your proposal attempts to change that such that special types can be 
exempt from the type checking rules for the purpose of a particular 
pattern (Decorator).  I've personally never had a problems with 
decorating, so it is hard for me to envision the system you are building 
where Decorators are a problem.


-ralph






--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Decorators Revisited

2012-08-14 Thread Anthony Ferrara
Ralph,

to write. This is one of the reasons that traits are so heralded.
 Because problems that are easy to solve with decorators (in general) are
 difficult to solve with PHP, so people wind up writing copy/paste


 If what you're trying to do is decorate an instance of a particular
 concrete type, the basic structure/foundation for creating a Decorator (as
 defined by wikipedia), can be achieved in PHP with about 3 lines of code:

 class FooDecorator extends Foo {
 protected $subject;
 public function __construct(Foo $foo) {
 $this-subject = $foo;
 foreach (get_object_vars($foo) as $n = $v) {
 $this-{$n} = $foo-{$n};
 }
 }
 }

 At this point, any instance of new Foo is statefully and type equivalent
 to new FooDecorator($foo).  Now, you're free to add in your custom
 decoration logic, overridden methods, additional methods, new interfaces,
 etc.  An instance of FooDecorator can be used an any place an instance of
 Foo would have been used.  i.e., it's bound to the Foo context.


That's an alternative? Really? Some hackery involving inheritance abuse...?

Let me pose a real world example.

Let's say you have a house. Let's call it `class House`. Then let's say you
want to add christmas lights to it. You don't go bulldoze the existing
house and construct a new one (class HouseWithLights). And you don't create
a new one, move all the furnature into the new one and then move the
original one to another temporary spot (your extends example). You go get
lights (class Lights) and decorate the existing house with them. All the
properties and features of the house still exist, but with the added
functionality (and responsibility) of the new lights.

Then, let's say you want to add a deck. You don't create a new class
HouseWithLightsAndDeck. You add the deck to the existing instance.

Now, you could also do this with a bridge pattern. But with a bridge, you
need to specially design the construction for the particular type you're
doing. So you would build a bridge for a house, and a separate one for an
office building. But with a decorator, you could decorate both the house
and the office building with the same lights, and the same deck.

And I don't need to resort to duck typing for it to work. All I need is
 the ability to decorate at will. I'm not talking about nuking the
 meaning of the interfaces (as they'd be proxied to). But more just


 We're going to have to disagree on the meaning of interfaces. Interfaces
 are a foundational element of a class based type hierarchy. If you want
 Interfaces without them being in an instance type hierarchy, I'm not sure
 what you call that; but it's not an Interface. The decisions made in the
 PHP group around the class type system more closely resemble those made by
 Java and C#.


I'm absolutely talking about the interfaces being in the *instance* type
hiearchy. That's the whole point of the proposal. What I'm talking about
here is adding the ability for it to be in the instance type hiearchy
without it being in the class hiearchy...


 Concerning your code snippets above.

 It sounds like you want to dynamically build classes and methods, on the
 fly, or you want a magical subclass that is free from the current rules of
 is_a, instanceof, etc.


Absolutely not. What I'm talking about is a magic class which *inherits*
type information from its parent. Not which will magically pass all
instanceof queries. It would behave as if you extended whatever class was
passed in, without doing the actual extension (and all the coupling baggage
that comes with)...


 Put another way, some developer somewhere built a system and has a method
 signature like

 class Controller {
public function dispatch(Dispatchable $dispatchable) { ... }
 }

 and they have provided the Dispatchable interface.  But you want to take
 any old object that does not implement Dispatchable and be able to modify
 it on the fly to bypass his type check in his type check in the method
 signature of his dispatch().


Not in the least. I want to be able to take an existing object that
implements Dispatchable, and wrap that with my decorator to either add new
functionality or alter existing (while keeping the typing contracts
enforced, so the interface of the parent cannot be violated in the
decorator without a construction time error).


  to solve this problem. I'm talking about runtime composability of
 functionality. Not compile time. I want to be able to construct my
 objects from other interactions (like database settings), not just be
 limited to having to copy/paste for everything.


 That's just crazy talk right there! ;)

 composing functionality != composing types

 In PHP (currently, as anything could change), is_a, instanceof and method
 type signatures are used by people who believe in a class based type
 inheritance system and the system of checks built around that.


And I'm not arguing that in the least. In fact, I'm embracing that by
allowing a 

Re: [PHP-DEV] Decorators Revisited

2012-08-13 Thread Jordi Boggiano
Heya,

 What do you think? Is this a route that I should continue down? Or is there
 something fundamental that I'm missing here? I know that Reflection,
 get_interfaces(), etc would need to be updated to account for this.

I can't speak for the feasibility, but from a usage point of view I do
like that it opens up some sort of duck-typing by allowing decorators to
be drop-in replacements even if there is no interface to implement.

Cheers

-- 
Jordi Boggiano
@seldaek - http://nelm.io/jordi

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Decorators Revisited

2012-08-13 Thread Benjamin Eberlei
Just seeing my previous reply only went to Anthony in person. so i have to
repeat here:

Its an awesome idea, i really like it :)

On Mon, Aug 13, 2012 at 9:10 PM, Jordi Boggiano j.boggi...@seld.be wrote:

 Heya,

  What do you think? Is this a route that I should continue down? Or is
 there
  something fundamental that I'm missing here? I know that Reflection,
  get_interfaces(), etc would need to be updated to account for this.

 I can't speak for the feasibility, but from a usage point of view I do
 like that it opens up some sort of duck-typing by allowing decorators to
 be drop-in replacements even if there is no interface to implement.

 Cheers

 --
 Jordi Boggiano
 @seldaek - http://nelm.io/jordi

 --
 PHP Internals - PHP Runtime Development Mailing List
 To unsubscribe, visit: http://www.php.net/unsub.php




Re: [PHP-DEV] Decorators Revisited

2012-08-13 Thread Nils Adermann
On 08/12/2012 08:17 PM, Anthony Ferrara wrote:
 Thoughts?
Yes, please. I think this would be a great simplification for all kinds
of extensibility / plugin mechanisms implemented in various PHP projects.

Typically these either end up with the boilerplate you described or try
to come up with some kind of hack (e.g. dynamic code generation) to
circumvent the problem of having to explicitly define parent classes if
one wants to dynamically decorate objects multiple times while maintaing
interfaces.

Cheers,
Nils

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Decorators Revisited

2012-08-13 Thread Nicholas Curtis
I agree great idea. Would really help to simplify benchmarking code also.

On Mon, Aug 13, 2012 at 4:16 PM, Nils Adermann nader...@naderman.de wrote:

 On 08/12/2012 08:17 PM, Anthony Ferrara wrote:
  Thoughts?
 Yes, please. I think this would be a great simplification for all kinds
 of extensibility / plugin mechanisms implemented in various PHP projects.

 Typically these either end up with the boilerplate you described or try
 to come up with some kind of hack (e.g. dynamic code generation) to
 circumvent the problem of having to explicitly define parent classes if
 one wants to dynamically decorate objects multiple times while maintaing
 interfaces.

 Cheers,
 Nils

 --
 PHP Internals - PHP Runtime Development Mailing List
 To unsubscribe, visit: http://www.php.net/unsub.php




Re: [PHP-DEV] Decorators Revisited

2012-08-13 Thread Anthony Ferrara
All,

As promised, here's a link to the proof-of-concept implementation:
https://github.com/ircmaxell/php-src/blob/spl_decorator/ext/spl/spl_decorator.c#L77


I'm not really looking for feedback about whether or not we should
implement a decorator helper, but more for this exact method of doing it
(having a magic base class which would be extended)...

The interface addition is mainly a quick tool to test it with. I would
think that's too dirty to go with in an official proposal.

In the official proposal I could foresee two main ways of solving it:

1. Add an additional pointer to the zend_class_entry for the wrapped class.
Then change instanceof and the like to check for that pointer as well.

2. Move instanceof to a handler from the current standalone function. Then
each (pecl level) class could choose its own implementation if it is
needed. The function could still exist for BC reasons, but would proxy to
the handler method if it existed... Then, the wrapped class (the additional
pointer) would only need to live on the objects internal store...

Thanks,

Anthony

On Mon, Aug 13, 2012 at 7:50 PM, Nicholas Curtis nich.cur...@gmail.comwrote:

 I agree great idea. Would really help to simplify benchmarking code also.

 On Mon, Aug 13, 2012 at 4:16 PM, Nils Adermann nader...@naderman.de
 wrote:

  On 08/12/2012 08:17 PM, Anthony Ferrara wrote:
   Thoughts?
  Yes, please. I think this would be a great simplification for all kinds
  of extensibility / plugin mechanisms implemented in various PHP projects.
 
  Typically these either end up with the boilerplate you described or try
  to come up with some kind of hack (e.g. dynamic code generation) to
  circumvent the problem of having to explicitly define parent classes if
  one wants to dynamically decorate objects multiple times while maintaing
  interfaces.
 
  Cheers,
  Nils
 
  --
  PHP Internals - PHP Runtime Development Mailing List
  To unsubscribe, visit: http://www.php.net/unsub.php
 
 



[PHP-DEV] Decorators Revisited

2012-08-12 Thread Anthony Ferrara
Hey all

I've posted before about adding the ability to do dynamic decorators
before. I think I have come up with a method to do so in core.

Basically, the problem is that I can't create a decorator for a class at
all. I would have to extend that class (with all of the coupling issues
that brings). I can create a decorator for interfaces, but I'd need to list
proxy methods for each and every interface combination in each decorator.
This leads to tons of boilerplate issues. For example:

class CachableFooDecorator implements foo {
protected $parent;
public function __construct(Foo $obj) {
$this-parent = $obj;
}
public function __call($method, $args) {
return call_user_func_array(array($this-parent, $method), $args);
}
public function method1($a, $b) {
return $this-parent-method1($a, $b);
}
public function method2($a) {
if (!$this-hasCache('method2', $a)) {
$ret = $this-parent-method2($a);
$this-setCache('method2', $a, $ret);
}
return $this-getCache('method2', $a);
}
}

That's a lot of boilerplate for each possible iteration. This is one reason
people like traits so much, as it's easier to just do automated copy/paste
than use the proper patterns.

So, I've wanted to add a dynamic way of being able to decorate classes at
the core level. So you'd declare the class in a special way and it would
handle that boilerplate for you.

I've come up with a method to do so. Basically, I created a class
SplDecorator which looks like this:

class SplDecorator {
private $parent;
public function __construct($obj) {
$this-parent = $obj;
}
public function __call($method, $args) {
return call_user_func_array(array($this-parent, $method), $args);
}
public function getDecoratedObject() {
return $this-parent;
}
}

The other difference, is there's an object creation handler which adds the
parent's class entry to the current instances interface list. Basically:

Z_OBJCE_P(this)-interfaces = safe_realloc(Z_OBJCE_P(object)-interfaces,
Z_OBJCE_P(object)-num_interfaces + 1, sizeof(zend_class_entry), 0);
Z_OPJCE_P(object)-interfaces[Z_OBJCE_P(object)-num_interfaces] =
Z_OBJCE_P(parent);
Z_OBJCE_P(object)-num_interfaces++;

Now, the internal instanceof function is recursive, so it will return true
when tested against this class list.

So, example code like:

class Foo {}
class Bar extends SplDecorator {}
$b = new Bar(new Foo);
var_dump($b instanceof Foo); // true

It also works with type hints:
function test(Foo $f) {}
test($b);

Now, there's a lot more to do (property cascading, interface validation,
etc), but the initial proof-of-concept is there.

I have it working locally, I'll push it to github on my branch in a day or
two so that you can play around with it...

What do you think? Is this a route that I should continue down? Or is there
something fundamental that I'm missing here? I know that Reflection,
get_interfaces(), etc would need to be updated to account for this.

Thoughts?

Anthony