As a full-time GUI developer (Java/SWT) this is so true it hurts. I would love to see the actor model and/or functional reactive programming become main-stream in this space. The observer pattern alone is insufficient...
As a full-time GUI developer (Java/SWT) this is so true it hurts. I would love to see the actor model and/or functional reactive programming become main-stream in this space. The observer pattern alone is insufficient...
I made a language for teaching programming to kids that uses CSP as a basis for the GUI where each event is a channel, so I'm quite interested in any literature in this area.
A saner way is to implement an event bus and send update events to it letting the main thread update itself from the bus. Some frameworks do use this model but really, it would be much nicer if the language itself could do this.
First, the actor model need not imply a separate thread/process for each actor. It's quite possible and in fact common (in Scala's built-in actor library and various Java actor libraries) to run a very large 100k pool of actors in a pool of well under 100 threads. [1] So, the typical notion of having a single UI thread can mesh quite well with actors (just have the UI event loop pump each actor's event loop during idle).
Second, since actors process messages - which are conceptually the same as events - an actor has messages pushed to it by widget(s) upon user interaction. (If this sounds identical to the observer pattern, it's because it is). There's nothing interesting about this step other than the "an event is a message" concept.
Third, and this is the really neat part, actors often involve some concept of blocking on a receive() call - which is an inversion of control from the observer pattern. That is to say an observer/listener is invoked by the UI framework when an event occurs, but an actor, which conceptually has its own message/event loop, can consume events at will. Thus the inversion of control.
So your classic listener looks like this:
// Added via $("#foo").click() or some such...
function onClick(e) {
// do something ... any state must be stored external to this callback
}
But an actor looks like this: // The event loop is started up and pumps indefinitely...
function loop() {
// any state is local
while (running) {
switch (receive()) {
case ....
}
}
}
The event loop in an actor can easily turn into a very tight and explicit state machine. [2] My event loop here is pretty boring, but consider, if after receiving event A, you explicitly block on receive for event B.I posted [2] a while back and there was a decent discussion at http://news.ycombinator.com/item?id=2972581. The section 5 of [2] really describe the idea neatly.
Hope that helps. Please let me know where I left things fuzzy.
1. Actors That Unify Threads and Events - http://lamp.epfl.ch/~phaller/doc/haller07coord.pdf
2. Deprecating The Observer Pattern - http://lamp.epfl.ch/~imaier/pub/DeprecatingObserversTR2010.p...