Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:51005 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 62496 invoked from network); 10 Dec 2010 22:20:52 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 10 Dec 2010 22:20:52 -0000 Authentication-Results: pb1.pair.com smtp.mail=quickshiftin@gmail.com; spf=pass; sender-id=pass Authentication-Results: pb1.pair.com header.from=quickshiftin@gmail.com; sender-id=pass; domainkeys=bad Received-SPF: pass (pb1.pair.com: domain gmail.com designates 209.85.214.45 as permitted sender) DomainKey-Status: bad X-DomainKeys: Ecelerity dk_validate implementing draft-delany-domainkeys-base-01 X-PHP-List-Original-Sender: quickshiftin@gmail.com X-Host-Fingerprint: 209.85.214.45 mail-bw0-f45.google.com Received: from [209.85.214.45] ([209.85.214.45:47099] helo=mail-bw0-f45.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 20/D1-51279-3C7A20D4 for ; Fri, 10 Dec 2010 17:20:52 -0500 Received: by bwz16 with SMTP id 16so4844659bwz.32 for ; Fri, 10 Dec 2010 14:20:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:received:received:in-reply-to :references:date:message-id:subject:from:to:cc:content-type; bh=4GpMHqu4l/8p3PkvpRcYHKybmEz9ggFa6XerzmZdVHM=; b=nKhyDn3L1TzYJx/V6q3rmyD7otjv6tU7GsATb9nCBs+gZyCKkvTaYEZbSvl+CdVhFV ILZ7nlz4y59In1C+JzyBrnCipsg11IRefyGjSxFe3IDoguCay6IZCWf+VBhQonDaM5uR xvXnHlcUVo9tFJEfl1U1mRpvqj6FLl7a3Wrk4= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type; b=wmrTlY4lLAe93cRqomYLek3M/wXutRJ9X5vN/NQYnz9AkH2Fdg3Z1cBdytY7a808ER lT56pQNUqzg9UrZnYpmHAF4lXGeYymGigNcFH+Lne76SJpiOfyRgcFaFEqhuNg7Y1VHO uNdeYGlkVFMOrRsjg6vC5SwMSX2AnVuSRPmdQ= MIME-Version: 1.0 Received: by 10.204.48.86 with SMTP id q22mr1267381bkf.141.1292019648480; Fri, 10 Dec 2010 14:20:48 -0800 (PST) Received: by 10.204.112.208 with HTTP; Fri, 10 Dec 2010 14:20:48 -0800 (PST) In-Reply-To: <39.F0.51279.8DE920D4@pb1.pair.com> References: <9CD87200-33CB-40BE-A81C-36FD7471F59C@stefan-marr.de> <9A31F2F9-ED6B-4BE5-A6E2-EB4536E8667F@stefan-marr.de> <39.F0.51279.8DE920D4@pb1.pair.com> Date: Fri, 10 Dec 2010 15:20:48 -0700 Message-ID: To: "Matthew Weier O'Phinney" Cc: internals@lists.php.net Content-Type: multipart/alternative; boundary=0016e6d7e10130c791049715c4c8 Subject: Re: [PHP-DEV] Traits expecting interfaces implicitly leads to expensive runtime checks From: quickshiftin@gmail.com (Nathan Nobbe) --0016e6d7e10130c791049715c4c8 Content-Type: text/plain; charset=UTF-8 On Fri, Dec 10, 2010 at 2:42 PM, Matthew Weier O'Phinney < weierophinney@php.net> wrote: > On 2010-12-10, Nathan Nobbe wrote: > > --0016e6d7e101e083a4049714bad3 > > Content-Type: text/plain; charset=UTF-8 > > > > On Fri, Dec 10, 2010 at 12:55 PM, Matthew Weier O'Phinney < > > weierophinney@php.net> wrote: > > > >> On 2010-12-10, Nathan Nobbe wrote: > >> > --0016e6dbe7fb8861a1049712ad63 > >> > Content-Type: text/plain; charset=UTF-8 > >> > > >> > On Fri, Dec 10, 2010 at 11:04 AM, Chad Fulton > >> wrote: > >> > > >> > > On Fri, Dec 10, 2010 at 9:29 AM, Nathan Nobbe < > quickshiftin@gmail.com> > >> > > wrote: > >> > > > On Fri, Dec 10, 2010 at 10:15 AM, Martin Wernstahl < > m4rw3r@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. Again the abstract keyword is there; just not nearly as elegant for naming an entire interface or set of them, when that was your intention in the first place. > 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. > How can you prove your class implements all the abstract methods it claims to - simple, by loading it into the interpreter w/o error. > > 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? I'd be curious to see how interfaces and abstract methods made it into the language since they embrace what is essentially the same concept. And I have tested properly.., the class loads w/o error so it implements any external methods the traits it uses need, guaranteed. If there's a logic bug in one of those methods, then let's hope I've caught them in an actual, meaningful unit test :D -nathan --0016e6d7e10130c791049715c4c8--