Event-Driven Programming: Why?
Yesterday, we looked at some simple server code that is called by events generated on the client. We saw that the server returns an EVENT property in its response -- but that my example never uses it. Today, we're going to see how that is used -- and why I think EDP is a BigDeal(tm).
Let's look again at a method within a controller. This is the "quote" method of my "Mathomatic.cfc":
<cfset var str = StructNew()>
<cfset var display = "">
<cfset var randomQuote = variables.instance.quoteService.quote()>
<cfsavecontent variable="display">
<cfinclude template="../views/quote.cfm">
</cfsavecontent>
<cfset str['event'] = "quoted">
<cfset str['display'] = display>
<cfreturn str>
</cffunction>
You'll see that I've created an EVENT property with a value of "quoted". EDP works best where user interaction level is high -- typical of Web applications. The real power of EDP is the loose encapsulation of the architecture. Let me give an example.
You've completed development of your latest application, StockPsychic, which uses the well-regarded field of Guessology to determine stocks likely to rise. Your users can drill down on a stock to see statistics, make notes, purchase shares, etc.
Everyone loves it. But shortly after launch, your boss shows up at your office...
BOSS: Love it. Love it. Love it.
YOU: Wow, thanks! Is this when we talk about bonuses?
BOSS: Yeah, well, it's just this one thing. People are getting confused about HOW to use some of these features. So, if you could just add in context-sensitive help? That would be great...
YOU: Just "add it in"? Oh, boy...
But, you've written this app as an event-driven program. This, you realize, may just come in very handy. You can easily add in a question mark icon at the top right of your page. When users click on that, perhaps a lightbox-effect can provide them with the help they need.
By adding a module, ContextHelp, you can listen to specific events and respond to them. When something like "stockPurchaseScreenDisplay" is announced, you can load the help content associated with purchasing a stock. When the user clicks on the "HELP" icon, the information is ready to display. Note that, apart from that HELP icon, nothing else in your existing program has had to change. You've added functionality far more easily thanks to the loosely-coupled nature of event-driven programs.
Another example? Sure -- this is a real-world one. We created a web app for a rental company. They were very happy with the job, which, of course, makes me happy. But I was speaking with their president one day and he asked me, "How hard would it be for me to see when other users do things like convert quotes into orders, receive a return shipment from a customer -- that sort of thing?"
Just a little thinking pointed to adding in a RemoteEventListener module. The module could listen for "significant events" -- such as those things the president requested. When such events occur, the event (along with the person initiating the event and the time) are saved in an application-scoped array. A bit of JavaScript polls the server periodically for any updates and, finding some, places them in a list displayed on screen.
All I needed to do was write new code (as opposed to the dangerous undertaking of changing already-written-and-tested code. The only change that needed to happen was to add a "pod" onto the page that my RemoteEventListener could write to when updates occurred.
We built, tested, and deployed this new functionality in two days.
I'm excited about the possibilities of EDP. Is it a magic bullet? Of course it is not. But in many situations -- certainly the ones I find myself in -- it provides the ability to respond to customer needs quickly and without the high drama of introducing new bugs into old code.
Now, back to that EVENT property of the server's response. All methods in the controllers return an event. Typically, that event is nothing more than announcing that the requested action was performed successfully or, in the case of a problem, that the request failed. If you decide to try out EDP, you'll need to ensure that the callback method -- the one fired when the server returns a response, automatically announces the new event defined by the server's response.
Adopting EDP requires a switch in mindset from "I call methods directly on specified modules" to "I announce events -- though I have no idea of who might be listening or what they might do with that event."
I started this journey a couple of years ago. I made lots of mistakes as I was fully wrapping my mind around this new paradigm. I went down plenty of dead ends, exploring things that looked promising but ultimately turned out to be either inadequate or simply wrong.
Today, having arrived at a well-defined method for doing EDP apps, I marvel at how different the code I now write is even from that I wrote two years ago. JavaScript has become far more important; things like server frameworks far less.
Well, "bully for you", as a detractor of mine wrote recently describing my enthusiasm for JavaScript. His response, though snarky, has a point. It's good that I'm finding coding easier, clearer, more enjoyable. But in the larger context of writing software, the more important question is: What does this mean for the customer?
That is where I find EDP to be invaluable. I am able to respond to requests for changes, for new features, for continuing changes to the software -- and to do it in a way that preserves my existing code's integrity.
In the IT world, we developers suffer from an afflication. My friend, Brian Kotek, refers to it as "the new hotness". You can see this in the recent discussions over OO and ColdFusion. OO began as an idea, became a niche technology, then went on to becoming the dominant paradigm. In the process, developers were mislead into believing that adopting OO would solve all their problems. OO became de rigeur. And, of course, it does not solve all problems-- helpful though it can be in the hands of an experienced OO developer. It's good and natural for us to be excited over something that is both promising and new, but sobriety needs to temper our enthusiam, lest we decouple the promise of a technology from the real benefits it may produce.
I would hate for EDP to suffer the same fate. This is something that calls for thoughtfulness on the part of the developer. We need to explore this new landscape to see if it fits our needs and, if so, how best to implement it. We need to learn when it may be appropriate and when a different architecture is called for. We want to be mindful of techniques we discover and learn from the experience of others. Technology makes a good servant, but a bad master.
Still, all cautions being noted, I find EDP to be very exciting. I'd be very interested in hearing your ideas and any lessons you may have learned from your experience.


Eventually, there is so much logic being handled by the UI that a full-blown domain model within the client becomes a virtual certainty. In fact, on many projects, the client's model is larger than the server's, since it is not only implementing business logic but all the display logic as well.
How does this compare with large JS projects? Do you end up using or creating an MVC and/or OO based JavaScript system?
I came to think of the page as a canvas, onto which we place code. For the sake of our discussion, let's assume a single-page interface model -- something like an Admin section. On the initial load, the entire page may be populated from a single event. But different user interactions typically do not refresh the entire page, but update smaller portions of the canvas. (To keep things simple, we'll just omit the discussion of tabs -- although nothing fundamentally changes with them.)
Take the example of a user viewing a list of customers. Event: listCustomersDisplay. The Customers controller might include two view files: list.customer.cfm and list.customer.pgm.
All of the event handling code for list.customers.cfm is located on list.customers.pgm. Typically this is quite small. Its main responsibility is to intercept a click event on a customer and announce "itemCustomerDisplay". When it does so, it provides a "context" for the results to be displayed in. That context is typically a DIV element. So, if the tree is located in the DIV with ID of "x" and next to it is a DIV with ID of "y", the announcement would look like this:
$('a[href^=Customers/item].click(function(){
$.announce(
'itemCustomerDisplay',
{
context : 'y',
customerId : $(this).metadata('id')
}
);
});
Where is that event handler code located? If list.customers.cfm had the HTML rendering code in it, then list.customers.pgm has the event handling code for events related to that HTML.
What this means is that you're only every having to deal with a very small subset of all possible events for a very specific piece of code. This makes the code almost necessarily non-complex.
I have a feeling I did a VERY bad job explaining this, so feel free to comment/ask further.
I'm definitely not disputing the power that EDP can offer. That said, I think that complexity can be much higher in event-driven applications, but it is a different kind of complexity than people might be used to in non-EDP systems.
All of the loose coupling comes with a price: it can be very difficult to keep track of the application flow. When you get a system that can be announcing 1000 different events, it gets very hard to understand what happens when an event is announced. That's because any number of things could be responding. There are some ways to help with this, for example the Mate framework for Flex relies on an event map to handle event mediation. Of course, that comes with its own drawbacks as well.
There's no doubt that EDP can be a very useful approach to building an application, particularly a robust UI. But it's very important for people to recognize the new and potentially unfamiliar types of complexity that goes along with it.
The key to this program, though, is having individual, specific "pgm" files that JUST deal with a specific section of code. So, on a typical page, you might have several such "pods".
While I found that EDP both revolutionized and simplified my own coding, there are some that EDP will simply not fit into the way they think about development.
Anyhow, I hope I didn't repeat something Hal already mentioned, figured I would chime in and share my experience!