DataMgr is Better than ColdFusion ORM
I have been thinking this for some time, but it seemed like hubris (and flame bait) to say it. So be it - it needs to be said. I worry that ColdFusion ORM is being / will be marketed where it isn't appropriate.
What is Better?
It can't be helped, "better" is a word that only makes sense in the context of goals to be met. After all, it is impossible to tell if a sedan is better than a truck unless you know your goals. Do you need to get to work on low gas mileage or haul cargo? I will use the criteria that Adobe ColdFusion engineer, Rupesh Kumar, has laid out in "ColdFusion ORM - An Evolution in building datacentric application":
- [Dependency] Database vendor dependency - The queries that are written are DB specific. If you ever need to switch the database or if you need to make the application database agnostic, it becomes too much of pain. You will end up changing the entire application code or lot of conditional code to handle queries for different databases.
- [Coupling] Very tight coupling with the database - The queries have very tight coupling with the database. This means that if there is any change in the table name or column name, you will end up with changes all over your application code.
- [Repetition] Repititive and hence low on productivity - For any CRUD (Create, read, update and delete) operation, you need to write queries which are more or less same for all the tables. You must have felt that you are repeating the same code everywhere in the application. There is too much of repititiveness which reduces productivity.
- [Errors] Error prone - How many times did you write insert/update queries and then you had to struggle to debug because the order of column and its values were different? And how many times did you get frustrated because there was a datatype mismatch between the value you had specified and the one expected? How many times did you write a query that was prone to sql injection and you were reminded to use query param? I am sure all of this has happened to all of us and its completely natural given the way queries are written. They are error prone.
So, do how do ColdFusion ORM and DataMgr stack up on these goals?
- Dependency: Both allow you to write database neutral code.
- Coupling: Both help with this, but each will result in code that references database table and column names.
- Repetition: Both greatly reduce repetition.
- Errors: Both solve this issue in much the same way.
ORM or DAL?
Note that what is not on that list is "Map Objects to a Relational Database". Where that is a criterion, an ORM is the solution (after all it is Object Relation Mapping). DataMgr isn't an ORM, so ColdFusion ORM is a better solution where that is a problem/requirement. Where it isn't, however, DataMgr is the better fit.
DataMgr is better (as a Data Access Layer) because it isn't an ORM. (see also Ike Dealey's blog entry on Pros and Cons of an ORM).
If you are doing pure OO development, an ORM is great (but the reality is that many of us are not). If you aren't, it presents some challenges:
What's Wrong with ORM?
Availability
DataMgr is available now and will run on versions of ColdFusion stretching back to ColdFusion MX 6.1 as well as Railo and OpenBD. ColdFusion ORM is part of ColdFusion 9, so you will have to wait until then. It may be included in Railo or OpenBD later as well, but in any event, it isn't available in full release yet.
Existing Table Structure
Hibernate (in particular) has opinions about table structure. If your table structure doesn't match how it things tables should be arranged, you have extra work to do.
"Stop Thinking About the Database"
Development using an ORM is supposed to make you "stop thinking about the database". A fine thing except that most ColdFusion applications are all about the database. Often any problems will be met with that perspective (this isn't a criticism of those who give that advice, but rather a reality of the tool itself).
SQL Execution Timing
The SQL doesn't execute immediately in Hibernate, instead executing at the end of a Hibernate "session" which almost matches a ColdFusion request. This means you have to start thinking about Hibernate sessions.
- ColdFusion 9 ORM - Explaining Hibernate Object State
- Learning ColdFusion 9: When Does An ORM-Enabled Object Get Persisted
- Some thoughts on ColdFusion 9 ORM and Persistent CFCs
Extra Code
You have to write extra code in ColdFusion ORM (compared to DataMgr):
As an example, consider a Contacts table with the following fields: "ContactID, FirstName, LastName, Email, Phone" being updated with the following structure {ContactID=1, FirstName="Steve", LastName="Bryant", Email="steve@example.com", Phone="918-555-1212"} (which I'll call "sData", but could come from a Form post or Arguments scope, for example.
(I'll skip the Application.cfc settings and the single line to instantiate DataMgr as those things are done just once per application.)
To save a record with ColdFusion ORM, first need a CFC:
In fairness, I don't call this a drawback of ColdFusion 9 ORM because I would use a CFC with DataMgr myself and the code is minute here (assuming you are willing to let ColdFusion 9 introspect the table).
Then the code would be:
<cfset oContact.setFirstName(sData.FirstName)>
<cfset oContact.setLastName(sData.LastName)>
<cfset oContact.setEmail(sData.Email)>
<cfset oContact.setPhone(sData.Phone)>
<cfset EntitySave(oContact>
(note that is just for 4 fields, imagine how much longer a real world scenario would be)
To do the same thing in DataMgr would be:
I should note, however, that you could use Bob Silverberg's Base Persistent Object to get this syntax:
<cfset oContact.populate(sData)>
<cfset EntitySave(oContact>
Single Datasource
ColdFusion ORM allows you to use only one datasource per application. While each instance of DataMgr can use only one datasource, you can have multiple instances of DataMgr in one application (as many as you like, in fact). (Update: Multiple Datasources is available in ColdFusion ORM as of version 9.0.1)
Access to Source Code
DataMgr is written in CFML. You can extend it yourself. Or, if you find a bug, you can fix it yourself. With ColdFusion ORM, even if you find a bug you will have to wait for at least a hotfix to install in ColdFusion itself (not quite as easy as updating a .cfc file).
The "N+1 Select Problem"
ColdFusion ORM is more likely to run a query and then another query for every row in the first query than is DataMgr, which only does this for "list" relation fields.
Learning Curve
Most of these issues can be summarized by quoting a comment from Ben Nadel "It looks like we are really going to have to know a bit about how Hibernate works to really leverage this integration efficiently. - we can't just start using it blindly." - Learning Hibernate is a big undertaking. I would argue (keeping in mind that I am biased) that DataMgr is much, much easier to learn.
What's the Flip Side?
Of course, ColdFusion ORM has its advantages over DataMgr as well.
OO
If you are doing pure OO, then you should probably use an ORM. ColdFusion ORM is an ORM, but DataMgr isn't. Case closed.
Tested
ColdFusion 9 will be the first version to include the ORM, so expect some bugs (with the ColdFusion piece - not Hibernate itself). Even so, it has probably gotten more use and testing - already - than DataMgr has in its nearly 4 years in full release. ColdFusion ORM is also built on top of Hibernate which has a massive user base. Expect fewer bugs in ColdFusion ORM than in DataMgr.
Paging
As of now, paging is supported (by use off an "offset" argument) in ColdFusion ORM, but not natively supported in DataMgr. Of course, that is a known and fixable issue... (Update: Efficient paging is available in DataMgr 2.5)
Features?
I know ColdFusion 9 has plenty of other features (as does DataMgr), but I think most of them are specific to an ORM (which DataMgr isn't) and so not really valid for comparison. I think DataMgr makes many things easier than ColdFusion 9 ORM, but I have too much bias and not enough experience to make any valuable commentary on that.
What Else?
Then again, I've changed my mind before...
In the meantime, DataMgr is open source and free for any use if you are interested.
Links:
Learn More about ORM
- ColdFusion ORM - An Evolution in building datacentric application
- ColdFusion ORM : Performance tuning - Lazy loading
- ORM - Rethinking ColdFusion Database Integration
- How Much Should Our ColdFusion Applications Actually Know About ORM?
- Learning ColdFusion 9: Exploring Object-Relational Mapping (ORM)
"Hibernate (in particular) has opinions about table structure. If your table structure doesn't match how it things tables should be arranged, you have extra work to do."
Well sure. If you want to use firstname for a column instead of fstname, then you have to tell Hibernate what the 'real' column name is. But frankly, you would only do that to improve the code in general. Ie, if you think fstname is a bad name (we've all seen horrible table/column names) then defining the alias in HIbernate is a _good_ thing. It's worth the extra 'work' (2 seconds ;) to provide a cleaner, nicer column name. The fact that you can do this is a HUGE win for ORM imho.
"Development using an ORM is supposed to make you "stop thinking about the database". A fine thing except that most ColdFusion applications are all about the database."
Right, and that's a mistake that ORM can fix. Just because many CF apps have been 'all about the database' does not, and should not, mean it should _stay_ that way. Frankly I'd much rather be concerned with business logic than table names.
"The SQL doesn't execute immediately in Hibernate, instead executing at the end of a Hibernate "session" which almost matches a ColdFusion request. This means you have to start thinking about Hibernate sessions."
I agree with you here. This is something you have to be concerned about. Frankly it is the biggest issue I can see with going to ORM. However, I do think the benefits far outweigh the mild 'penalty' here of having to think about Hibernate sessions.
"Single Datasource"
Point taken - but I've rarely, if ever, used more than one DSN. And - you CAN use ORM if your site has 2-N DSNs, you just have to restrict the ORM usage ot one DSN. I believe in most cases where you have multiple DSNs, you still have one core DSN for most of your content, and other DSNs for auditing or security. So I'd just apply ORM to the main content DSN.
"If you are doing pure OO, then you should probably use an ORM."
I'm sorry, but OO has nothing to do with learning ORM. Just because you write a CFC to use ORM does not mean you are using OO. A person with no knowledge of OO at all can easily grasp the idea of: My component is a table, each property a column. Yes, you work with entities and methods, so you can consider this pretty light OO, but I don't think it is fair to say you must be using "pure" OO to use ORM. "Pure OO" means so many things to many different people, I don't think then this is a fair statement to make. You need not know nothing of design patterns or frameworks to write a simple CFC.
Thank you for hammering this point.
Thanks for the feedback. I knew I was bound to miss on a few points. Always good to learn.
My statement about table structure had nothing to do with column names. It was really drawn directly from Ben Nadel's experience (I linked to his entry in that section).
As to thinking about the database, I definitely see your point but in CRUD apps it looks (to me) like the whole "you aren't supposed to think about the database" thing just makes life harder. I certainly don't think you think about table names any more with DataMgr than with ColdFusion ORM.
As to "If you are doing pure OO, then you should probably use an ORM.", you are definitely right. I really just meant that an ORM provides real advantage over a non-ORM DAL (like DataMgr) when you are doing "pure OO". Again, I agree that is a slippery concept and one I didn't want to tackle in this entry.
My point is that use of CFCs does not mean that you will get a savings out of ColdFusion ORM. Use of bona-fida objects, however, may.
Thanks for the kind words. That is exactly what I think as well (the impetus, in fact, for this entry).
About your code block, to be fair, if you used 4 lines to set sData values, then 4 lines to call the methods, I'd skip the sData step completely.
I'd use code like this then, which takes out the unnecessary step of copying data to a structure.
cfset oContent.setFirstName(whatever)
At that point it becomes the same as DataMgr, right?
Just for info, there is a error in your ORM code;
EntityLoad('Contact',sData.ContactID) will return an array of objects, in this case, an array with one element.
P.S. I'm also being blocked as spam - hence the 2nd comment :)
First of all, sorry about the spam trouble. I messed up a regular expression. I think I have that fixed now.
I used "sData" to avoid choosing a scope. Since every scope in ColdFusion can be treated as a struct, I think of this as one of the major strengths of DataMgr.
Normally I would use a saveContact method and use something like this:
Application.DataMgr.updateRecord("Contacts",arguments)
If you are going to have a bunch of "set" methods anyway, then I would argue that you may be in a situation where an ORM is a good match.
Even so, if you save all of those to variables.instance (for example), then you could still use:
Application.DataMgr.updateRecord("Contacts",variables.instance)
That is no more work that ColdFusion ORM (except that you don't need an EntityLoad call).
Thanks for the correction. I have corrected my entry accordingly.
That still makes it 3 lines for ColdFusion ORM to 1 for DataMgr (not that reduction in lines of code alone makes for a superior solution).
It wouldn't surprise me at all if that made it into ColdFusion ORM before full release - making it closer to DataMgr ;)
When you say that a person with no OO knowledge can use Hibernate with no no matter at all you are completely wrong.
I am not talking of easy application to show how to save a record but I am talking about complex app that will require a huge OO understanding in order to manage hibernate properly.
Hibernate is the most huge JAVA framewrok I have ever seen and took me years to know that in a good manner....do not make it to easy cause is not.
@Steve - Thanks for the comparison. I know that we (DataMgr users) are in the minority, but I believe the DataMgr concept is a seriously good alternative approach to any ORM solution - especially the CF ORM.
In fairness, I think Ray was just saying that you don't have to use "pure" OO in order to use ColdFusion ORM. Even so, I agree that ColdFusion ORM looks (based on several blog entries that I have read) to be more difficult to learn and use for real-world development that it at first appears.
Randy,
Thanks. I'm sure it won't surprise you to learn that it was you I was thinking of when I mentioned the single datasource restriction.
I had considered using the CF ORM on my next project but that is off the table if I can only use one DSN. There are plenty of valid reasons for more than one DSN on a single application. What if I have more than one server (i.e. some data in MSSQL and some data in MYSQL)?
I really like Coldfusion, but it seems whenever a new features is added it is also crippled in someway. CFREPORT anyone?
Adobe usually updates/fixes this later, but why release half of a feature?
If I've read this thread wrong and multiple datasources are possible then please correct me.
I was actually looking for your CF DAL/ORM comparison entry because I just pushed a version 1.1 Release Candidate of DataFaucet with the new persistence service feature, which means it's no longer a BER feature (like it says in that comparison chart).
From the looks of it, the persistence service in DF will be significantly simpler than the Hibernate integration in CF9. Honestly, I'm mildly surprised at how complicated the new Hibernate features look. The Hibernate sessions thing is the wierdest one imo and liable to cause the most confusion and problems in the long-run... at least of what I've seen. What happens if there's an error on the page? Does the Hibernate session still execute its changes or does it abandon them? I could see either choice causing headaches. DataFaucet has no "sessions" concept, it just updates the datasource as soon as it can. Which is immediately for relationships on previously saved objects, or as soon as the object is saved otherwise. The convenience of structure population is built-in to the save() method (much like the rest of DF), and multiple DSNs have been supported since the very beginning. ;)
It does currently have the N+1 problem though... I may go back and tweak it so that the getArray() method uses a single query to populate all the non-cached objects in the array instead of querying for each one. It may be slightly challenging, but it should be possible. The challenge has more to do with working the reads around the possibility that some of the objects in the array may already be cached.
Anyway there's a blog about the new release here: http://datafaucet.riaforge.org/blog/index.cfm/2009...
And the documentation for it is up on the DF site here: http://www.datafaucet.com/persistenceservice.cfm
I've been having fun playing around with the maze game I created as a sample application. :)
Oh and I got this weird error from your "contact us" form on the Bryant Web Consulting website... I think you used a cfcatch with an "any" type instead of a custom type for your form validation. It says "We're Sorry. Some information is missing or incomplete: The CHECKCASE argument passed to the numRegExMatches function is not of type boolean." Didn't seem like something I could fix by changing the form inputs. ;)
Thanks for the heads up on DataFaucet 1.1. I have been a bit busy and so I haven't kept up with the outside world very well.
I think many CF project do not need ORMs. For the many that do, however, I still think that they should investigate options such as DataFaucet and Transfer for just the reasons you mentioned.
Sorry about the spam filtering. I am planning to redo that in the near future. Contact form is fixed now - thanks for the heads up on that.
I did update the DAL Comparison page. Let me know if I missed anything and I will correct it.
not only scopes, forms etc are structure: i pass the memento of any instance of any class in my project, the table which such instance is to be
persisted in, and your dataMgr save it: too simple!
i use a generic data layer, with an instance of dataMgr injectd, with a numbr of methods: ie, i simply pass a bean and a table as arguments to these and all is done.
dataMgr is a great tool.
salvatore
I just rolled datamgr into my rig (kinda like datamagr.... 'cept I use an abstract service cfc in front of the default Illudium templates). It took me a whole 15 min to swap out an Illudium based back end to Datamgr...
Dude! This is insane. I just swapped out my entire database layer in 15 min. OOP's. (pun intended) Gotta love it.
I am running datamgr on Railo OS and it is *disturbingly* fast. Thanx for taking the time on that!
G!
Thanks! I would guess some of ease you found was due to how well Brian architected Illudium, about which I have heard nothing but good things.