Defending the Gateway pattern in ColdFusion
In a few recent posts, there's been discussion of the validity and purpose of what's called the "Gateway" pattern in a ColdFusion application's object model.
To summarize the critique, it focuses on whether or not it's a good idea to use a pattern that often lets the details of a relational database model (in the form of a ColdFusion query) float up into your application tier.
That's a tough argument to counter because it sidesteps the nature of design patterns.
Instead of focusing on an implementation detail, let's look at the design forces, implementation, and consequences of using the Gateway pattern.
Design Forces
The design forces behind the Gateway pattern are a situation where your domain model needs to speak to an external resource without understanding its format or connection details.
Note that it has nothing to do with a relational model. It just so happens that many ColdFusion applications are data-driven, so we're often connecting to a resource (a relational database) that's external to our object model. Our object model has a need to connect to this resource without understanding its connection or implementation details.
Is it right that the messaging format between our object model and the Gateway implementation is a ColdFusion query? IMHO, sure. More often than not, a ColdFusion query is a fantastic way to show a set of data - a point that's validated when you notice how many other parts of the language (LDAP, email, cfhttp) use it to represent sets. If all you need to do is deal with a set, why force yourself to deal with the complication and overhead of "iterating business objects" and what not when it's not at all necessary?
Implementation
All the Gateway's reference implementation states is that a single Gateway class will know how to speak to an external resource, and that all other objects / applications will use this gateway instead of maintaining knowledge of the external resources implementation.
An example I've got sitting here on my MBP is an application that can use either a MySQL DB, MS SQL DB, or LDAP server to perform authentication. I declare a gateway interface that contains a single method: authenticate(user:User). Each implementation then knows how to perform authentication against either appropriate database tables or the LDAP server. Switching is a matter of updating a ColdSpring configuration file.
In one of the posts criticizing Gateway, it was suggested that higher order objects be used to represent its functionality, such as a Report object that may power an aggregate report or a list of object instances.
I think that's a higher level of architecture than is often necessary for a simple CRUD app, but if it is necessary, I feel the Gateway is both appropriate and an improvement - it should be used in conjunction with the report to abstract the reports data access from its own capabilities. For example, a QuarterlySalesReport's constructor could take an instance of ISalesGateway, an interface defining methods like getQuarterlySalesData(), regardless of whether it comes from a local database or an external provider like SalesForce.com.
Consequences
When Gateway is implemented, your domain model receives one-stop shopping for communication with an external resource (something that lives _outside_ happy object land).
Conclusion
95% of the time, in 95% of ColdFusion applications, that external resource is going to be a relational database. Whether or not that's appropriate for your application is your call - is the tradeoff of dealing with relationally-based sets (ColdFusion queries) one you're willing to make?
Whether or not it's a valid pattern to use is a moot argument - the implementation of the Gateway pattern, even when just to do a bunch of SELECT statements, satisfies its design forces and is therefore valid.
Personally, I love using the Gateway pattern and its distinction from DAO. It's simple, it's efficient, and it's rarely come back to haunt me. I see a few people in the ColdFusion spending a lot of time trying to get rid of queries to be more "pure OO," and I think a lot of this time could be better spent.


I definitely see a benefit to how the ColdFusion community has been using the Gateway pattern. I really appreciate you walking through an analysis of the pattern, I think it helps to shed light on the its use and purpose rather than it's implementation. In my blog post I was thinking more in the context of what I do at work, where refactoring systems (even our CF apps) has the potential to be a large initiative. Design by contract and OO practices are heavily employed which has a strong basis in forming dependencies between "boundary" classes using objects rather than data types like primitive values, structs, arrays, or queries. I think this practice is more geared for systems which have to live for possibly a few decades and scale relatively over time.
I think if a shop is going to take a more formal approach to software design for an application which has to fill a more enterprise need, then what I'm advocating is appropriate. That being said, if you are building applications which are being created with little maintenance in mind, you're probably right. Refactoring won't be that much of an issue anyway, so why put the extra work in abstracting out your domain if you can just as easily, and infrequently, refactor the calling class.
Good post man.
I listed your entry as part of the "discussion of the validity and purpose" of Gateway - not as critique. I liked your post. Sorry if that was muddy.
I agree 100% there is no such thing as a good or bad pattern - it's all use case driven. What I'd like to understand better is the "edges" of the gateway pattern. I use an IBO rather than a recordset so I can use the same smart getters for both single instances and collections of instances. I frequently need to generate apps where the properties don't match exactly to the columns in the DB and I find smart getters on an IBO to be a nice way to encapsulate that and (for my use case) a better match than putting all of the getter logic in Views or SP's or writing some kind of script that iterates through a recordset to create the calculated columns.
Just to re-ask the questions that to me are interesting aout the Gateway pattern (I'd like to really "get" the Gateway pattern and would love to see if people have different or the same answers to the following questions - or even their range of answers for different use cases and how they choose between them):
1. I want to get three items by ID (I want to edit the price of products 7, 12 and 14 on a single screen). DAO or Gateway? Why?
2. I want to delete using a filter (e.g. delete expired carts - all carts where lastupdated > a month ago). DAO or Gateway? Why?
3. If the Gateway returns a recordset and the DAO returns a bean, let's say you have a user with an Age property based on the DateofBirth column in tbl_User. In the bean returned by the DAO, you probably use getAge() to encapsulate the calculation (right?). If so, how do you display the Age for a list of users without replicating the logic elsewhere? (If you do replicate it, where do you put it, and if you put the calculation into the database, how do you handle the case where the calculation requires pulling from a web service or otherwise can't be implemented in SQL?)
For 1) and 2), I'll take the "it depends" answer. It drives me batty when people try to wrap design patterns in hard and fast rules like "should a DAO be used for use case X?"
For 3), I'd use dateDiff on the view side. I know that's a cop-out because your example was a simple one, but it makes my point: there are consequences to using ColdFusion queries as the messaging format for a Gateway, and it's part of the tradeoff of your specific implementation, not the pattern itself.
@Peter - As for your questions, my answers would be:
1) I would use the gateway because my getByAttributes() default method is perfectly designed for this type of thing (and returns an array of objects). Keep in mind this method simply calls getByAttributesQuery() and then converts the results to an array of objects, so if the situation called for a query, you could just call that method directly.
2) I agree it depends. In most cases though this also goes in my gateway. Why? Well because my DAO deals in objects (so I pass it a cart object and tell it to delete it) which doesn't nicely suit multi-object transactions (though it could be made to do so).
3) There is no hard and fast answer to this to me since there are multiple solutions that each have their own trade-offs: You could make your query return an age using SQL functions; you could handle it on the view; you could return an array of objects; or you could use your IBO. I think in this case you just use the solution that best suits your use case as you say.
OK, well that explains a lot! It drives me batty when people DON'T examine the rules of thumb they use to select a given collection of patterns for a given use case. In my experience, documenting and debating heuristics improves them - both as an individual and within a community. Guess it's just a matter of preferences.
As for 3, come on Joe, that is indeed a cop out. What if there are 7-8 calculated properties in each of 3-4 different business object where the average calculation is 20-30 lines of code and some of them are not amenable to moving to views or SP's in the db? How do you handle that?
Please send an example of something that needs 7-8 calculated properties where each requires 20-30 lines of code along with the use cases to meet and I'll try to factor it however I see appropriate. Should make interesting blog material / thought.
I've got a commerce app which generates e-commerce sites for Vets which comes pretty close to this as there are interrelating properties on a project basis for figuring out per pill pricing, whether to match pet meds pricing, system, project and product specific discounting rules and the likes, but it's proprietary, so can't provide the specs - sorry!
Also, I guess we have a different perspective. My goal is always to solve the general case for n-business objects each of which could have m-calculated properties of an arbitrary complexity - encoding the heuristics for the design patterns to use within my generator so I don't have to actually code the design patterns on a per project basis. It's the only way I have any chance of generating thousands of custom apps a year.
I'm confused. Your general comments sound like you're talking about the Adaptor/Facade pattern. Surely Gateway is precisely the special case of Adaptor that *does* specifically apply to relational table data? Can you provide a pointer to the reference implementation you mention?
@Peter:
In a recent thread on cfcdev, Sean Corfield sidestepped your #3 neatly by proposing that the DAO use the gateway to get its single record.
Yep, Sean does something similar to what I do. The only thing I'd like to see is some sample code as for the general case it seems to me that if I'm putting what is effectively smart getter type calculations somewhere, the most obvious place to put them is in the bean and to ask the bean to handle those calculations.
One of the reasons I started writing OO code was that when you start writing code to loop over a recordset to add calculated columns to it, if you have a number of different calculated columns that change, it can get messy pretty quickly if you're not very disciplined and I'd like to see what that kind of code might look like in the Gateway in the case where you have three or four non-trivial calculated properties.
The thing that works for me about an IBO (or a collection of objects - the IBO is at its heart just performance hack to provide a collection of objects without the instantiation cost - I can't imagine using an IBO in Java or Ruby) is that when I want to describe a calculated property, I just add a getWhatever() method to encapsulate that calculation.
I actually do something similar to what Sean does in the case where I need to return (say) a recordset or XML or JSON to a remote requester. Obviously I can't pass an IBO over the wire, so I set Response = MyIBO.asJSON() or MyIBO.asXML() or MyIBO.asRecordset(). Each method takes an optional property name list for the properties to return, and it takes care of looping through itself, calculating all of the calculated values and returning a nicely formed JSON, XML or recordset using the same custom getters as used for single records and lists in HTML front ends. It is extremely easy to work with, solves all my use cases, scales well . . . there may be a problem with the approach, but I honestly haven't come across it yet and I've generated about 50 projects using the technique over the last few months!
Your IBO is just an alternative message format for what's returned from your Gateway. The Gateway is what hides your object model from SQL - your IBO sounds like the message it gets back, an alternative to a ColdFusion query.
When I need to go from recordsets to arrays of beans and whatnot, I generally use an aspect-wrapped instance of the gateway that knows how to translate that's reusable across whatever entities I choose (it traverses graphs via metadata in <cfproperty> tags). When that won't suffice, I just write a listFooAsArray() method in the gateway.
@Jaime,
Gateway, Adapter, and Facade are all very similar patterns in that they provide the "one stop shopping" APIs for something more complicated. While they may have the similar looking outside interfaces, they're different in the design forces the aim to solve.
Gateway (the def I referenced is at http://www.martinfowler.com/eaaCatalog/gateway.htm...) exists to deal with things that aren't objects, such as relational databases.
Facade exists to simplify the interface to a larger collection of classes. For example, processing an order in an e-commerce system may require talking to multiple business classes - a payment processor, a notification subsystem, etc. Facade coordinates all this ook into a placeOrder() method.
Adapter exists to make one API take on the external interface of another. For example, you could write a LiteWire adapter for ColdSpring that made it so that you could use LiteWire's API but back it with ColdSpring (couldn't resist.)
@all,
I've always contained all of my SQL in my gateways, using something like Gateway.listByIdentifier(id:int) from my DAO. To me, this is part of meeting the problem Gateway solves: keeping knowledge of that external format (SQL, XML, SOAP, whatever RPC format is hot tomorrow) in a single place.
In the trivial case of the User example, I know that any code for concatenating FullName from FirstName and LastName or creating Age from DoB will be in User.getFullName() and User.getAge() respectively.
I know that the discount for a product will be calculated in Product.Discount(), and the customer specific pricing will be calculated in Product.CustomerPrice().
I just find it a REALLY useful way to organize all of the code for smart getters/setters, allowing them to apply to both a single record or a collection and to be used for both local and (via the asRecordset(), asXML() and asJSON() methods) remote method calls.
I'm still trying to understand how I'd implement the general case of an object with n-calculated properties (or if you want to be concrete, let's say three of them!) using the gateway. Are you using an aspect to perform transformations on the recordset that the gateway provides (I saw the word "aspect" and am trying to figure out if that's handling the calculated properties?)
In the past (pre-CFC), when I had a number of calculated properties, I had a function that would iterate over a recordset and call n-UDFs - one for each calculated property, and a general function that would handle the looping and adding of the calculated columns to the recordset. I just didn't love the structure of the code I ended up with as the mapping between the displayed properties and the persisted fields became more complex over time. How do you organize the code for your various calculated properties and (assuming they don't fit into a DB view/SP or a CF/Flex view) do they go in the Gateway? Do you have a post-processor in your Service method that does something like:
Recordset = whateverGatewayMethod()
CalculatedRecordSet = transform(Recordset)
cfreturn CalculatedRecordset
where transform loops through and delegates to various functions for calculating the various fields?
I'm actually finally determined to figure out HOW people are using gateways for collections of non-trivial business objects with rich "getter" calculations!
FYI, I do the same with my SQL, although I just happen to call the bean holding it all a DAO rather than a Gateway, but intent seems to be the same.
> In the trivial case of the User example, I know that any code for
> concatenating FullName from FirstName and LastName or creating Age
> from DoB will be in User.getFullName() and User.getAge() respectively.
That's nothing to do with an IBO - that's just writing a getter function, man. Nothing revolutionary - I'm not sure why it's worth a term like "rich getter" or pages of blog entries?
> (via the asRecordset(), asXML() and asJSON() methods)
It is not a good design decision to place knowledge of remoting protocols inside of business objects.
> I'm still trying to understand how I'd implement the general case of an
> object with n-calculated properties (or if you want to be concrete, let's
> say three of them!) using the gateway.
By following the KISS principal: if the ColdFusion query doesn't cut it and I need to use a set of business objects, I'll transform the recordset into an array of objects. How it gets there depends on the situation, but it often involves ColdSpring AOP around gateways.
My goal was to have a single approach for accessing all of my business objects to (a) minimize development time and (b) ensure that I wouldn't have to refactor the structure of an object should its getters become sufficiently complex over a time to warrant accessing the properties via getters.
I agree with you on point 2. I delegate the work to a protocol aware singleton that does the work, but I'm still playing with the design decision. At first I was just going to write an external method that operated on the business objects but that also smelt bad. I think in the end I'll probably decorate the business objects with a protocol aware extension, but I don't feel the pain right now, so I'll wait to fix it until I can't stand the stench :->
The array of objects is fine. I just needed a general solution and found in CF7 that wasn't consistently performant - hence throwing a few methods into my base business object and then being able to use a single consistent method for interacting with all of my business objects.
public void mySuperSmartWidgetHander( Long id ) {
NotificationService notificationService = NotificationService.getInstance();
if (!notificationService.isInitialized()) {
notificationService.initialize(ConfigurationService.getMailServer(),
ConfigurationService.getAdminUserEmail());
}
CashService cashService = CashService.getInstance();
if (!cashService.isInitialized()) {
cashService.initailize(ConfigurationService.getPoolSize(),
ConfigurationService.getExpirationLength());
}
boolean valid = superSecurity.checkCredentials(SessionManager.getCurrentUser(), id);
if (!valid) {
throw new SecurityException(?Invalid User?);
}
Widget widget;
boolean exists = cashService.exists(Widget.class, id);
if (exists) {
boolean valid = cashService.isValid(Widget.class, id);
if (valid) {
widget = (Widget) cashService.retrieve(Widget.class, id);
} else {
cashService.remove(Widget.class, id);
}
}
if (widget == null) {
widget = widgetService.getWidget(id);
widgetService.store(Widget.class, widget);
}
notificationService.sendObjectRetrievalNotification(SessionManager.getCurrentUser().getEmail(),
(Widget.class, widget.getId());
SessionService.setParameter(widget);
}
Yeah, there?s a lot going on up there, look at how this Widget handler can encapsulate security, caching, session management, etc! How about this:
public Widget getWidget(Long id) {
return widgetService.getWidget(id);
}
All of the intricate and possibly important functionality in the first method can easily be layered in on top of this simple widget getter, leaving us with clarity. There is no doubt about this method, it returns a widget. So does the first one, with a lot of extra crap to work through. If I want to go into details about the caching mechanisms in my app, I would like to do that in the caching service, no where else. I don?t want that code sprinkled all throughout my code, just to make each method seem smarter.
When I was learning Perl I think, I remember reading that it?s much harder to write simple code that it is to write complicated code. To strive for simplicity means better design, the ability to understand abstraction without over using it, understanding how to separate business concerns, and most importantly to KEEP IT SIMPLE.
I don't think avoiding anaemia is about mixing up concerns though. It's about rich getters/setters and telling objects rather than asking them. Persistence, notifications, caching and the like aren't (usually) the right things to put in your business objects, but getting, setting and (often) validating (via some kind of composed validation service/library) are.
Guess you *could* implement the validation using aspects - do you do that at all? Maybe advice before save() to validate??? But I think I'd want my validation rules within the business object - even if using a composed library for common classes of validation.
I just wanted to say that I prefer object collections (IBOs) over recordsets for consistency, which provides easier maintainability.
Rather than accessing an object property like such:
#object.getProperty()#
And then a recordset field like this:
#recordset.field#
I like to consistently use the following:
#object.getProperty()#
#recordset.getField()#
Secondly, I favor collections for the simple reason that I can establish relationships very easily like this:
<cfset objectA.hasObjects = objectCollection />
or something like that... my wife is rushing me out the door... had to rush through the last bit.