There are few people this side of Harry Fuecks who have rode the php design patterns money train as much as I have. In fact, programming patterns have been very good to me: they’ve provided trips to exotic locales, paid for my conference admission, impressed all the hot women…
Well maybe not that last one.
But Alejandro’s recent spate of GoF patterns on DevShed, besides being a blast from the past, made me realize that practicality hangs over my Pattern Bubble like the Sword of Damocles, pointedly showing just how oppressive programming design patterns in PHP are.
Time for a new rule:
“With few exceptions, by the time you deduced what a pattern is from its clever name, you could have just coded it.”
—Terry Chay, 2007
and my original inspiration:
“PHP isn’t Java. Deal.”
—Terry Chay, 2003
[The Flyweight makes an appearance after the jump]
Yep, I’m doing a pattern sell-off faster than today’s stock market drop and this pattern whore has checked into rehab (and this time I’m not going to to come out demanding someone shave my head.)
The Flyweight
You know what really grinds my gears? When PHP articles on design patterns, after quoting the inevitably opaque definition of the pattern, give examples that have no practical use in web development: Flyweight pattern, anyone?
PHP developers would be better served being taught the very similar Singleton Registry pattern with the example being able to reuse database connection objects.
As for a valid use of Flyweight in PHP, I’m scratching my head. I guess if your PHP site had a User object with some nasty-assed property containing an object inside whose total data set is very small (like maybe they had the user’s TimeZone attached to it as an object) and in the unlikely even that the PHP script might load 100,000 of these User objects, then Flyweight would reduce the memory footprint by reusing the maybe 40 or so TimeZone objects.
But returning the same three input html elements? Puh-leez. Is this shit for real? I thought PHP-side form generator and validator classes were so 2005.
(And to skip picking on poor Alejandro for a second, check out this example. What’s with this obsession with three anyway?)
Women and design patterns
I thought I’d bookend this article by talking about hot women again…
“There is no way the flyweight pattern is going to stop a pretty girl from accessorizing.”
—Terry Chay, 2007
Reuse and share the same object my ass! See, now if that wasn’t so geeky, I could use it on a hot girl at a post-conference pub crawl to get a laugh.
Or a slap in the face.
PHP and Design Patterns? Wouldn’t that imply PHP and design? That does not compute… I have to rip on PHP while I can since I might wind up programming in it soon.
Flyweight is great for a lot of caching scenarios. At my company, we have a couple of dozen canonical datatypes in our system, like photos, videos, contacts, favorites, etc. We have a very rich metadata model for each one of these guys. So if a user logs in a views their photos, each photo not only has all of its particular data like it’s name, URL, geometry, camera used for taking it, etc. but also a lot of metadata that is common to any photos. In good OOD, this photo metadata should accessed as part of the photo. So this was an obvious flyweight situation. We cached the metadata and then when building a photo (uh oh another pattern there) a pointer to the metadata is passed. Of course the actual photo only exposes read-only accessors to the metadata.The metadata itself wasn’t that expensive in terms of memory usage, but it is created by parsing an XML file stored in a database. It wouldn’t make any sense to go through that process for every photo on the site.
So what would be the PHP way of doing this? Keep the metadata separate from the object instances? Is it difficult to keep shared data around for the lifetime of an application as opposed to a request or a session?
@Michael:
Yeah because powering sites like Yahoo!, Facebook, Wikipedia, etc. doesn’t impress. 🙂
The reason Flyweight may be very useful in a language like Java and not that useful in PHP is because Java can be multiple threaded and requests can be long lived and reused. In PHP, the latter isn’t possible and the former shouldn’t be true (PHP is slow and abusive).
Also Java uses objects for everything. In PHP, arrays (hashes) occupy a unique state that no amount of SPL will change. (Can you var_export() an object?)
Here is my example:
1) Why use objects at all? Just use an array (bind to property by reference) and move the work to the client class (there is only one).
2) You would probably not load so many photos at a time in a single PHP process. (You can see how Facebook limits the total number of photos per album and Flickr always paginates output no matter what you are viewing).
3) Just because the metadata is separated and reused in your database during normalization, doesn’t mean it has to be reused in PHP. Remember PHP is a glue language that is essentially user-facing so it’s representations work best when they are perceived the way the user sees them.
4) Separate it into two server side queries (one for the photo essentials and one fot the metadata). The latter only gets requested on user action (like a mouseover or a page view).
5) The standard PHP approach: move the hard work to a different layer. (The most common layer is the database itself, but even at Tagged we use a lot of Java for the stuff PHP does shitty.)
I use the flyweight pattern in my project at work (http://www-306.ibm.com/software/awdtools/buildforge/enterprise/) and it has actually helped. When dealing with massive amounts of data it cuts down quite a bit on memory usage.
That said, I don’t use it that much, and I didn’t need a name for the “make managing lots of objects in a single hit not suck” pattern.
While here, might as well respond:
1. Using objects means not only using the data, but the behavior the data inherits elsewhere. Flywheels of database objects can definitely help in specific cases.
2. I completely agree.
3. I disagree. PHP gets used mostly to glue browsers to databases, but as someone who codes a comparatively large application in PHP, it can get used however you want to use it, to sound completely redundant. I would definitely say it didn’t get designed for it originally, but you can code a complex application in PHP without wishing for another language’s features.
4. Well, yeah…
5. I agree with separation of layers, but you can have each of the layers in PHP. What kind of things in particular have you had to push onto Java? Can you give an example?
Thanks for the info Terry and Shawn. I wasn’t kidding when I said that I might be writing PHP soon. I might be re-writing an existing Java app that is pure middleware in PHP. This app is used by > 10 million users daily and is part of a company that is very well known for its use of PHP. They wrote it in Java about four years ago and say it scaled pretty well up to around 10 million daily users. They don’t think it will scale up another order of magnitude because it is stateful. So they figured if they were going to re-write it to be stateless, then PHP was the way to go.
So it’s really good to know PHP’s strengths and weaknesses. Are there performance issues around using objects in PHP, or is it more of a matter of taste to use things like associate arrays and what not in place of objects? In Java, just the opposite is (generally) true.
Michael,
As far as performance and memory control, the Advanced PHP Debugger has done wonders for me in tracking down issues. I’ve found that most of the issues I’ve run across in performance have stemmed from out of control recursion, filesystem calls, database interaction, or library functions that simply run faster if you hand-code them in PHP instead.
Your mileage may vary, but I would say that the difference between using objects or arrays should really lie in what you instead to do with the data they’ll hold rather than the performance implications of each option.
@Shawn: My point is that any one of those reasons is a workaround againt needing the Flyweight pattern which is why, in practice, the pattern is extremely rare in the PHP world. One of the only patterns more rare is the double check lock pattern (for obvious reasons I hope).
@Mike:
There are performance issues and memory issues for objects in PHP4, but I suspect that version isn’t an issue with this particular client. With SPL you can make an object behave a lot like an array except during export.
Be sure to run APD or XDebug on the app with profiling mode on.This will generate valgrind file which will show you where the slowdown is. Optimizing blind is a very bad thing. If they are a Zend shop (they’re not), there are tools in Zend Studio for this.
Remember it’s a really bad idea to do in PHP what has already been solved better somewhere else. PHP is a glue language, it isn’t an all-in-one language like Ruby or Java.
“My point is that any one of those reasons is a workaround againt needing the Flyweight pattern which is why, in practice, the pattern is extremely rare in the PHP world. One of the only patterns more rare is the double check lock pattern (for obvious reasons I hope).”
Okay, that makes sense, then. And yes, very obvious… 🙂