DataFaucet, onTap and setProperties()
I often find myself amazed at how today's "new breed" of ColdFusion programmers are not only willing to sacrifice simplicity for no reason, but seem to actually prefer things to be outrageously complicated... a lot like Java. And really I think the only reason for it is because of unwarranted Java love. That's not to say that there aren't good things in Java. There are indeed good things in Java, however, the ColdFusion community in recent years has been unfortunately influenced by a halo effect, causing us to largely avoid the good parts of Java and acquire the bad parts or to acquire techniques that aren't appropriate for ColdFusion in spite of being perfectly appropriate for Java... leaving us with the worst of both worlds. See for example Ray Camden's recent frustration with JBoss (in the comments). The kind of frustration Ray demonstrates here is the crux of it, where he points out that "things don't *need* to be this difficult" (paraphrased).
And this is even after Sean Corfield himself no less, a man who is single-handedly responsible for a LARGE amount of popular technique in the ColdFusion community and who genuinely dislikes Ruby, recommended that perhaps the ColdFusion community ought to be spending a little more time paying attention to the Ruby community's thoughts about "beautiful code". Don't believe me? Check out Design Patterns and ColdFusion.
I talked about this a fair amount when I posted a previous blog entry on the onTap framework blog about duck-typing. And that's actually where the setProperties() method came from. SetProperties() is a method I've used in my "ducks" for a long time to provide a simple and elegant way of setting multiple properties for a given object with a structure or a query. Of course it also has a comparable getProperties() twin for returning all the defined properties of a given object. These have been supported aspects of the onTap framework for a long time even before there was DataFaucet and of course they've become supported parts of DataFaucet also.
Yet in the rest of the community I continually see people writing blog entries where they're going round and about in circles over "when/where/how do I set my properties on this object?!" Not only are they going round in circles over it, but they're often even excited to be doing it! I was recently reading one such article on the blog of Jason P. Dean where he was talking about using Transfer's getMemento() function and it turned out that not only was getMemento() not officially supported, it actually changed suddenly shortly after the blog was posted. And then today Scott Stroz posted an article on the Alagad blog titled Transfer, Model-Glue and makeEventBean(). You see where this is going don't you? :)
(Please note that this is not intended to be derogatory toward either Jason or Scott, they're both smart guys. I'm simply trying to make a case here and these were useful examples for my case.)
At the end of Scott's article he says "It has saved us quite a bit if time, and code." And what he's describing is a system that's still an order of magnitude more complicated than the way onTap/DataFaucet ducks work. And it is that way largely because Transfer and Model-Glue both see problems through the lens of Java and are therefore unable to see how much simpler things could be if they weren't carrying around all of Java's dead weight all the time.
Here's a relevant snippet of Scott's code:
<cfset var company = getCompanyService().getCompany( arguments.event.getValue( "companyID", 0 ) ) />
<cfset user.setCompany( company) />
<cfset arguments.event.makeEventBean( user ) />
He then explains how you can simplify this code by creating yet more code as a decorator for your transfer object with functions like this:
<cfargument name="companyId" type="numeric" required="true" />
<cfset var company = getTransfer().get("company",arguments.companyId)>
<cfset setCompany(Company)>
</cffunction>
And here's the equivalent of Scott's code (all of it) done with onTap and DataFaucet:
<cfset user = request.tap.getIoC("myapp").getBean("User").read(attributes.userid) />
<cfset user.setProperties(attributes) />
There are no bloated or complicated decorators in play here. There isn't any need for confusing method names like makeEventBean() (what the heck is that supposed to mean anyway?!) The most complicated part of this is the getIoC() and getBean() (instead of getUserService()), which isn't even part of what he was demonstrating, they're just different approaches to fetching the user object.
All the OO "purists" in the CF community ultimately always come around in the end to a solution that is similar if not darned nearly identical to the onTap/DataFaucet solution with one exception: it's needlessly overcomplicated. Scott's Model-Glue/Transfer article is merely another example. In the end, Scott created a system that would do what DataFaucet's "active record" objects do... but in order to get there, he had to create a decorator for his transfer object and a bunch of other tedious and overly complicated things... In essence he's just run a marathon and said "wow, look how I didn't have to run all the way across the continent! That was so much easier!" Of course, he hasn't realized that he could have just skipped the running all-together and casually strolled next door.
UPDATE: Minutes after posting this blog, I received an email from Twitter to let me know that Scott Stroz started following me. Coincidence? I wonder if that's because he wasn't offended or if it's because he's contemplating Sun-tzu's advice to "Keep your friends close, and your enemies closer." :)

DataFaucet actually does it both ways (I'm guessing FourQ might also) where you've got get/setProperties() which does a batch and then you've also got get/setValue() if you just want one of them and those are used under-the-hood by get/setProperties(). And then create() and update() take in an optional struct of new properties to set so you can set and commit at the same time.
Before it was called DataFaucet, this ORM included an XML schema for executing DDL to create tables and the like. It's only been recently that there've been features added to the "active record" objects that allow you to specify the schema there, so you can have objects that are "auto-installing" in a manner similar to FourQ. I was talking with Jeff Coughlin about it recently and hearing about the system of using cfproperty tags and I've given some thought to adding that as another extension so it would build the XML from the property tags to generate the create table statement. Of course I haven't gotten around to implementing that. :)