Without UI events we’d be totally lost on the client-side — it is only via User Interface Events that we can know what the user wants to do. User-initiated events such as “click”, “mouseover” and “mousemove” are absolutely essential to upholding a user-centred experience and I want to make it clear that my quarrel is not with these types of events. Any event that gives us information about users’ intentions is a good event.
I feel that there are bad events too though — events that we feel we must utilise just because they exist — and we feel we must build into our APIs just because event-driven design dictates absolute submission to this way of thinking.
DOM mutation events
Every single time I’ve ever considered using a DOM-mutation event I’ve subsequently discovered that the problem can be better solved by re-architecting the codebase. The DOM2 mutation events aren’t well supported in less capable browsers but offer an interesting opportunity — to listen for document mutation such as attribute changes, node insertion and node removal.
This sounds cool and I’m sure your mind was buzzing with ideas when you first heard about these events, but have you actually encountered a situation where utilising these events is the only viable solution? If so, I’d love to hear it.
Programmatic events
This is where I lose all sense of comprehension. The premise is a mechanism that allows you to be notified when changes occur to your program — i.e. your objects, arrays and functions. I’m talking about the likes of Object.prototype.watch
, IE’s onPropertyChange
and a tonne of other new implementations (e.g.) that seem to perpetuate a dangerous disconnect of cogs that should be working together.
It seems pointless — it’s akin to starting your car, and then being notified by the car that you just started the car… an entirely redundant notification.
var a = abstraction.Array(1,2,3); a.push(4); // > Abstraction says: "You just changed the array" // > Me says: "OH RLY" |
Left hand, meet right hand!
Events exist so that processes outside the scope of your code can communicate with your code and let you know when certain things occur. Events typically operate up the abstraction chain — you listen for events from lower-level abstractions. I feel that the “outside the scope of your code” aspect is central to the whole concept of events and is why they make so much sense in a browser-scripting environment. The browser listens to events from the operating system and forwards certain events to the DOM where we can listen for them. It’s a simple fluid concept that works!
There’s a lot of hype surrounding event-driven programming/design at the moment and it seems that we’re approaching a risky threshold, where events are used just because they can be, and not because they should be.
If you’re creating an app, and it requires a great deal of client-side functionality, then you’re going to need to interface with the DOM to listen for events and apply certain changes. This is what JavaScript is all about. You write the logic layer of code (your own personal API) and then you write the implementation code that utilises the logic layer. You have authored two distinct layers of abstraction. That’s pretty much the gist of what we do.
What’s approaching, it seems, is an era of haphazard juggling of third-party scripts, multiple abstractions, multiple APIs and consequently, dozens of events. No need to write a consistently encapsulated logic layer — you can just bung these plugins/modules/classes into the app… To heck with maintenance, clean and consistent abstractions, intuitive APIs, self-documenting code and all sense of originality.
I’m not questioning events in general, and I will admit that they can be very helpful to make two scripts work together, but as I mentioned, I feel there’s a threshold where it becomes simply foolish…
Thanks for reading! Please share your thoughts with me on Twitter. Have a great day!
I think I understand your frustration. Events are definitely very powerful. Even the property update events can be very powerful, and is, I believe what powers all the bindable features in the FLEX framework. But that said, I can easily see events being abused.
On the server side, I often see event usage where I feel like it is just being use to be “used” and not necessarily because it make more sense. I love the idea of being able to “announce” things; but, when one object *should* know about another object, there’s not need to announce anything – you simply need to invoke methods.
Oh sorry – I read this post before I read the one you linked to regarding Microsoft. It looks like the stuff they are doing is similar to the stuff that FLEX does with their bindable features… I didn’t read the article yet, but saw the code snippet you linked to.
I recently tried to experiment with some data binding stuff, with FLEX as the inspiration. It is interesting, but I think people will lose a bit of the fascination when they realize that listening to data changes is only a *tiny* part of the battle. The real hurdle will be responding to those changes and smartly re-rendering the layout… which has nothing really to do with data binding at all.
Yes, exactly. That’s really the only reason why I take issue with this new event-driven frontier. Copious callbacks and events are all the rage now but eventually using it so much will become an anti-pattern. I just hope developers think carefully before jumping on (or off) the bandwagon.
I haven’t yet looked into the Flex framework, so I can’t comment on that, but I’d love to see some realistic demos of data-binding in languages like JS/AS — all the ones I’ve found so far are pointless… just console-logging when a piece of data is mutated.
I don’t want to chime in with little more than a “I agree”, but I’d generally agree that it seems like a bit much.
I suppose one could make an argument that objects firing events like “I was changed!” means you can write theoretically more modular code, because then Object A doesn’t need to be aware of Object B, so when A changes, B can just listen in, and A can remain un-coupled, but it seems to be little more than a theoretical argument with no real meaningful application.
I’ve been dabbling with the video tag and canvases lately for fun, and I have found that some non-UI events in that area are kind of nice. The video pops play and pause events, and while typically those actions are associated with user interaction, if a video is set to autoplay, there’s not any interaction at the outset, so having the video say “Hey, I’m playing now!” has been really handy. Given load times, there’s no real way I could just wait a predetermined amount of time for it and then say “Okay, we must be playing now”, and while it’d be easy enough to write a polling timeout, that feels kind of ugly.
It seems like it’s about knowing the right tool for the job, and being able to recognize that while one can do some neat things with events, it doesn’t mean they necessarily should, just like anything else we do.
@James,
Yeah, even with my experimentation, all I did was log that data was changed. Beyond that, you get into a much more complex world of, “Oh crap, data was changed… now what?”. And that, becomes a lot of work.
I know very little about FLEX; but, they do things like binding an ArrayCollection to a DataGrid; then, when the array data changes, the DataGrid *automatically* re-renders. This is done, in part, by data-binding. BUT, the really super powerful stuff – the re-rendering – has nothing to do with data binding at all really (form what I can break down). For the people coming from a FLEX world, I think the allure of “data binding” is that they are getting confused as to what does what.
@Brian,
Yeah, definitely there are great uses for non-UI events. Interacting with video players is a great one. I use to play with Flash and the video playback module in Flash has all kinds of timeline events that you can bind to.
While there are many ways to approach an application framework, none of them has been proven to be right or wrong, they’re all just different, with varying benefits and drawbacks.
With more native events in the browser, it becomes easier to implement an events-based application architecture pattern, which, while being just another way of doing things, might actually be preferable to some people.
Having recently experimented with events-based application architecture patterns myself, I can definitely see some benefits to that approach. For example, through DOM event bubbling (and ideally, capturing as well), ancestor and descendant elements can be “coupled” through only their hierarchical relationship, which can help to generalize and reduce code.
I’ve wrestled with this a lot. Event Oriented Programming is similar to Aspect Oriented Programming and shares many of its strengths and weaknesses. But fundamentally, people use event systems to enable multiple responses to a single event.
Here’s 2 examples I find all the time:
1. A representation of the data model is changed (ex: a file deleted).
There might be multiple representations of the same file on the page. With JavaScriptMVC, models use OpenAjax.hub to publish events. It’s possible for widgets on the page to listen for these events and act accordingly.
Doing this without OpenAjax would be rather annoying. Each widget would have to add a callback to some structure (which is effectively open ajax), or the response code would have to look up each widget and tell it what happened. All this is much easier by having the widget subscribe to “file.deleted” events.
2. Widgets triggering ‘change’ with their value.
In an app I am working on right now, there are toggle-able sections and other widgets that have some important UI state that needs to be saved between visits. I have all widgets triggering (w/ jquery) a ui.state.change event with their new value. I listen on the document for ui.state.change events and send updates to the server.
The great thing about this approach is that we can build any widget to produce ui.state.change events and it will automatically work.
I find that widgets triggering a “change” value is extremely common and useful. I also find having that making widgets respond to Activate and Select allows me to customize how they are used easier.
But all this said, it is very easy to take events too far.
The best use of non UI events I can figure out is building more un-coupled code implementing the observer pattern, which is great for companies or big frameworks.
I found very interesting this video from Nicholas Zakas:
http://developer.yahoo.com/yui/theater/video.php?v=zakas-architecture
The idea is to build a modular structure, where every module knows as little as possible of the surrounding environment.
But I agree that if you are one coder working on one project this sounds more as a waste of time and performance.
The thing about generalizations is, they are generally true.
I think, in general, especially at the scale of usual implementations in typical web pages, yes, you’re absolutely right.
Question is (and I don’t pretend to know the answer) using this proscription, could we create gMail or Google Docs or EBay or Amazon.com or things beyond mere-mortal scale? I’m not so sure.
Another consideration: when you code-crash in a mainline JS application, you’re likely scuppered. If you crash in a trigger implementation, trigger functionality aside, you’re likely fine. (Again, generalities…)
So I sense that, at-scale, or in systems built by composition (jQuery-UI being a convenient example) it’s hard to imagine not using custom events.
I’ve been thinking about this post, because I’m looking at writing some code that’ll involve an indeterminate number of widgets, which I’ll likely be storing references to in an array. There’ll then be another widget (not a parent, more like a controlling element of sorts) that’ll then take actions on a fairly tight interval that all widgets need to respond to.
If I’m thinking right (and I admit I very well could not be), if I use an array and iterate over it in some sort of loop/foreach fashion, and call a method on them to take their action, they would run sequentially, but if I notified them to update via some sort of triggered event, then the sequence of execution isn’t necessarily sequence in array (which doesn’t matter in this case), and also doesn’t block me from completing whatever I have to do in this controlling widget’s interval.
It seems like that’s one thing a non-UI-driven event gives me — the ability to kick off methods on an indeterminate amount of objects without having to wait for execution of all of its slave widgets. Given that this event has to happen on a fairly regular interval, it seems like an event-driven approach might be better, even though I am fully aware of what’s in my array and could just go down the list.
Am I think of this right? (I realize I’m speaking very vaguely, but I’m hoping it’s enough to be clear.)
In the same way that a UI event needs to update a data model (eg. the DOM, some backing array, etc.), sometimes the data model needs to update the UI, since not all changes come from the user (eg. an AJAX request is returned, a timer has ran out, etc). Also, please remember that callbacks and timeouts are event-driven programming.