Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
I am the chief technical officer at InVision App, Inc - a prototyping and collaboration platform for designers, built by designers. I also rock out in JavaScript and ColdFusion 24x7.
Meanwhile on Twitter
Loading latest tweet...
Ben Nadel at the New York ColdFusion User Group (Mar. 2008) with:

Global Events vs. Entity-Bound Events In JavaScript Application Architecture

By Ben Nadel on

The more I try to learn about JavaScript application development, the more I tend to think that absolute decoupling is a myth. I know I'm quite inexperienced when it comes to building non-trivial, thick-client applications; but, the idea of being able to simply "assemble" an app using recycled components strikes me as being very suspect. While this may work for inconsequential apps, I can't wrap my head around this working for anything with a complex feature-set.

A lot of this frustration comes from the concept of event binding. I simply don't believe in "global event" types. Meaning, I don't believe an event type has implicit meaning without a context. In the same way that a "submit" event type has no meaning unless it is bound to a specific Form object (in a standard HTML page), I don't see how any published event type can be useful unless the subscriber knows specifically which entity announced the event in the first place.

It is for this reason that I am beginning to believe that all events should be bound at the entity level. When I learn about things like Signals (one Object per event type), something about the enforced structure feels very satisfying. Binding event listeners at the entity level, however, does mean that two independent components need to be linked using either direct references or some kind of third part "conscious" entity.

In either case, you are left with a situation where coupling exists. Either the two modules know about each other and changes in one might precipitate changes in the other; or, a third entity needs to facilitate decoupled communication in which changes in either module may precipitate changes in the facilitator.

In both of these cases, you need to have objects that are aware of each other's functionality. And, once you're in that situation, it seems that you can more easily rely on direct method invocation for certain forms of communication. Rather than having to worry about keeping everything completely decoupled, you can leverage an informed, 3rd part entity to translate events on one object into direct API method calls on another object.

This is all a bit of stream-of-consciousness, so take it with a grain of salt. But, this line of thinking does stem from an ongoing frustration with event binding in modular applications; while I thoroughly like the philosophy, I am having serious mental blocks when it comes to practicality.

The battle for understanding continues!




Reader Comments

I don't have anywhere near your experience in these areas, Ben, so I am likely describing something that you've considered long ago. But the way I am trying to approach it is to think of the event and the object *type* as a bound construct of sorts.

So for instance you have a submit event and a form object. So the event might be submitForm(). This event expects certain parameters to be provided by all form objects that call it. Now if you have some other type of object that does submits, let's call it Widget, you might have a different event there, submitWidget(), with its own parameters. Perhaps both these events inherit from a global submit() event which handles shared functionality when appropriate.

So I agree that it's probably not true decoupling, but it does separate the event from any *specific* object.

This is just how I've been trying to think about it, and I'm pretty new into this so I may be going down a bad path, but I thought I'd at least throw it out there.

@Gary,

I claim no good experience here :D Like I try to explain to people, I know things at a "technical" level; but when it comes to bring lots of ideas together in a good way, I'm still pretty inexperienced at that.

I think what you're describing is in alignment with much of what I've read in terms of event-based communication. And, it seems crazy for me to even begin to think that the loads of really bright people who talk about this stuff don't know exactly what they're talking about.

But, something about it just "feels" bad in my gut. I can't articulate it any better than that at this point. Really, I need more experience.

@Drew,

I definitely like the Callbacks. I don't know the ins and outs of it yet (as far as the configuration options go); but, it seems cool. I played around it a bit in my previous post on the "one object per event". In Addy's article, he had something similar with "Topics".

But, when the rubber meets the road, that just lays the foundations for event binding; it doesn't implement or require any larger structure for event management. You could use Callbacks to create a global event system; or, you could use it to create Signal-type event systems.

I'll have to do some experimentation with a combination of specific event beacons and API invocations... gotta wrap my head around this stuff!

I also gotta re-read Addy's articles; he's been absolutely prolific lately!

@Ben,

What opened my eyes about pub/sub and reusable parts was Ali Ozer's talk "Fundamentals of Cocoa" from waaay back in 2004. It was a WWDC talk, only 1:13 long. In that short period of time, he hand coded a surprisingly flexible "Dot App" in Objective C. It initially just displayed a big blue dot. Then he made the dot track mouse clicks and drags. Then he got into the pub/sub:

He hooked up a slider control to the size of the dot in Xcode's Interface Builder using drag-and-drop. Then he hooked up a color well the same way. In a manner of minutes, he had a dot that tracked mouse clicks and drags, with user controllable size and color!

It was that hookup of on-screen controls to data structures that made my jaw drop. (New term, "drag-and-jaw-drop".) He also presented the virtues of MVC and getters/setters at the same time. The drag-and-drop simply answered the question: "What data structure in memory do I want to control with this on-screen control?" (I followed along with that presentation to create my very first Xcode project, calling it "AliOzerDotApp".)

It's my understanding, though I haven't played around with it yet (don't quote me), that Dashcode does the exact same thing for html and JavaScript. (The "SproutCore" library? Something like that.) Of course, Dashcode was written long before jQuery, so in that sense, jQuery's catching up to what pub/sub can do in other environments.

I guess what I'm trying to say is, assembling an app using recycled components shouldn't strike you as suspect. I know for a fact that it works. I've done it, though not yet in html/JavaScript.

@WebManWalking,

Good point. I did over-speak a bit. Clearly, we all re-use widgetry all the time, whenever we make use of native HTML controls (ex. checkbox, select, etc.). In the litttttle bit that I've played with Flash, I've also been able to make use of their native widgets for things.

Of course, we have to keep in mind that the Flash library is like hundreds of thousands of lines of code that do a lot to make widgets very flexible.

That said, I guess where I was going with this was not so much the re-using of widgets; more so, it was the belief that widgets can just be plugged in and have them work. Going to your Dot App example, you couldn't just put in the slider and have it automatically control the dot. Someone / something had to say, *this* data coming out of this widget had to be piped into *that* widget.

The thing that says "this goes into that" has be explicitly coded; otherwise they're be chaos! Chaos! :D ... and, if a second slider was added (so that one controlled height and the other controlled width of the Dot), then the dot itself would have to be completely altered to function in the context of two, independent sliders (even if they are same widget - duplicated).

Sorry if none of that made any sense :)

I recently finished a web app (client side consumer, not server implementation needed) built with an Event Emitter structure (specifically based on Event Emitter 2). The problem you raised very quickly presents itself when trying to build an entire app structured around event emitting, as you immediately see the requirement to attach more semantics to the existing event sources.

Ultimately what you're saying is that there needs method of translation. The translator could be a central clearinghouse as you said, or tight coupling between modules acting as the translation. Ultimately what you really want is a defined language. This quickly brings to bear the last 3 decades of computing in general because this is the same problem that's been tackled over and over.

The entirety of the Win32 API is basically an enormous implementation of the best solution to your problem. It's an immense vocabulary that can be looked up programmatically and then used to translate data and meaning between otherwise completely disparate programs, implemented entirely using event emitting and message passing. There's plenty of examples of this but Windows is the most vast example of it I know off the top of my head. Indeed, many of the largest victories for Windows from the developer uptake end came directly from this system's relative ease in addressing these problems. Once you get past a certain minimum point of complexity, the ability to successfully decouple becomes the entire limiting factor for additional functionality.

@Ben,

> Someone / something had to say,
> *this* data coming out of this
> widget had to be piped into
> *that* widget.

That was the drag-and-drop. That step was no coding at all. Of course, the receiving data element had to be right -- slider controls a float, color well controls a color -- so there had to be coding to define the MVC model. So in that sense, yes, there was SOME coding. But the hookup itself was from a drawing window on the left, where you positioned the slider, onto the text of the proper data item in a window on the right. Xcode did the rest. You don't get much closer to "no coding at all" than that.

Modern day Xcode contains the Core Data framework, allowing you to use a graphical editor to define your data model in entity-relationship diagrams. But you still have to type in the names of the data items. (Marisa Tomei voice near the end of My Cousin Vinny: What a frickin' NIGHTMARE!)

P.S.: I didn't mean to give the wrong impression about Ali Ozer's video. It's one hour and 13 minutes, not one minute and 13 seconds. And there seems to be some singer with lots of videos on YouTube these days, also named Ali Ozer. Who knew THAT name collision would occur! They need to namespace themselves. Apple:Ali Ozer, not Singer:Ali Ozer.

It depends, also, on what the parts are. Every language since the 70's, if it wanted to be a serious tool, instead of just a toy, needed a way to address code reuse. Heck, even Logo had a concept of modules. I like playing a lot with graphical toys. My code reuse has ended up being about a simple vector3d class, which holds an {x,y,z} and provides the essential interaction set. Whenever I want something in 'space' going at a certain velocity, thats a vector for the coordinate, and a vector for the velocity, and I don't have to keep on proving to myself that the vector class works. Another is the cubeTree class, which holds items in three dimensions in a sparse fashion, so you can insert and retrieve in n log n times. Still another is the camera object, which transforms a div into a pair of canvas elements, and attaches generic tools that you'd want to have on a viewpoint into space. It's all about the generality of the 'things' that you built previously. If they are well thought out, then it won't *feel* like undue coupling. Of course a camera has a pan(x,y) method!

Don't build cars and expect them to be reused... build Legos!

@Brandon,

I don't know too much about the Event Emitter 2 API. Is that what the Event Emitter in node.js is using? I've played around with the EventEmitter class in node and rather enjoyed it. I like that jQuery 1.7 is now using terms like "on" for binding.

I've heard of Win32, but I never actually knew what it was. I just assumed it was part of the Windows Operating System (and that is as far as my thinking went). It does all seem to come down to coupling, like you say. And, where that coupling happens probably depends on how complex things are?

In my coding, I like to always use object that have constructor functions (as opposed to object literals). This allows me the opportunity to invoke the constructor and pass-in the more highly coupled object references.

@WebManWalking,

"Who knew THAT name collision would occur!"

Ha ha, word up! I get that all the time. Sometimes, I'll try to look up an old classmate or something and they are impossible to find because they have the same of some pop singer (who I've never heard of)... goes to show how little I know about pop culture.

As far as the drag-n-drop data binding, I believe FLEX had a lot of that stuff also. But, with FLEX, I think you actually see the code that gets generated (though I could be mistaken). However, even if something is simply hooking one data supply up to another object as a data source, there is code somewhere that is doing this *explicitly*.

I don't *think* you ever have a data source (ex. an array collection) that randomly emits CRUD events and have some completely decoupled data consumer (ex. data grid) listening for randomly "item-added" events. Rather, I *believe* you will always have a data consumer listening to CRUD events on a *specific* data source. Which is really the big point I am wrestling with.

@Justin,

I definitely agree with you that modularity is awesome! I'm 100% on board with that (though, I'll admit that when I want to get small things / proofs-of-concept done fast, I tend to code junky-monkey). I think you can build modules with excellent, reusable APIs. And, I think that those modules can also emit events for communication. The only issue I start to take is when one module listens for events dispatched by another module (without either of those modules "knowing" about each other). That just seems odd.