Proposed New Years Resolution: No More Gateways!
I’ve written and posted about this a number of times. In short, you are either displaying columns from the database directly or you have calculated attributes that need to be displayed. If you are only displaying columns directly from the database then you probably don’t need to use OO at all – a procedural design will be simpler, faster and just as maintainable. If you need to calculate displayed attributes then you should consider using an OO approach, encapsulating the calculation of the attributes using getters in your business object. If you take this approach then the need for the calculated attributes doesn’t magically disappear when you display more than one at a time so you need to either create a collection of business objects (expensive) or use an Iterating Business Object.
The only time you can justify using a Gateway in an OO app is if you have an object with no calculated attributes but very rich validations so you want to use calculated setters but standard getters. I can see how such applications could get away with a Gateway (and I can see that a fair number of simple web applications could fall into that category).
Oh, and I know the common wisdom is that you use a Gateway so you don’t end up with too many methods in your DAO. If you have too many methods, by all means break them out into another object, but having too many methods isn’t an excuse for passing around naked recordsets instead of well encapsulated business objects. Also, if you look at the cases where you have too many methods, it is often a function of reporting. Sorry guys, but the bad news is that your reports should NOT BE within the core business objects. A report on users or articles has completely different attributes and methods than the underlying business object. Feel free to have a UserReport.cfc with a UserReportDAO.cfc, but the user reports should NOT be in a UserGateway all mixed in with methods that return collections of users – it makes no sense from first principles of cohesion and the Single Responsibility Principle.
Gateways are training wheels for those of us making our way across the procedural-OO chasm, but their time as a "best practice" has come and gone. Sooooo 2006.
Any comments? Please skim the referenced articles (at least my CFDJ article) first and then post away :->


Too often, procedural code comes out terrible because folks misunderstand the 'alternate' use of CFCs as a mechanism to divide your system into layers, group similar code, and promote code reuse.
(I say 'alternate' in recognition of the recent trend in CF land to promote OO as the answer to nearly everything.)
Thanks for the comment! Good point. I think training wheels are a great way to learn how to bicycle, and I'm sure there are use cases where an experienced cyclist would be better off with four wheels instead of two.
I'm just making the point that Gateways aren't really OO and that if you have rich, calculated object attributes then getters are often required which means you must return collections of objects (or more performantly, an Iterating Business Object) rather than a record set.
Putting your queries for a given business object in a single file is certainly better than putting them into your views or elsewhere in your app, and for some use cases it is the right way to go. The concern I have is that historically Gateways were one of the default architectural components of "OO CF" and I just wanted to point out that such an approach isn't usually the best way to go to get the full benefits of OO in CF as your applications become more complex (in terms of your object attributes mapping less directly to your database table columns).
I'm one of those OO noobs making the leap, and I still don't feel comfortable ditching gateways as you suggest.
The main sticking point is that in the current app I'm working on, I need to do a query of queries on my recordset to obtain a subset of records, and it just makes more sense to leverage CF's ability to do that quickly than to write a bunch of code to loop over a collection of objects and determine the ones I need in the subset.
Maybe the answer is in the Iterating Business Object, I have no idea what that is...perhaps you can elaborate in a future post.
As for the IBO, here is one link that'll take you to others:
http://www.pbell.com/index.cfm/2006/7/15/Real-Worl...
Just search the blog for iterating business object and you'll find all the information you could be interested in!
As for QoQ, you could just add that functiuonality to an IBO and reload it and you get the benefits of getters and setters for very little additional complexity. Of course, if you don't HAVE any calculated getters, gateways will work fine.