DataFaucet ORM!!!

DataFaucet is an ORM tool.

Why DataFaucet? Well two reasons, first it originated with the onTap framework and I like the pun.

Secondly the goal of DataFaucet is to make ORM as easy as getting a glass of water from the tap in your kitchen.

Another ORM? Really? Why?

To give you a little history, my friend Doug Boude, who's been doing a lot of work with Model-Glue in the past couple years had posted a blog the other day about his experiences with ORM. I can't say that I "feel his pain" because honestly, I've never worked with any of the recent ORM frameworks for ColdFusion outside of my own. But my own is an integrated part of the onTap framework... and perhaps largely as a result of that, few people have really looked at it. Doug had asked me once a couple years ago if I could split it out into a separate project - actually several people have over the years - and I've always replied "yes", but just never bothered to do it. So when Doug asked, particularly after having just finished the first draft of the Galleon ports project, I decided to go ahead and split it out for everyone. Doug of course wants to use it with Model-Glue because that's the framework he and his team work with. And that's fine. OnTap has always been open source, so I never had any objection to that, but nobody else was undertaking the task of splitting it out.

A year or so ago I found myself explaining some of the features of the SQL abstraction library to a coworker who said to me "you know Transfer already does all that"... umm... sure... and Transfer wasn't even a twinkle in Mark Mandel's eye when I started working on my SQL abstraction tools... and it's as far as I know still not as robust. Nor is Reactor, in spite of Sean Corfield's comment when I spoke at cf.Objective a couple years ago that it "reminded me of the things we can do with Reactor". I'm not saying this to be derogatory here, I'm just trying to establish a baseline. I started working on ORM with ColdFusion 5, before there even were CFCs. At the time it was HIDEOUS and SLOW and required custom-tags as its syntax. But it did work. It wasn't until much later after the release of ColdFusion MX that I grabbed up the Java API docs and learned how to work with JDBC through reflection and wrote the cover article for the ColdFusion Developer's Journal titled Leveraging JDBC or Just Fetching Coffee. That article, my first for the journal, almost didn't get published. When I originally proposed it the editor at the time felt it would be too advanced for the average ColdFusion programmer. Someone else recommended that I reword the proposal and resubmit it and I suspect they also put a bug in the guy's ear themselves and it got accepted and made its way to the cover. Where it quickly became one of their more popular articles. As far as I know that was still before either Transfer or Reactor had been conceived. It wasn't until still a while later that I finally rewrote the entire SQL abstraction library using CFCs instead of custom tags.

What struck me about Doug's comments about their experiences with ORM is that none of the things he described as being major headaches with their choice of ORM would have been an issue if they'd been using the onTap framework. And that really may have been the thing that finally convinced me to go ahead and do the leg-work to separate these tools for everyone. It is a little more work than I'd expected, but not much. I'll be done with the initial draft in a few more hours.

Two of Doug's comments in particular are especially important to note here. The first is his comment about what he calls "gluttony" -- the ORM components being "resource hogs" and slow as hell... While I've never been the first to champion the cause of performance tuning, I told Doug that, "gee when I tested them, they only added about 35ms per query over the top of Ray's original ad-hoc sql" (from Galleon) -- which he said sounded reasonable, leading me to believe that it's more efficient than the ORM they chose. That's really interesting because the ORM they chose was a code-generator like Reactor or I presume Transfer. I don't know which one they chose. But the conventional wisdom is that generated code is more efficient... apparently except when compared to mine. DataFaucet will not be a code-generator -- it abstracts SQL on the fly at run-time, and in truth, a number of its features like and/or keyword search filtering could not be accomplished with generated code.

The second thing and probably more important than the performance question, is something I'll actually quote from Doug's blog:

And ah, the grandest reason of them all that I pretty much despise ORMs: losing my beloved sql. Now, I wouldn't have a problem with losing sql as long as my ORM provides me with a suitable substitute. But it does not. The task of translating a simple sql statement into "ORM-speak" is far, far from simple, my friend. I and others I know have quite literally spent an entire DAY trying to figure out how to write the code, leveraging our ORM, to execute a simple join.

You mean like this?

<cfscript>
statement = ds.getStatement("select").init("products"); // query the product table

cat = statement.join("productcategories",true,"productcategoryid"); // join the category table

cat.filter("productcategoryid",rc.productcategoryid); // filter products by category

query = statement.execute(); // run the query
</cfscript>

hmmm... makes me wonder what ORM-speak looks like... must be hideous... which brings me back to the name... DataFaucet -- relax, have a drink. :)

I actually wrote an article that's included with my ports of Ray's Galleon Forums about having converted Ray's business objects to use the DataFaucet CFCs and cataloged all the changes in an Excel spreadsheet. Overall I found that in addition to a goodly amount of decoupling (it's not limited to the big-4 databases anymore), I was also able to remove about 600 lines of code with a negligible change in performance. In fact, it's unlikely you would even notice the difference as a forum user.

Anyway, all this stuff is already built -- it has been for a while now... all I gotta do is decouple a few leftover helpers (half of which were holdovers from CF5). The other half were just because I didn't want to duplicate code. Although I'm going to have to put up with some duplicated code because if I'm going to support both projects then I'm not going to branch the code, I'm gonna have to rewrite some of the onTap framework core to use the new version of DataFaucet.

UPDATE: So it's actually approved on RIAForge now. There's some code in the SVN repository, but it's in an ugly state right now. You can look, but don't say I didn't warn you. :)

As I've been working on separating it from the framework I've also realized that, as clean and simple as I thought the syntax was before, there are several ways I can improve it even further, so I'm going to be adding some new methods to make those short query builds even smaller as a matter of syntax sugar. For simple queries, you'll be able to do something like <return ds.select(table="mytable",filters=arguments).execute() />. And since the project is already approved (thanks Ray) :) I posted a syntax sample on the DataFaucet blog.

Related Blog Entries

Comments
Sana's Gravatar Hi,
I just had a quick look of galleon port, onTap is quite impressive with huge amount of libraries. awesome work man.
ORM implementation is quite neat and interesting.
does DataFaucet support table inheritance ...or ...?

keep up great work.
# Posted By Sana | 6/10/08 5:53 PM
ike's Gravatar Thanks Sana. The term "table inheritance" is new to me, so I had to go look it up. :) Most of what's involved in single table inheritance is built in ... the only problem with the current structure is that there's no manager class to tell it to look at the value of column-x and instantiate that particular AR class. I would think however that would be a pretty simple thing to do given the structure. I may add a feature to automate that from the Datasource object in the first release of DF.
# Posted By ike | 6/11/08 2:12 AM
Sana's Gravatar I was referencing about hibernate style.
://www.hibernate.org/hib_docs/reference/en/html/inheritance.html

I know you have been doing awesome stuff from long time, surely DataFaucet would be a great step toward more easy/advance ORM in CF.
Looking forward to DataFaucet.
# Posted By Sana | 6/11/08 3:52 PM
ike's Gravatar Oh that's why I have a headache now after reading the first couple paragraphs of that URL -- you sent me directly to a Java project. :P

I'm not sure how their config files are laid out off-hand, but yes, some of that is currently available in the ActiveRecord CFC and some of it isn't, although it might get added later if people want for example join-subclass, which I'm assuming means that it joins a table or 2 extra when it reads & writes the data for objects of that class. Although at least in its current incarnation, DataFaucet has no XML config files to deal with, you just instantiate an ActiveRecord object and declare its table -- or you extend the ActiveRecord object, it's up to you.

Anyway, thanks for the complement. There should be a beta release of DF pretty soon.
# Posted By ike | 6/11/08 7:13 PM
ziggy's Gravatar Is it using java methods that are missing in Bluedragon/Railo? Any word yet if it can be used on open-source engines? Would be a great addition seeing as Transfer doesn't work on them.
# Posted By ziggy | 8/19/08 12:50 AM
ike's Gravatar Well the internals use the ServiceFactory object and I know someone told me they were able to get my code from the JDBC article in the ColdFusion Developer's Journal to work on Railo, which surprised me honestly... So it's not out of the question, but right now it just supports CF7/8. I would lean in the direction of it being more likely to run on Railo, although that's just a hunch, it's not based on any kind of inside information or anything... I'd like it to run on all 3 (would be nice if the onTap framework did too), although it's liable to require contribution from folks who spend more time working with Railo and BlueDragon as I've not been able to find the time to make them run on the other CFML engines. I have been rather impressed with the Railo announcements in general though. Got to meet Gert at the Boston CFUG a week or so ago.
# Posted By ike | 8/19/08 1:26 AM
BlogCFC was created by Raymond Camden. This blog is running version 5.5.006. | Protected by Akismet | Blog with WordPress