DAOs and Gateways in ColdFusion
Some thoughts on Data Access Objects and Gateways within ColdFusion, and whether or not we really need both of them?
What are DAOs and Gateways?
Firstly a quick overview of what these are:
Data Access Object and Gateways are the names given to ColdFusion components that access information from a database or other external data source. Within the ColdFusion community DAOs and Gateways have pretty much taken on the meaning as follows.
What is a DAO?
A DAO is used for manipulating single records at a time for a given table; specifically a DAO has methods for creating, reading, updating and deleting a single record. But the key point is that it only ever deals with a single record at a time. For example, you might have a person table which has a corresponding PersonDAO.cfc which knows how to access single records within that table. For this example, the functions might be:
PersonDAO.cfc
init(datasource)
read(personId)
delete(personId)
create(person)
update(person)
Sometimes, the create and update can have their access set to "private" and hidden behind a public save() function.
Some example code that uses a DAO might look like
<cfset person = personDAO.read(1)>
<cfset person.setLastName("smith")>
<cfset personDAO.update(person)>
What is a Gateway?
A Gateway on the other hand is for dealing with multiple records for a given table. Typically this is used for reading multiple records. There is no nice pattern for the names of the functions here and really can be anything that you like. Using our person table as an example again, our PersonGateway might contain functions such as:
PersonGateway.cfc
init(datasource)
readAll()
readAllWithLastNameLike(string)
With Gateways it seems to be very common for the functions to return a ColdFusion query object, which can them be easily looped over using
Some example code that uses a Gateway might look like
<cfset peopleQuery = personGateway.readAllWithLastNameLike("s*")>
<cfloop query="peopleQuery">
<cfoutput>#lastName#<br></person>
</cfloop>
Do we really need both of these?
Even though DAOs and Gateways are almost always mentioned together I wonder if we really need both of these?
The DAO is a very nice pattern for single record access and the Gateway is a nice place to put all multi record data access, but would it really matter much if they were in one object? Then we would have only one object that was used for all associated data access and it doesn't seem a big deal that some functions deal with single records and some functions deal with multiple records. The point is that one object can contain all of the knowledge of the relevant external data.
Martin Fowler's book on patterns describes a Gateway as 'an object that encapsulates access to an external system or resource'. Specifically he refers to a Table Data Gateway as 'an object that acts as a Gateway to a database table. One instance handles all the rows in the table'.
From the Java world there is a Data Access Object pattern which seems to be implementing something similar.
So for the sake of choosing a name for this object, I will use the term 'Gateway' - which appears to be a more generalised pattern.
So our PersonGateway now combines all of the functions of the original DAO and Gateway together:
PersonGateway.cfc
init(datasource)
read(personId)
delete(personId)
save(person)
readAll()
readAllWithLastNameLike(string)
What do you think?

I'll be watching the comments here - be interesting to hear from the experts!
It seems that the main argument there is about Gateways returning ColdFusion Queries (recordsets) vs DAOs returning objects.
I am also is favour of returning objects over recordsets. In particular I return arrays of objects (trying to move away from this) or iterators (seems a better approach) for multiple records. For the projects I have worked on these have been fine.
Yes, great idea to split up your cfc's - one objective being that 'each object does only one thing and does that one thing very well' (I am sure I have read that phrase at least 100 times - it seems to have stuck).
Your PersonGateway (or PersonDAO) object focuses on the complexity of dealing with the database, a PersonReport object might use your PersonGateway to extract data to generate a report, while your Person object focuses on just simple Person specific functions.
directory.cfc
- init(DirectoryId)
- get()
- update(fields)
- createFile(fields)
- getFiles()
- deleteFile(FileId)
file.cfc
- init(FileId)
- get()
- update()
Actually, i love using it now. It clearly identifies the purpose of each object and also where to do/find things when developing.
I place all my dao's and gateway's in the application scope and it works fine.
Does everyone also put these objects in the application scope aswell?
Yes, application scope is definitely the right place for these.
It is best to exclusively lock the application scope when initially creating them but no need to lock when using them (as they are read only after creation).
It is also worth looking into giving ColdSpring a try (http://coldspringframework.org). It might seem a bit complex at first, but is a very nice way to manage all of your DAOs and Gateways.
Regards
Kevan
I just wanted to confirm that it was safe.
I have looked into Cold Spring, and i intend using it in my future projects. It looks really useful.
On quick question, maybe a little of this topic, but in the application.cfc would i need to var all object declarations anbd other variables (request,session and local variables)?
Regards,
Rony
When placing code in the Application.cfc functions, you only need to var variables that are not stored in one of the standard scopes. For example, you don't need to var any variables you set in the application, session or request scope.
Var required:
[cfset var temp = ""]
[cfset var locals = structNew()]
Var not required:
[cfset session.count = session.count + 1]
[cfset application.stringUtil = creaObject("component","StringUtil").init()]
And, locking the application scope is not required inside your onAplicationStart function (locking is auomatically provided there by CF).
Regards
Kevan
For example, suppose you are reading from a Person table which had a firstName, lastName and dateOfBirth fields.
If you are working with a Person component then you might have access too functions such as getFullName(), and getAge().
If you were working with a query directly then you would need to code this into your query loop (or create dynamically as part of the sql statement).
As you mentioned, ColdFusion is unfortunately too slow to create many components for every record of every query executed. So at the moment I am usually going with two options:
1) Just use the query directly (not so bad in most cases)
2) Create an Iterator with a single instance of the component required inside. This single component will be re-used for each record of data.
When you create the iterator you store the query data inside (I actually convert the query to an array of structs which is quite quick). Each time you call next() on the iterator it changes the data within internal component to the next record of data and returns it.
So we get the benefit of component functionality, and only one component exists for the entire set of records.
The disadvantage of course is that you cannot store the component returned by the iterator anywhere because it's data it constantly overwritten.
Hope this makes some sense.
The whole DAO/Gateway as separate CFCs thing dates back to a casual recommendation I made back in 2003 in the Mach-II Development Guide (on livedocs.adobe.com) when I was trying to help people structure their CFCs (when everyone was new to CFCs).
I hadn't intended it to become a rule cast in stone but unfortunately that's what happened.
I certainly don't advocate this separation as a default these days - in fact I tend to put everything in a XyzGateway.cfc (although my single object persistence is usually handled by Transfer ORM these days).
I've constantly been surprised at how literally people have followed some of my old, old advice... :(
Whenever apparent 'rules' present themselves it is easier to jump on board and use them rather than question them. And in the absence of experience or a guide it is as good a place to start as any.
Overall though, I think the best idea to read out of the DAO and Gateway concepts is to separate out and encapsulate data access.
Eventually, I read about this thing called a gateway object in cf and that seemed like it would be a good way to get rid of the door/house problem, so I put that in place. The gateway would return either arrays of objects or recordsets as requested. There was no direct coupling from the bean's point of view. Any beans necessary would be instantiated in the gateway. That seemed pretty good for a while.
After a while, I started feeling that the little CRUD wrappers I had in my beans to facilitate the use of the DAO started to feel strange to me. I would look at those methods and think "they have nothing to do with my business logic and add a lot of noise to my bean code". So, I reworked things again. Now, my beans are completely ignorant of storage mechanisms. Instead of instantiating the DAO with the bean init function, I now pass in the bean to a separately created DAO. It adds a little more code to the software that uses the objects, but you feel a little more in control. You only need to deal with a DAO when you have to deal with your persistence technology.
Lastly, I noticed that now my DAOs and my Gateways where constructed in very similar manners. It felt like I had little reason for keeping them as separate objects. They pretty much do the same job - interact with my database. So, I put them both together. I now only use DAOs. The only reason I chose to use the DAO term instead of the Gateway term is that it just seems a little more descriptive and it's easier to type.
So, that's my trip. I basically ended up with what I started with, although they are built substantially different. I pretty much like the way they work now. Next for me is to look a little closer at the work Sean Corfield has done to create default get/set functions. That will certainly remove a lot of clutter.
However, it did seem nice syntax to have code like
<cfset person.save()>
<cfset postcode = person.getStreetAddress().getState()>
where the 'person' is my bean loaded up DAO and Gateway artillery. But I am trying some alternatives now.
I gave Reactor a run ( http://trac.reactorframework.com ) which also uses the Active Record pattern. This combines business objects with the data layer.
I am now looking into Transfer ( http://transfer.riaforge.org ) instead which separates out the business objects and the data layer.
Sean wrote up a comparison of the two:
http://corfield.org/blog/index.cfm/do/blog.entry/e...
I believe that generic get() and set() functions have special case uses rather than in common application beans. Peter Bell ( http://pbell.com) uses them in his application generator (they are not hand coded) and I would favour using them whenever an object has a range of general name/value properties.
For the general approach I would still favour the setName()/getName() style. If typing all of those get and set statements is a problem, then Transfer or Reactor or something like Brian Rinaldi's CFCGenerator ( http://code.google.com/p/cfcgenerator ) might be just the ticket.
I have just created an iterator base class, that, with very little code under the hood will let you do like this:
o_myDAO.read(args); // depending on the args will get different result sets
while(o_myDAO.next()){
o_myDAO.methodThatActsOnTheCurrentRow();
}
I think the tricky part is keeping the create, update and delete methods un-muddy but I think you could still do this AND have a seperate Gateway component for CUDding.
My temporary conclusion is that the iterator is useful in situations where you would need a seperate instance of an object for each record returned from a query but that this does not replace the 'need' for a Gateway object.
Dom
Great idea. This has some similarities with Peter Bells "Iterating Business Object" idea (http://www.pbell.com/index.cfm/2007/8/13/IBO-Sampl... and the big brother version http://www.pbell.com/index.cfm/2007/6/20/IBO-20--R...)
The essence of Peter's idea is something along the lines of:
o_myIBO = myDAO.read(args)
while (o_myIBO.next()) {
o_myIBO.methodThatActsOnTheCurrentRow();
}
Initially I wasn't convinced that this was such a good idea, but thinking it through more I believe that it is particularly suited to ColdFusion development, primarily due to the potential performance gains, so makes it a good option for iteration.
Incidentally, I understand that the best performance gains are provided when converting the query result to an array of structs inside the IBO (or DAO in your case) and maintaining a pointer to the "current" struct in the array.
Thanks for your thoughts.
I don't see the benefit of using an array of structs over a query though - is it to do with flexibility of data types?. At the moment, the component just uses the query and stores a pointer to the current row and the whole thing is about 50 lines of code so is very unbloated. It could be even less so because I think there should be a plain iterator base class and a BOI should inherit from that.
I've just installed reactor so I'm very interested to see what they do with their iterator (I saw the words GetIterator() somewhere and got excited, oh dear).
D :)
Good luck with Reactor. And keep in mind that you have Transfer available as well (http://www.transfer-orm.com).
It would appear that Reactor is not getting much attention these days. Some important bugs remain unfixed even though patches have been submitted many months ago, and the Trac site has quite a bit of spam that is not being cleaned up :(
But I would be happy to know that I am wrong about this assumption!