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.