Traits are Includes!
As part of the Great New Code To Come (some call it GForge6.3), we’ve been looking at several improvements to our technology stack, not the least of which will be moving to PHP 5.4 or 5.5. Traits are an interesting new construct, neither Interface nor Base Class, that I’ve been trying to factor into the Great New Code. I’ll admit that I’ve been kinda stumped about why traits are cool. Well, that’s because it turns out they’re probably not.
Benjamin Eberlei got things started with a good, objective analysis of the trait feature. Boiled down, his argument is that if you can derive the same benefits of a trait using a class and static method instead, then traits are really the same tool with a different handle. And I agree, but I think it’s even worse. If Benjamin’s associative analysis is valid, then traits are actually just include/require statements with the trait {} wrapper around the functions.
Consider this example from the article:
Here’s Benjamin’s equivalent, rewritten for static methods:
And here’s the same thing as an include, without the trait/class wrapper:
Yes, there’s extra plumbing in there, because PHP does not allow random includes in the middle of a class declaration. And while it’s klunky to look at, it serves exactly the same purpose as a trait – shared implementation without inheritance (or aggregation, which IMO would be the right solution here). Other than being klunky, it seems no less reusable, testable or readable than traits (but again, not as good as aggregation).
So: IF you hate this code, AND it’s functionally equivalent to traits, THEN maybe traits aren’t so great either.
Maybe I’ve missed the point, and I would love to hear about that. I don’t think I have. In fact, I think this is a good example of how sneaky and pernicious the “new” can really be. How easily we can be dazzled by something slick that does the same job as the old tool we already have. But relentlessly adding new things leads to cruft, to redundant and fragile features. For example, I spent a couple of hours last week removing all of the ereg() calls from our code base, in favor of preg_match(). Over time, too much “new” can de-stabilize a solid product, as we have seen in PHP (and others, of course).
Instead of adding new (and arguably redundant) language features, maybe we should stay focused on harnessing what’s already there. A great example for PHP would be the array_column function coming in 5.5, that lets us easily process the arrays that are central to PHP’s power. This is code I’ve written before and will be happy to retire. And it’s not a new feature, but a deeper usage of PHP’s powerful array handling.
Dynamic languages like PHP and Javascript have been incredibly popular for many years, but much of their usage has (unfortunately) conformed to Sturgeon’s Law. With better understanding and application of the basic language features, we now have tools like Composer, Doctrine, and KnockoutJS – tools that largely insulate us from the Fractals of Bad Design. I am more excited about PHP than I’ve been in several years, because these tools also drive me to better understand and apply those same language features. I’m looking forward to Great New Code.