An Architect's View

CFML, Clojure, Software Design, Frameworks and more...

An Architect's View

The DAO and Gateway separation in CFML is nonsense

March 3, 2009 ·

There, I said it! I said it in a post to the cfcdev mailing list and Henry Ho felt it deserved a mention on his blog. The topic came up because John Whish, manager of the Devon CFUG over in England (where I spoke last September on design patterns), is running a series of presentations on OO and patterns for the group. He wondered how to approach the fact that CFers tend to have separate DAOs and Gateways whereas that distinction does not exist in non-CF languages or pattern literature. I feel responsible for that distinction so I replied with my thoughts and an explanation of why I had suggested it nearly six years ago but why I don't think it's good advice these days (and, frankly, hasn't been good advice for years - I no longer had access to the guidelines document that enshrined the advice!). I recommend you read the thread on the Google Group (cfcdev). Henry quotes part of my reply and links to the thread for more detail.

Tags: architecture · coldfusion

31 responses

  • 1 Cody // Mar 3, 2009 at 9:55 PM

    By god I was waiting for someone with some reputation to come out and say this. I have always been befuddled with the whole "5:1 syndrome" as you tagged it. When I first started tackling MachII (and I read that dev guide in question) I felt like it was sooo overkill to have so many objects all really dealing with the same concepts (e.g. talking to the Users table).

    I now work with ActiveRecord (via Rails) on a daily basis and absolutely love its simplicity. Diving into ColdBox and Transfer and back to the DAO/Bean/Gateway/Service approach just makes me want to run for the hills.

    I think all this 5:1 stuff steepens the learning curve for CFers that are trying to get their feet wet using frameworks.
  • 2 Sean Corfield // Mar 3, 2009 at 10:20 PM

    @Cody, I've been railing against the 5:1 syndrome for years... That was never my intent but I sort of overestimated people's ability to think beyond the letter of the guidelines :)

    It's why I removed some example code (while I was still with Macromedia and had access to the source of the document). I found people just copying the example code without understanding it and then running into problems (and blaming the example instead of their lack of understanding).

    At a conference several years ago, I suggested to one CFer that it would take him a few years to get good at OO - and he was incensed, accusing me of calling him stupid. I started doing OO 17 years ago and I'm still learning and still honing my OO design skills. It's a long road but a lot of people seem to think there's a shortcut, a set of rules they can learn and just churn out code without having to think.

    It can get a bit frustrating at times :)
  • 3 John Whish // Mar 4, 2009 at 12:42 AM

    Thanks for you thought Sean, I'll be interested in any comments people have.

    The DAO/Gateway approach is simple to understand and as such I have found that once people get something working, they just stick with it without looking at other patterns/languages or the drawback of this approach, thinking that is _the_ way to write the data layer.
  • 4 Gary Gilbert // Mar 4, 2009 at 1:19 AM


    I always found it serious overkill and tended to delete the gateways when using the wizard to generate code.

    It's nice to hear that others also think the same. When I first saw it been promoted by Macromedia I thought that perhaps I didn't have the depth of knowledge to understand the why of why they were doing it that way.

    In the end I saw it as more work than it was worth and simply ignored it.

    @Sean,

    I took Hal Helms OO test and failed miserably. I've been "trying" to understand OO for over 10 years, but to be perfectly honest I start getting lost pretty early on into the detailed stuff, especially when folks start quoting the big brains who invented all of it. I wish I had the time to really read "design patterns explained" and one day I will, hopefully that will help.

  • 5 bri // Mar 4, 2009 at 2:03 AM

    I came to CF from a smalltalk background, DAOs and Gateways never felt right to me and fortunately I've mostly been in a position to avoid using them. Once I find something that works for me I tend to stick with it and I find FuseBox 5.5 and Transfer gives you MVC and easy db interaction and helps stop things getting so complicated you think your brain will explode.
  • 6 Brian Rinaldi // Mar 4, 2009 at 4:57 AM

    I think the key to this issue lies in ColdFusion's incredibly expensive object creation penalty. As you know, when you create arrays of objects it very quickly begins to cause a performance issue. I will check out the thread but I have always maintained that separation in part because I liked that my DAO dealt in objects while the Gateway in queries (since I think returning queries is still kind of a hack). I am truly hoping that CF9 will begin to resolve this issue which is the source of endless frustration to me (especially when trying to pass items back to Flex and take advantage of the auto type translation).

    Fwiw though, I never do 5:1 and I wonder if that isn't oversimplifying the issue (I can't even recall what the 5 would be honestly). The people doing straight 5:1 probably wouldn't be writing better OO without a Gateway. Despite the fact that I authored the code generator that often seems to perpetuate the problem a bit, much more thought goes into the objects and services I create than the 1 table:1 object (and n CFCs).
  • 7 John C. Bland II // Mar 4, 2009 at 7:10 AM

    I never liked that approach and am glad, as @cody noted, it is being discussed.

    I built a code generator that spits out CRUD for every table in my database. It is dynamic enough to allow custom queries or simple selects. Lately I've gone to using a controller to access them but that's as far as I'll go.
  • 8 Sean Corfield // Mar 4, 2009 at 8:27 AM

    5:1 = bean + dao + gateway + manager + controller for every table in the DB behind the app. Seen that over and over - very unpleasant.

    FWIW, I keep my single object methods and my aggregate query methods segregated by name: getObjByCriteria(criteria) for single objects, findObjsByCriteria(criteria) for aggregate queries. Both in my ConceptDataGateway (since one gateway object usually manages persistence of a group of related entities).
  • 9 Tony Nelson // Mar 4, 2009 at 9:14 AM

    I agree with Brian that separating the components based on return type (object vs query) can be a handy reminder. Hopefully with CF9+Hibernate we'll be able to combine the 2 into a single DAO and only work with objects, but I have my doubts...

    As for the 5:1 problem, it's not as bad as long as your components are built around a set of related entities and not just 5 components for every table.
  • 10 Sean Corfield // Mar 4, 2009 at 10:17 AM

    @Tony, well, that "handy reminder" was what I had in mind when I wrote the guidelines in 2003 but it was only intended to get people started - it wasn't meant to be followed slavishly. I had hoped that once people got a bit of OO under their belt in CF, that's start to question the guidelines (and I expected to be in a position to be able to keep updating the guidelines!).
  • 11 salomoko // Mar 4, 2009 at 10:42 AM

    "since I think returning queries is still kind of a hack"

    Could one explain why this is frowned upon in CFML?
  • 12 Sean Corfield // Mar 4, 2009 at 10:59 AM

    @Salomoko, Brian thinks you should be able to return arrays of objects, like you would with Hibernate in Java.

    CF's object creation is not (currently) fast enough to make that practical - 2,000 records in a query is fine, 2,000 objects in an array is "too slow".

    I take the position that query in CFML is already an abstraction and the language has a number of constructs that operate natively on queries. There are aggregate operations that are *harder* on arrays of objects than on native queries. Consider the built-in tags that take a query as an attribute - you cannot pass arrays of objects to those.

    So, whilst I'd *like* to see array of object be fast enough to use it for large recordsets, I think a lot else has to change in the language to make that worthwhile.
  • 13 Brian Rinaldi // Mar 4, 2009 at 12:21 PM

    @Sean @Salomoko - yes, I want to return arrays of objects in part because all of my CF work recently has interfaced with Flex and returning queries doesn't take advantage of the Object to VO type translation. So what happens is I end up converting the queries to typed structures but they aren't deep (as in I leave most of the composed elements out) whereby I still need to retrieve the full object whenever it is accessed. This all seems like a bit of a hack to me to get around a performance issue.
  • 14 salomoko // Mar 4, 2009 at 2:06 PM

    "I take the position that query in CFML is already an abstraction and the language has a number of constructs that operate natively on queries."

    @Sean, I *definitely* agree, I do not see a problem with returning a query object in itself. I think that's a perk of the language most languages don't have to offer... I also believe languages that don't natively support query beans (if you will) have to make up the lack of support with arrays...

    I say leverage CFML for what it is, rather than trying to mimic other languages DSLs...

    idunno :-\
  • 15 Sean Corfield // Mar 4, 2009 at 2:32 PM

    @Brian, yeah, the Flex integration thing is a bit of a pain - I hope Adobe address that. We (at Broadchoice) went with Groovy / BlazeDS / Spring / Hibernate for the back end to our AIR app and we get great performance. Then we built a CFML front end reusing the exact same Groovy-based model (services / entities etc).
  • 16 tony petruzzi // Mar 4, 2009 at 3:39 PM

    i never understood why people in the cf community adopted the 5:1 pattern. maybe the got all object crazy once cf could support objects, maybe they "thought" they were java programmers (their not), maybe they were just being too smart for their own good or maybe they were just being retarded.

    rails activerecord is the simpliest, most elegant and easy way to interact with a database. everything is contained in one class for you and it make switching between database platforms pretty painless.

    i've been saying for years that adobe, and now the cf advisory counsel, needs to come up with a solution for the object creation penalty. i know it's not the function or purpose of the advisory counsel, but their influence and backing would be extremely beneficial.
  • 17 Sean Corfield // Mar 4, 2009 at 3:56 PM

    @Tony, re: CFML Advisory Committee. We can help drive the language specification but not the vendor implementations (in terms of performance). Market forces will dictate that sort of thing. Adobe are very aware of comparisons between Java / ColdFusion / Railo / OpenBD in terms of object creation speed tho'...
  • 18 John C. Bland II // Mar 4, 2009 at 4:01 PM

    You know the funny thing is I used to feel like less of a CF developer around folks using 5:1. I outgrew that but it still seemed like you couldn't join the "secret society" until you were a 5:1'er. ;-)
  • 19 Adam Ness // Mar 4, 2009 at 7:08 PM

    I never quite understood why a query that returned a large number of rows should go in a different object than a query that returned a single row, thus all of my hand-coded DAOs have the bulk query functions built into them, and I never hand-code a DAO.

    However, what I do use occasionally is a "Report" or "Search" object, which I can inject ordering and filtering information into, and call a function on it to return results. This is usually separate from my DAO, since it often does Joins, subqueries and unions with other tables/information sources. I haven't really seen any documentation for this pattern, but I've found it to be very useful for generating reports and helping build user interfaces for data-mining. I never quite understood the reasoning for the Gateway object, but I suspect it was similar to my Report object.
  • 20 Jake Munson // Mar 4, 2009 at 10:56 PM

    @sean, you said "I sort of overestimated people's ability to think beyond the letter of the guidelines".

    I have written a few blog posts about what I'm about to say, but this is one of the reasons I have been known to rail against the OO community in general. Yes OO is a valuable tool. No, I don't believe that most people think outside of the box. When someone with a reputation like you, Sean, says something about OO, most of the rest of the OO "sheep" (in our little community) follow what you said.

    Let me pose some deep questions: are the base OO principles that we follow today the end of the story? Will we continue to find better ways to do OO as time goes on? Will we eventually develop/find some other fundamental programming paradigm that makes OO look like pencil and paper?

    I don't know the answer to any of these questions, but I think it's wise for the geniuses among us to continue to push the envelope, so to speak.
  • 21 Sean Corfield // Mar 5, 2009 at 12:21 AM

    "are the base OO principles that we follow today the end of the story?"

    Knowledge and best practices are always evolving so that's a a bit of a silly question.

    "Will we continue to find better ways to do OO as time goes on?"

    Of course! I've said early and often that I started doing OO in 1992 - yes, 17 years ago! - and I'm still learning, still improving and still adapting to changes in thinking about "what's best".

    "Will we eventually develop/find some other fundamental programming paradigm that makes OO look like pencil and paper?"

    I don't know. In some ways OO is a radical departure from previous thinking but in many ways it's just plain common sense - procedural programming was so far removed from "how the world works" that it's amazing we ever got any systems built!

    You also need to remember that COBOL was standardized as an OO language before C++ was standardized (much to the chagrin of some of us on the C++ Standards Committee). Some OO languages date back over 40 years now (but have never been standardized). Functional programming was much vaunted in the 80's as the "next wave" but it never became mainstream (although it still has a very solid following these days, e.g., Haskell). Declarative programming was another style that was very popular in the 90's but, again, never became mainstream (e.g., Prolog).

    The worst thing any programmer can do is assume technology is static and that they will eventually master it. Languages evolve. Technology evolves. Thinking evolves.
  • 22 Shawn Holmes // Mar 5, 2009 at 3:44 PM

    @tony

    ColdSpring certainly does not help the issue. A quick review of the reference PDF that comes with CS and you are already headed down the path of 5:1. Those CF developers looking to expand their OO knowledge and do so by embracing such a framework are inevitably going to spend more time focused on adhering to the implementation "guidelines" set forth in the docs, and less time considering the ramifications.

    We lept on Coldspring for that reason, and the fact that we were tightly integrating with a Java-service layer which (surprise!) uses Hibernate. Suddenly, any argument against arrays-of-objects falls to the wayside.

    Personally, I'm encouraged by this announcement, and plan to dig deeper.
  • 23 Sean Corfield // Mar 5, 2009 at 3:53 PM

    @Shawn, just to be clear: the ColdSpring *docs* are what you're complaining about here, right?

    ColdSpring itself has no bearing on the 5:1 problem (and, in fact, you'll have less work to do with ColdSpring if you have fewer services and data gateways).

    Again, the problem here is people slavishly follow "simple examples" and applying them to their own code without understand the principles.

    People really need to read more OO literature *outside* the CF world...
  • 24 Jake Munson // Mar 5, 2009 at 5:01 PM

    @Sean,

    I totally agree with all that you said (in response to my comment). Obviously, some of my questions I posed were rhetorical...however, I honestly believe that some of the "sheep" I mentioned earlier don't ever think about questions like this. You do, obviously. And I do, and many others do.

    But the sad thing (to me) is that most of the OO crowd (in my opinion) just reads books and follows whatever trend is hot at the moment. But this isn't unique to OO. The same thing happens in all walks of life, from the clothes we buy to the politics we believe in.
  • 25 Shawn Holmes // Mar 6, 2009 at 6:26 AM

    @ Sean

    Correct, *just* the documentation. What's funny is that on one page, there is a diagram that contains an explosion of DAOs and Gateways.

    Of course, CS itself isn't locked down to that model, and a new ref. guide certainly might do it wonders for the new-to-CS developer.

    You can add my vote to the "read more OO literature" motion.
  • 26 Jeff Battershall // Mar 20, 2009 at 3:14 AM

    About the object creation penalty - I would think that use of frameworks which persist DAOs and services would mitigate some of that. Are there other strategies to minimize the hit? Other than using fewer CFCs?
  • 27 Sean Corfield // Mar 20, 2009 at 11:20 AM

    @Jeff, yes, DAO/Gateway CFCs should be singletons and therefore cached. That has nothing to do with the issue tho'...

    Returning an array of CFCs (instead of a recordset query) is the expensive part.
  • 28 Sean Corfield // Mar 20, 2009 at 11:22 AM

    BTW, it's probably worth mentioning that Railo is about 3-4 times faster than CF8 at creating objects but even so, I'm not sure I'd want to create an array of 2,000 objects, even on Railo...
  • 29 Sean Corfield // Aug 24, 2010 at 11:08 AM

    A year and a bit later and I wanted to touch on my comment about functional programming. I said:

    "Functional programming was much vaunted in the 80's as the 'next wave' but it never became mainstream (although it still has a very solid following these days, e.g., Haskell). "

    Interestingly, functional programming seems to be having a massive resurgence these days, with Scala, Clojure, Erlang and F# all becoming more popular (and other, more niche functional languages also getting press).

    So, technology and the problems it solves have already evolved and changed the way quite a few people are thinking about software!
  • 30 Daniel Budde // Aug 25, 2010 at 6:32 AM

    How funny it is that you would post on this yesterday Sean and a year later at that, since I just started reading this post yesterday. So, I am not an OO sheep yet, as I am just getting into more OO with CF by trying to embrace CF9 ORM, AOP and MVC using Model Glue and ColdSpring, but I do have a real lack of understanding and before I move forward I want to fix this.

    First off, I would like to get a better understanding of the '5:1' and understanding the original idea of what should have been in each of the 5 (bean, dao, gateway, service, ?). Mainly, I have been reading a lot about these, but I still lack the understanding of what each ones function was supposed to perform. I understand each of these may not be the solution going forward (especially from your discussions above and because ORM probably removes some of the need for some of these objects). So, I guess my question for this part is, can any of you point me towards any posts/literature that explains the idea behind these? I'm hoping by asking this, this might help some others in my position so we do not become sheep.

    If any of you would like to recommend a model to follow for the architecture that I will be using, I'd be happy to point my ears at you and learn more.

    Any recommended OO books? I saw 'design patterns explained' mentioned above. Is this a good book to start with?
  • 31 Sean Corfield // Aug 26, 2010 at 3:19 PM

    @Daniel, the best thing I can do is point you at the Beans and DAOs and Gateways Oh My! chapter in the Adobe ColdFusion Anthology from Apress - or, if you have the original Fusion Authority Quarterly Update that contains it (Vol II, Issue IV "Do More Code Less!").

    That explains the ideas behind layered architectures and how different combinations of domain object (bean), data access layer (DAO or gateway) and orchestration (service, controller) lead to solutions with different trade offs in terms of maintainability and extensibility.