RE: [PHP-DEV] Traits expecting interfaces implicitly leads to expensive runtime checks
On Sat Dec 11 10:25 AM, Stefan Marr wrote: http://wiki.php.net/rfc/horizontalreuse#requiring_composing_class_to_impleme nt_interface Are there any objections to implementing this? It's not a bad idea, though I haven't found a strong need for it in the way I plan to use traits. It also turns a trait into something more complex 'copy paste' code with requirements/dependencies. -1 on using 'require' (T_REQUIRE token), an option could be 'within' trait IteratorUser within Iterator { function foo() { $next = $this-next(); ... } } class MyIterator implements Iterator { with IteratorUser; } So the 'with/within' tokens would apply to traits. Overall I feel -1, more use cases around Trait expresses a requirement for the composing class would help, it seems like useful theory... not convinced it's worth the trouble. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Traits expecting interfaces implicitly leads to expensive runtime checks
On Sun, Dec 12, 2010 at 7:25 AM, Jonathan Bond-Caron jbo...@openmv.comwrote: On Sat Dec 11 10:25 AM, Stefan Marr wrote: http://wiki.php.net/rfc/horizontalreuse#requiring_composing_class_to_impleme nt_interface Are there any objections to implementing this? It's not a bad idea, though I haven't found a strong need for it in the way I plan to use traits. Do you intend to use traits as reusable implementations of interfaces? If not, I could see why this feature isn't of interest to you :) It also turns a trait into something more complex 'copy paste' code with requirements/dependencies. I think copy paste is a good way to conceptualize traits, but feel, practically, they're a bit more complex than that w/ conflict resolution, traits composed of traits, and the issue w/ attributes Stefan has brought up. Essentially, there are already rules being added around the copy paste concept. Also, this feature is mostly an extension of the abstract keyword concept in traits, which they already support. -1 on using 'require' (T_REQUIRE token), an option could be 'within' trait IteratorUser within Iterator { function foo() { $next = $this-next(); ... } } class MyIterator implements Iterator { with IteratorUser; } So the 'with/within' tokens would apply to traits. I feel 'expect', 'need', 'require' etc sound better, matter of opinion really, but it sounds like from an internals perspective it's preferred to reuse existing keywords if possible. Overall I feel -1, more use cases around Trait expresses a requirement for the composing class would help, it seems like useful theory... not convinced it's worth the trouble. If you see the value in the abstract keyword in abstract classes or moreover interfaces in general, I'd consider the value of this feature equal. Of course not everyone uses abstract classes or interfaces :D -nathan
Re: [PHP-DEV] Traits expecting interfaces implicitly leads to expensive runtime checks
Hi: I added the proposal to the RFC. See http://wiki.php.net/rfc/horizontalreuse#requiring_composing_class_to_implement_interface = Requiring Composing Class to Implement Interface = Traits are able to express required methods by using abstract method declarations. An abstract method can be satisfied in varios ways, for instance by implementing it in the composing class or by bringing it in from another Trait. However, for traits that require complex interfaces to be satisfied, this approach is tedious and fragile, since it requires the developer to state all used methods explicitly. Another solution is that a Trait expresses a requirement for the composing class to implement a certain interface. This is not entirely identical to using abstract methods, however. First, it imposes a requirement on interface level and thus will have the same fragility with respect to interface changes as all other clients of an interface. On the other hand, it avoids duplications of abstract method definitions and makes the interface the main entity of responsibility as for normal client-interface uses in current code. ?php // IteratorUser works with $this using the Iterator interface trait IteratorUser require Iterator { function foo() { $next = $this-next(); ... } } // composed into a class that needs to implement the interface class Example implements Iterator { use IteratorUser; } Are there any objections to implementing this? Thanks Stefan -- Stefan Marr Software Languages Lab Vrije Universiteit Brussel Pleinlaan 2 / B-1050 Brussels / Belgium http://soft.vub.ac.be/~smarr Phone: +32 2 629 2974 Fax: +32 2 629 3525 -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Traits expecting interfaces implicitly leads to expensive runtime checks
On Thu, Dec 9, 2010 at 4:04 PM, Stefan Marr p...@stefan-marr.de wrote: Hi Nathan: On 09 Dec 2010, at 23:42, Nathan Nobbe wrote: What I'm getting at is the scenario when a trait is designed to be used in concert with the class in which it is being used. In this case the trait expects certain functions to be available on the class in which it is used with. If the methods aren't there (or checked for at runtime) a fatal error is raised. A quick example ?php class A { use AHelper; function blah() {} } trait AHelper { function meh() { // hoping we get used w/ instances of A ... return $this-blah() * 5; } } class B { use AHelper; /// waiting for a runtime error if blah() is ever called .. } ? Do you see what I mean? No, do not really see what you are getting at. How is your approach using the instanceof checks (from the first mail) different from changing AHelper to require blah() by stating this requirement using an abstract method definition? For the trait it is not important where that method is implemented, it just has to be in the final composed class. So, why don't you want the following trait? trait AHelper { abstract function blah(); function meh() { // hoping we get used w/ instances of A ... return $this-blah() * 5; } } Ahh, I see how the abstract methods are working in traits now, I didn't catch that from your first post; thanks for showing that to me. You want to avoid the fatal error during runtime, right? Yes, exactly, and the runtime check for expected interface / class / method. Do you prefer dynamic checks over compile time checks? Def not :D, however, I still think this paradigm is lacking. Don't you think it makes more sense if I write a trait that expects a given interface or class to be able to specify said interface/class in it's entirety with just a single identifier rather than listing out all the methods? For example, I think this would be ugly ?php trait IteratorHelper{ abstract public current(); abstract public key(); abstract public next(); abstract public rewind(); abstract public valid(); } ? essentially you're redeclaring the entire interface in the trait, the same would be true of the public interface of an expected class. i think it would be much more elegant to allow a specification on the trait declaration itself, something like ?php trait IteratorHelper expects Iterator { ... } ? -nathan
Re: [PHP-DEV] Traits expecting interfaces implicitly leads to expensive runtime checks
Hi Nathan: On 10 Dec 2010, at 17:49, Nathan Nobbe wrote: Def not :D, however, I still think this paradigm is lacking. Don't you think it makes more sense if I write a trait that expects a given interface or class to be able to specify said interface/class in it's entirety with just a single identifier rather than listing out all the methods? For example, I think this would be ugly ?php trait IteratorHelper{ abstract public current(); abstract public key(); abstract public next(); abstract public rewind(); abstract public valid(); } ? essentially you're redeclaring the entire interface in the trait, the same would be true of the public interface of an expected class. i think it would be much more elegant to allow a specification on the trait declaration itself, something like ?php trait IteratorHelper expects Iterator { ... } ? :D That was exactly my thought when I was writing my first answer. My second thought was, damn, not another keyword... But since you also seem to see the need, we should give it a thought. Anyone else with an opinion on that? Best regards Stefan -- Stefan Marr Software Languages Lab Vrije Universiteit Brussel Pleinlaan 2 / B-1050 Brussels / Belgium http://soft.vub.ac.be/~smarr Phone: +32 2 629 2974 Fax: +32 2 629 3525 -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Traits expecting interfaces implicitly leads to expensive runtime checks
First i have to say that I am not a PHP internals developer, but as a user I think it would maybe be better to just let the trait use the implements keyword, and copy that to the classes utilizing the trait? Or does that seem illogical when the trait does not implement all of the methods specified by the interface? (Because I think expects might be a common name in APIs for some kind of validation.) Best Regards Martin Wernstahl On Fri, Dec 10, 2010 at 18:09, Stefan Marr p...@stefan-marr.de wrote: Hi Nathan: On 10 Dec 2010, at 17:49, Nathan Nobbe wrote: Def not :D, however, I still think this paradigm is lacking. Don't you think it makes more sense if I write a trait that expects a given interface or class to be able to specify said interface/class in it's entirety with just a single identifier rather than listing out all the methods? For example, I think this would be ugly ?php trait IteratorHelper{ abstract public current(); abstract public key(); abstract public next(); abstract public rewind(); abstract public valid(); } ? essentially you're redeclaring the entire interface in the trait, the same would be true of the public interface of an expected class. i think it would be much more elegant to allow a specification on the trait declaration itself, something like ?php trait IteratorHelper expects Iterator { ... } ? :D That was exactly my thought when I was writing my first answer. My second thought was, damn, not another keyword... But since you also seem to see the need, we should give it a thought. Anyone else with an opinion on that? Best regards Stefan -- Stefan Marr Software Languages Lab Vrije Universiteit Brussel Pleinlaan 2 / B-1050 Brussels / Belgium http://soft.vub.ac.be/~smarr Phone: +32 2 629 2974 Fax: +32 2 629 3525 -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Traits expecting interfaces implicitly leads to expensive runtime checks
Hello Martin: On 10 Dec 2010, at 18:15, Martin Wernstahl wrote: First i have to say that I am not a PHP internals developer, but as a user I think it would maybe be better to just let the trait use the implements keyword, and copy that to the classes utilizing the trait? Or does that seem illogical when the trait does not implement all of the methods specified by the interface? Implements sounds misleading to me. Read: trait Foo implements Bar. Sounds like Foo is providing Bar and not expecting the interface to be there. But require might be a good keyword to be reused. Best Regards Stefan -- Stefan Marr Software Languages Lab Vrije Universiteit Brussel Pleinlaan 2 / B-1050 Brussels / Belgium http://soft.vub.ac.be/~smarr Phone: +32 2 629 2974 Fax: +32 2 629 3525 -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Traits expecting interfaces implicitly leads to expensive runtime checks
On Fri, Dec 10, 2010 at 10:15 AM, Martin Wernstahl m4r...@gmail.com wrote: First i have to say that I am not a PHP internals developer, but as a user I think it would maybe be better to just let the trait use the implements keyword, and copy that to the classes utilizing the trait? This is actually in the RFC as a rejected proposal http://wiki.php.net/rfc/traits#rejected_features But what I'm talking about is something different. We're not trying to say 'these are the methods implemented in the trait', rather, 'this trait expects a class it is used with to be of a certain type or implement a certain interface' for the trait to do its job. -nathan
Re: [PHP-DEV] Traits expecting interfaces implicitly leads to expensive runtime checks
Oh, sorry, should have read the RFC thoroughly before sending an email. But yeah, require might be a good choice, provided it doesn't collide with the specific require logic in the scanner/parser (I don't have much knowledge on that subject, but I've peeked a few times on it as it is interesting). Best Regards Martin Wernstahl On Fri, Dec 10, 2010 at 18:29, Nathan Nobbe quickshif...@gmail.com wrote: On Fri, Dec 10, 2010 at 10:15 AM, Martin Wernstahl m4r...@gmail.comwrote: First i have to say that I am not a PHP internals developer, but as a user I think it would maybe be better to just let the trait use the implements keyword, and copy that to the classes utilizing the trait? This is actually in the RFC as a rejected proposal http://wiki.php.net/rfc/traits#rejected_features But what I'm talking about is something different. We're not trying to say 'these are the methods implemented in the trait', rather, 'this trait expects a class it is used with to be of a certain type or implement a certain interface' for the trait to do its job. -nathan
Re: [PHP-DEV] Traits expecting interfaces implicitly leads to expensive runtime checks
On Fri, Dec 10, 2010 at 9:29 AM, Nathan Nobbe quickshif...@gmail.com wrote: On Fri, Dec 10, 2010 at 10:15 AM, Martin Wernstahl m4r...@gmail.com wrote: First i have to say that I am not a PHP internals developer, but as a user I think it would maybe be better to just let the trait use the implements keyword, and copy that to the classes utilizing the trait? This is actually in the RFC as a rejected proposal http://wiki.php.net/rfc/traits#rejected_features But what I'm talking about is something different. We're not trying to say 'these are the methods implemented in the trait', rather, 'this trait expects a class it is used with to be of a certain type or implement a certain interface' for the trait to do its job. -nathan Shouldn't the burden be on the programmer to make sure the trait works with the class using it rather than on the compiler? If they try to use a trait that requires methods that don't exist, it will error out anyway, so it won't be difficult to debug. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Traits expecting interfaces implicitly leads to expensive runtime checks
On Fri, Dec 10, 2010 at 11:04 AM, Chad Fulton chadful...@gmail.com wrote: On Fri, Dec 10, 2010 at 9:29 AM, Nathan Nobbe quickshif...@gmail.com wrote: On Fri, Dec 10, 2010 at 10:15 AM, Martin Wernstahl m4r...@gmail.com wrote: First i have to say that I am not a PHP internals developer, but as a user I think it would maybe be better to just let the trait use the implements keyword, and copy that to the classes utilizing the trait? This is actually in the RFC as a rejected proposal http://wiki.php.net/rfc/traits#rejected_features But what I'm talking about is something different. We're not trying to say 'these are the methods implemented in the trait', rather, 'this trait expects a class it is used with to be of a certain type or implement a certain interface' for the trait to do its job. -nathan Shouldn't the burden be on the programmer to make sure the trait works with the class using it rather than on the compiler? If they try to use a trait that requires methods that don't exist, it will error out anyway, so it won't be difficult to debug. Well I know PHP is a dynamic language but what about all the compile time features that have come along over the years. The abstract keyword for example vs. the PHP4 way of implementing an 'abstract' method which was triggering an error in the default implementation in a base class. One of the main things a lot of PHP programmers I've worked with hate is waiting for code to hit production and encountering a runtime error w/ something that could have been caught at compile time. I know the notion of compile time in a scripting language like PHP is much less removed from that of C++, Java etc, however there is a notion of it there, obviously. Also, I would suggest this feature be optional, so there is no need to use it if you don't like it. But for those of us who would like to defer as much type checking to the compiler as possible so we don't need runtime checks all over our code or prayers that we've tested every line before production, it would certainly be nice. Lastly, you may know that traits will allow PHP programmers to move away from the delegate pattern which is a common workaround to multiple inheritance at this point. However, in speaking with a colleague over the concept I'm proposing yesterday we discovered the delegate model actually does allow you to specify which class/interface the delegate is used w/, it would be sad not to see comparable support in the trait feature which will mostly eliminate the need for the delegate pattern, see my quick example. ?php class MainClass { private $_oDelegate = null; function addDelegate() { $this-_oDelegate = new Delegate($this); } } class Delegate { private function $_oMain = null; /// delegate gets to say what it can be used with via type hinting function __construct(MainClass $oMainClass) { $this-_oMain = $oMainClass; } } ? Imagine how much cleaner this could be w/ traits, yet just as expressive ?php class MainClass { use Delegate; } trait Delegate require MainClass { ... } ? -nathan
Re: [PHP-DEV] Traits expecting interfaces implicitly leads to expensive runtime checks
On Fri, Dec 10, 2010 at 10:39 AM, Nathan Nobbe quickshif...@gmail.com wrote: On Fri, Dec 10, 2010 at 11:04 AM, Chad Fulton chadful...@gmail.com wrote: On Fri, Dec 10, 2010 at 9:29 AM, Nathan Nobbe quickshif...@gmail.com wrote: On Fri, Dec 10, 2010 at 10:15 AM, Martin Wernstahl m4r...@gmail.com wrote: First i have to say that I am not a PHP internals developer, but as a user I think it would maybe be better to just let the trait use the implements keyword, and copy that to the classes utilizing the trait? This is actually in the RFC as a rejected proposal http://wiki.php.net/rfc/traits#rejected_features But what I'm talking about is something different. We're not trying to say 'these are the methods implemented in the trait', rather, 'this trait expects a class it is used with to be of a certain type or implement a certain interface' for the trait to do its job. -nathan Shouldn't the burden be on the programmer to make sure the trait works with the class using it rather than on the compiler? If they try to use a trait that requires methods that don't exist, it will error out anyway, so it won't be difficult to debug. Well I know PHP is a dynamic language but what about all the compile time features that have come along over the years. The abstract keyword for example vs. the PHP4 way of implementing an 'abstract' method which was triggering an error in the default implementation in a base class. One of the main things a lot of PHP programmers I've worked with hate is waiting for code to hit production and encountering a runtime error w/ something that could have been caught at compile time. I know the notion of compile time in a scripting language like PHP is much less removed from that of C++, Java etc, however there is a notion of it there, obviously. Also, I would suggest this feature be optional, so there is no need to use it if you don't like it. But for those of us who would like to defer as much type checking to the compiler as possible so we don't need runtime checks all over our code or prayers that we've tested every line before production, it would certainly be nice. Lastly, you may know that traits will allow PHP programmers to move away from the delegate pattern which is a common workaround to multiple inheritance at this point. However, in speaking with a colleague over the concept I'm proposing yesterday we discovered the delegate model actually does allow you to specify which class/interface the delegate is used w/, it would be sad not to see comparable support in the trait feature which will mostly eliminate the need for the delegate pattern, see my quick example. ?php class MainClass { private $_oDelegate = null; function addDelegate() { $this-_oDelegate = new Delegate($this); } } class Delegate { private function $_oMain = null; /// delegate gets to say what it can be used with via type hinting function __construct(MainClass $oMainClass) { $this-_oMain = $oMainClass; } } ? Imagine how much cleaner this could be w/ traits, yet just as expressive ?php class MainClass { use Delegate; } trait Delegate require MainClass { ... } ? -nathan As a note, I'm not strongly opposed to this proposal, since I don't think it would do any harm. It just seems to me like a kitchen sink feature. The issue for me is that traits, as I understand them, are there primarily for horizontal code re-use via compile-time copy/paste. With that in mind, I feel like the developer is responsible for making sure the methods they copy into their classes make sense, just as they would have to do if they physically copied and pasted them. I think your example above isn't quite what you meant to show, since you're requiring a specific class and not an interface (since PHP only allows one class definition for a class name, you're not gaining anything via traits, since the trait could only be used for that specific class, in which case why not just have the code in the class in the first place?). If we take your example in a more general case using interfaces, I still can't see what the benefit is. All it does is provide a more explicit and immediate error message for developers (e.g. instead of method not found error when the bad method call is made at runtime, you get a classes using trait trait must implement interface at compile time). Again, I'm not against it, but maybe be too much hand holding, since the developer should make sure using the trait makes sense first? -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Traits expecting interfaces implicitly leads to expensive runtime checks
On 2010-12-10, Nathan Nobbe quickshif...@gmail.com wrote: --0016e6dbe7fb8861a1049712ad63 Content-Type: text/plain; charset=UTF-8 On Fri, Dec 10, 2010 at 11:04 AM, Chad Fulton chadful...@gmail.com wrote: On Fri, Dec 10, 2010 at 9:29 AM, Nathan Nobbe quickshif...@gmail.com wrote: On Fri, Dec 10, 2010 at 10:15 AM, Martin Wernstahl m4r...@gmail.com wrote: First i have to say that I am not a PHP internals developer, but as a user I think it would maybe be better to just let the trait use the implements keyword, and copy that to the classes utilizing the trait? This is actually in the RFC as a rejected proposal http://wiki.php.net/rfc/traits#rejected_features But what I'm talking about is something different. We're not trying to say 'these are the methods implemented in the trait', rather, 'this trait expects a class it is used with to be of a certain type or implement a certain interface' for the trait to do its job. -nathan Shouldn't the burden be on the programmer to make sure the trait works with the class using it rather than on the compiler? If they try to use a trait that requires methods that don't exist, it will error out anyway, so it won't be difficult to debug. Well I know PHP is a dynamic language but what about all the compile time features that have come along over the years. The abstract keyword for example vs. the PHP4 way of implementing an 'abstract' method which was triggering an error in the default implementation in a base class. One of the main things a lot of PHP programmers I've worked with hate is waiting for code to hit production and encountering a runtime error w/ something that could have been caught at compile time. I know the notion of compile time in a scripting language like PHP is much less removed from that of C++, Java etc, however there is a notion of it there, obviously. To me, putting this into the language feels like overkill. Unless you're using an opcode cache, the notion of compile time as a differentiation from runtime in PHP has little relevance -- you still only find out when the script executes. There's already a way to mitigate this as well: write a testing suite for your application, and exercise it often. If you write your tests well (targeting the discrete behaviors of your application), then most likely they'll catch such errors -- allowing you to fix them before you deploy. -- Matthew Weier O'Phinney Project Lead| matt...@zend.com Zend Framework | http://framework.zend.com/ PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Traits expecting interfaces implicitly leads to expensive runtime checks
On Fri, Dec 10, 2010 at 12:55 PM, Matthew Weier O'Phinney weierophin...@php.net wrote: On 2010-12-10, Nathan Nobbe quickshif...@gmail.com wrote: --0016e6dbe7fb8861a1049712ad63 Content-Type: text/plain; charset=UTF-8 On Fri, Dec 10, 2010 at 11:04 AM, Chad Fulton chadful...@gmail.com wrote: On Fri, Dec 10, 2010 at 9:29 AM, Nathan Nobbe quickshif...@gmail.com wrote: On Fri, Dec 10, 2010 at 10:15 AM, Martin Wernstahl m4r...@gmail.com wrote: First i have to say that I am not a PHP internals developer, but as a user I think it would maybe be better to just let the trait use the implements keyword, and copy that to the classes utilizing the trait? This is actually in the RFC as a rejected proposal http://wiki.php.net/rfc/traits#rejected_features But what I'm talking about is something different. We're not trying to say 'these are the methods implemented in the trait', rather, 'this trait expects a class it is used with to be of a certain type or implement a certain interface' for the trait to do its job. -nathan Shouldn't the burden be on the programmer to make sure the trait works with the class using it rather than on the compiler? If they try to use a trait that requires methods that don't exist, it will error out anyway, so it won't be difficult to debug. Well I know PHP is a dynamic language but what about all the compile time features that have come along over the years. The abstract keyword for example vs. the PHP4 way of implementing an 'abstract' method which was triggering an error in the default implementation in a base class. One of the main things a lot of PHP programmers I've worked with hate is waiting for code to hit production and encountering a runtime error w/ something that could have been caught at compile time. I know the notion of compile time in a scripting language like PHP is much less removed from that of C++, Java etc, however there is a notion of it there, obviously. To me, putting this into the language feels like overkill. Unless you're using an opcode cache, the notion of compile time as a differentiation from runtime in PHP has little relevance -- you still only find out when the script executes. *Only* if you hit the line of code at runtime that would destroy your script; often times this doesn't happen until it's too late, and the code has made it to production. And there is a notion of compile time in PHP, I'm not sure what it's referred to by the internals group, but abstract methods and interfaces definitely constitue compile time checks to me. There's already a way to mitigate this as well: write a testing suite for your application, and exercise it often. If you write your tests well (targeting the discrete behaviors of your application), then most likely they'll catch such errors -- allowing you to fix them before you deploy. Right, so you have to do tons of extra work (writing unit tests) which have to actually test every potential line of failure, when this could just simply be caught up front w/o any second guessing whether or not you've covered all cases in your tests. I'm not against unit tests at all, just saying it's much easier to guarantee you're safely using a trait w/ a compile time check rather than deferring the application author to test suite development. -nathan
Re: [PHP-DEV] Traits expecting interfaces implicitly leads to expensive runtime checks
On Fri, Dec 10, 2010 at 12:39 PM, Chad Fulton chadful...@gmail.com wrote: On Fri, Dec 10, 2010 at 10:39 AM, Nathan Nobbe quickshif...@gmail.com wrote: On Fri, Dec 10, 2010 at 11:04 AM, Chad Fulton chadful...@gmail.com wrote: On Fri, Dec 10, 2010 at 9:29 AM, Nathan Nobbe quickshif...@gmail.com wrote: On Fri, Dec 10, 2010 at 10:15 AM, Martin Wernstahl m4r...@gmail.com wrote: First i have to say that I am not a PHP internals developer, but as a user I think it would maybe be better to just let the trait use the implements keyword, and copy that to the classes utilizing the trait? This is actually in the RFC as a rejected proposal http://wiki.php.net/rfc/traits#rejected_features But what I'm talking about is something different. We're not trying to say 'these are the methods implemented in the trait', rather, 'this trait expects a class it is used with to be of a certain type or implement a certain interface' for the trait to do its job. -nathan Shouldn't the burden be on the programmer to make sure the trait works with the class using it rather than on the compiler? If they try to use a trait that requires methods that don't exist, it will error out anyway, so it won't be difficult to debug. Well I know PHP is a dynamic language but what about all the compile time features that have come along over the years. The abstract keyword for example vs. the PHP4 way of implementing an 'abstract' method which was triggering an error in the default implementation in a base class. One of the main things a lot of PHP programmers I've worked with hate is waiting for code to hit production and encountering a runtime error w/ something that could have been caught at compile time. I know the notion of compile time in a scripting language like PHP is much less removed from that of C++, Java etc, however there is a notion of it there, obviously. Also, I would suggest this feature be optional, so there is no need to use it if you don't like it. But for those of us who would like to defer as much type checking to the compiler as possible so we don't need runtime checks all over our code or prayers that we've tested every line before production, it would certainly be nice. Lastly, you may know that traits will allow PHP programmers to move away from the delegate pattern which is a common workaround to multiple inheritance at this point. However, in speaking with a colleague over the concept I'm proposing yesterday we discovered the delegate model actually does allow you to specify which class/interface the delegate is used w/, it would be sad not to see comparable support in the trait feature which will mostly eliminate the need for the delegate pattern, see my quick example. ?php class MainClass { private $_oDelegate = null; function addDelegate() { $this-_oDelegate = new Delegate($this); } } class Delegate { private function $_oMain = null; /// delegate gets to say what it can be used with via type hinting function __construct(MainClass $oMainClass) { $this-_oMain = $oMainClass; } } ? Imagine how much cleaner this could be w/ traits, yet just as expressive ?php class MainClass { use Delegate; } trait Delegate require MainClass { ... } ? -nathan As a note, I'm not strongly opposed to this proposal, since I don't think it would do any harm. It just seems to me like a kitchen sink feature. The issue for me is that traits, as I understand them, are there primarily for horizontal code re-use via compile-time copy/paste. With that in mind, I feel like the developer is responsible for making sure the methods they copy into their classes make sense, just as they would have to do if they physically copied and pasted them. Copy paste itself leads to duplicated unmaintainable code, so traits are introduced (among other reasons) to prohibit this practice. Why not take it a step further and let a trait definition be as expressive as possible, eliminating ambiguity, right out of the gate? I think your example above isn't quite what you meant to show, since you're requiring a specific class and not an interface (since PHP only allows one class definition for a class name, you're not gaining anything via traits, since the trait could only be used for that specific class, in which case why not just have the code in the class in the first place?). In retrospect Chad, that's a good point, and perhaps there is no reason to allow marking of classes as required by traits. If we take your example in a more general case using interfaces, I still can't see what the benefit is. All it does is provide a more explicit and immediate error message for developers (e.g. instead of method not found error when the bad method call is made at runtime, you get a classes using trait trait must implement
Re: [PHP-DEV] Traits expecting interfaces implicitly leads to expensive runtime checks
On 2010-12-10, Nathan Nobbe quickshif...@gmail.com wrote: --0016e6d7e101e083a4049714bad3 Content-Type: text/plain; charset=UTF-8 On Fri, Dec 10, 2010 at 12:55 PM, Matthew Weier O'Phinney weierophin...@php.net wrote: On 2010-12-10, Nathan Nobbe quickshif...@gmail.com wrote: --0016e6dbe7fb8861a1049712ad63 Content-Type: text/plain; charset=UTF-8 On Fri, Dec 10, 2010 at 11:04 AM, Chad Fulton chadful...@gmail.com wrote: On Fri, Dec 10, 2010 at 9:29 AM, Nathan Nobbe quickshif...@gmail.com wrote: On Fri, Dec 10, 2010 at 10:15 AM, Martin Wernstahl m4r...@gmail.com wrote: First i have to say that I am not a PHP internals developer, but as a user I think it would maybe be better to just let the trait use the implements keyword, and copy that to the classes utilizing the trait? This is actually in the RFC as a rejected proposal http://wiki.php.net/rfc/traits#rejected_features But what I'm talking about is something different. We're not trying to say 'these are the methods implemented in the trait', rather, 'this trait expects a class it is used with to be of a certain type or implement a certain interface' for the trait to do its job. -nathan Shouldn't the burden be on the programmer to make sure the trait works with the class using it rather than on the compiler? If they try to use a trait that requires methods that don't exist, it will error out anyway, so it won't be difficult to debug. Well I know PHP is a dynamic language but what about all the compile time features that have come along over the years. The abstract keyword for example vs. the PHP4 way of implementing an 'abstract' method which was triggering an error in the default implementation in a base class. One of the main things a lot of PHP programmers I've worked with hate is waiting for code to hit production and encountering a runtime error w/ something that could have been caught at compile time. I know the notion of compile time in a scripting language like PHP is much less removed from that of C++, Java etc, however there is a notion of it there, obviously. To me, putting this into the language feels like overkill. Unless you're using an opcode cache, the notion of compile time as a differentiation from runtime in PHP has little relevance -- you still only find out when the script executes. *Only* if you hit the line of code at runtime that would destroy your script; often times this doesn't happen until it's too late, and the code has made it to production. That's what good testing is about -- exercising all the expected behaviors of your code. If you hit an unexpected behavior in production, you add a test to your suite that reproduces it, fix it, and re-deploy. And there is a notion of compile time in PHP, I'm not sure what it's referred to by the internals group, but abstract methods and interfaces definitely constitue compile time checks to me. There's already a way to mitigate this as well: write a testing suite for your application, and exercise it often. If you write your tests well (targeting the discrete behaviors of your application), then most likely they'll catch such errors -- allowing you to fix them before you deploy. Right, so you have to do tons of extra work (writing unit tests) which have to actually test every potential line of failure, when this could just simply be caught up front w/o any second guessing whether or not you've covered all cases in your tests. Writing tests should not be considered tons of extra work; it should be considered a basic part of development. How can you prove your code does what it should without them? How can you insulate your code from future changes? As long as you consider it extra work, I don't care what the compiler offers you -- you're going to shoot yourself in the foot some day. I'm not against unit tests at all, just saying it's much easier to guarantee you're safely using a trait w/ a compile time check rather than deferring the application author to test suite development. Again, are the benefits worth it, if you're writing code where an unexpected runtime exception could still occur because you didn't test properly in the first place? -- Matthew Weier O'Phinney Project Lead| matt...@zend.com Zend Framework | http://framework.zend.com/ PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Traits expecting interfaces implicitly leads to expensive runtime checks
On Fri, Dec 10, 2010 at 1:00 PM, Nathan Nobbe quickshif...@gmail.com wrote: As a note, I'm not strongly opposed to this proposal, since I don't think it would do any harm. It just seems to me like a kitchen sink feature. The issue for me is that traits, as I understand them, are there primarily for horizontal code re-use via compile-time copy/paste. With that in mind, I feel like the developer is responsible for making sure the methods they copy into their classes make sense, just as they would have to do if they physically copied and pasted them. Copy paste itself leads to duplicated unmaintainable code, so traits are introduced (among other reasons) to prohibit this practice. Why not take it a step further and let a trait definition be as expressive as possible, eliminating ambiguity, right out of the gate? I think your example above isn't quite what you meant to show, since you're requiring a specific class and not an interface (since PHP only allows one class definition for a class name, you're not gaining anything via traits, since the trait could only be used for that specific class, in which case why not just have the code in the class in the first place?). In retrospect Chad, that's a good point, and perhaps there is no reason to allow marking of classes as required by traits. If we take your example in a more general case using interfaces, I still can't see what the benefit is. All it does is provide a more explicit and immediate error message for developers (e.g. instead of method not found error when the bad method call is made at runtime, you get a classes using trait trait must implement interface at compile time). Exactly, catch it at compile time rather than runtime, that's all it is really, just like the benefit of discovering a given subclass doesn't implement a given abstract method so that I don't go any further and run code guaranteed not to work. Again, I'm not against it, but maybe be too much hand holding, since the developer should make sure using the trait makes sense first? Couldn't the same be said for a developer extending an abstract class, or implementing an interface? And also, a developer is to look through the entire definition of a trait to know which methods it's going to depend on? I know abstract is there as Stefan showed, but as we've both observed that approach can get messy quickly. -nathan I think that you make a convincing argument. Thinking more about your Iterator example, this idea makes a lot of sense and could be quite useful. Also, I was wrong about requiring a class. It could be very useful, especially if it is an internal class (e.g. ArrayObject) which might have many children, and of course in this case the parent can't be changed. I think the require keyword works well. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Traits expecting interfaces implicitly leads to expensive runtime checks
On Fri, Dec 10, 2010 at 2:42 PM, Matthew Weier O'Phinney weierophin...@php.net wrote: On 2010-12-10, Nathan Nobbe quickshif...@gmail.com wrote: --0016e6d7e101e083a4049714bad3 Content-Type: text/plain; charset=UTF-8 On Fri, Dec 10, 2010 at 12:55 PM, Matthew Weier O'Phinney weierophin...@php.net wrote: On 2010-12-10, Nathan Nobbe quickshif...@gmail.com wrote: --0016e6dbe7fb8861a1049712ad63 Content-Type: text/plain; charset=UTF-8 On Fri, Dec 10, 2010 at 11:04 AM, Chad Fulton chadful...@gmail.com wrote: On Fri, Dec 10, 2010 at 9:29 AM, Nathan Nobbe quickshif...@gmail.com wrote: On Fri, Dec 10, 2010 at 10:15 AM, Martin Wernstahl m4r...@gmail.com wrote: First i have to say that I am not a PHP internals developer, but as a user I think it would maybe be better to just let the trait use the implements keyword, and copy that to the classes utilizing the trait? This is actually in the RFC as a rejected proposal http://wiki.php.net/rfc/traits#rejected_features But what I'm talking about is something different. We're not trying to say 'these are the methods implemented in the trait', rather, 'this trait expects a class it is used with to be of a certain type or implement a certain interface' for the trait to do its job. -nathan Shouldn't the burden be on the programmer to make sure the trait works with the class using it rather than on the compiler? If they try to use a trait that requires methods that don't exist, it will error out anyway, so it won't be difficult to debug. Well I know PHP is a dynamic language but what about all the compile time features that have come along over the years. The abstract keyword for example vs. the PHP4 way of implementing an 'abstract' method which was triggering an error in the default implementation in a base class. One of the main things a lot of PHP programmers I've worked with hate is waiting for code to hit production and encountering a runtime error w/ something that could have been caught at compile time. I know the notion of compile time in a scripting language like PHP is much less removed from that of C++, Java etc, however there is a notion of it there, obviously. To me, putting this into the language feels like overkill. Unless you're using an opcode cache, the notion of compile time as a differentiation from runtime in PHP has little relevance -- you still only find out when the script executes. *Only* if you hit the line of code at runtime that would destroy your script; often times this doesn't happen until it's too late, and the code has made it to production. That's what good testing is about -- exercising all the expected behaviors of your code. If you hit an unexpected behavior in production, you add a test to your suite that reproduces it, fix it, and re-deploy. Right, and implementing an interface or subclassing an abstract class does not require a unit test in order to determine if I've at least met the obligations set forth by the interface or abstract class. The basic idea of a unit test is to write meaningful tests that actually offer you some milage for your time. I mean sure, I could write tests for setters and getters, but that's pretty much a waste of time compared to writing tests that actually get into semantics the class aims to provide. And there is a notion of compile time in PHP, I'm not sure what it's referred to by the internals group, but abstract methods and interfaces definitely constitue compile time checks to me. There's already a way to mitigate this as well: write a testing suite for your application, and exercise it often. If you write your tests well (targeting the discrete behaviors of your application), then most likely they'll catch such errors -- allowing you to fix them before you deploy. Right, so you have to do tons of extra work (writing unit tests) which have to actually test every potential line of failure, when this could just simply be caught up front w/o any second guessing whether or not you've covered all cases in your tests. Writing tests should not be considered tons of extra work; it should be considered a basic part of development. Shrug, taken out of context. I'm sure you can see how writing an extra word in the trait definition is much less work than including a unit test suite in your project and then a test against each class that uses the trait.., IMO, *that* is a ton of extra work. Even in the context of unit test writing a compile time check would eliminate the need of writing what I would consider bolier plate unit tests for traits. It's like, well I just wrote a trait, now any class I write against it I should go ahead and test that it provides all the methods for said trait .. that's just a waste of time.
Re: [PHP-DEV] Traits expecting interfaces implicitly leads to expensive runtime checks
On Thu, Dec 9, 2010 at 1:09 AM, Stefan Marr p...@stefan-marr.de wrote: Hi Nathan: On 09 Dec 2010, at 08:44, Nathan Nobbe wrote: Hi, I think traits will lend themselves to frequent runtime checking against the type of class in which they were used. Consider a trait designed for use with an Iterator class; the first thing might be to check the type of $this. Why would you need such a check? To avoid a fatal error at runtime. You want to ensure that the class that is using your trait obeys a certain interface, right? Not really, it's so the trait can guarantee the class it has been used with implements a given interface that it may need to accomplish its job. More specifically, you need it to implement a number of methods of an interface, correct? So, why not asking for it explicitly? ?php trait InnerIteratorImpl { abstract function next(); public function apply() { do somthing with $this-next() ... } } ? Does that what you want it to do? Not really, in this example above the trait is self-contained, implementing all the methods of a particular interface so it's reasonable to expect from one of the methods in the trait, another of the Iterator interface to be there. What I'm getting at is the scenario when a trait is designed to be used in concert with the class in which it is being used. In this case the trait expects certain functions to be available on the class in which it is used with. If the methods aren't there (or checked for at runtime) a fatal error is raised. A quick example ?php class A { use AHelper; function blah() {} } trait AHelper { function meh() { // hoping we get used w/ instances of A ... return $this-blah() * 5; } } class B { use AHelper; /// waiting for a runtime error if blah() is ever called .. } ? Do you see what I mean? -nathan
Re: [PHP-DEV] Traits expecting interfaces implicitly leads to expensive runtime checks
Hi Nathan: On 09 Dec 2010, at 23:42, Nathan Nobbe wrote: What I'm getting at is the scenario when a trait is designed to be used in concert with the class in which it is being used. In this case the trait expects certain functions to be available on the class in which it is used with. If the methods aren't there (or checked for at runtime) a fatal error is raised. A quick example ?php class A { use AHelper; function blah() {} } trait AHelper { function meh() { // hoping we get used w/ instances of A ... return $this-blah() * 5; } } class B { use AHelper; /// waiting for a runtime error if blah() is ever called .. } ? Do you see what I mean? No, do not really see what you are getting at. How is your approach using the instanceof checks (from the first mail) different from changing AHelper to require blah() by stating this requirement using an abstract method definition? For the trait it is not important where that method is implemented, it just has to be in the final composed class. So, why don't you want the following trait? trait AHelper { abstract function blah(); function meh() { // hoping we get used w/ instances of A ... return $this-blah() * 5; } } You want to avoid the fatal error during runtime, right? Do you prefer dynamic checks over compile time checks? Best regards Stefan -- Stefan Marr Software Languages Lab Vrije Universiteit Brussel Pleinlaan 2 / B-1050 Brussels / Belgium http://soft.vub.ac.be/~smarr Phone: +32 2 629 2974 Fax: +32 2 629 3525 -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Traits expecting interfaces implicitly leads to expensive runtime checks
Personally, I believed that traits are a *compile time injection* to a class, so that at runtime a class behaves completely as it would if trait methods were implemented directly in the class. That said, everything like trait requirements for a certain interface, should be done at compile time and constructions like abstract foo(); in a trait serve that purpose. IMHO. 2010/12/10 Stefan Marr p...@stefan-marr.de Hi Nathan: On 09 Dec 2010, at 23:42, Nathan Nobbe wrote: What I'm getting at is the scenario when a trait is designed to be used in concert with the class in which it is being used. In this case the trait expects certain functions to be available on the class in which it is used with. If the methods aren't there (or checked for at runtime) a fatal error is raised. A quick example ?php class A { use AHelper; function blah() {} } trait AHelper { function meh() { // hoping we get used w/ instances of A ... return $this-blah() * 5; } } class B { use AHelper; /// waiting for a runtime error if blah() is ever called .. } ? Do you see what I mean? No, do not really see what you are getting at. How is your approach using the instanceof checks (from the first mail) different from changing AHelper to require blah() by stating this requirement using an abstract method definition? For the trait it is not important where that method is implemented, it just has to be in the final composed class. So, why don't you want the following trait? trait AHelper { abstract function blah(); function meh() { // hoping we get used w/ instances of A ... return $this-blah() * 5; } } You want to avoid the fatal error during runtime, right? Do you prefer dynamic checks over compile time checks? Best regards Stefan -- Stefan Marr Software Languages Lab Vrije Universiteit Brussel Pleinlaan 2 / B-1050 Brussels / Belgium http://soft.vub.ac.be/~smarr Phone: +32 2 629 2974 Fax: +32 2 629 3525 -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php -- С уважением, Виктор